I'm in my 1st year of faculty and I have this homework:
Write a program that reads n arrays of characters and concatenates them into another dynamically allocated array. Repeat the operation as many times as the user desires.
After each displaying of the result, the allocated memory is freed.
And that is what I did:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
int main()
{
char** p, * v;
int n, m;
printf("\n\t enter the number of the arrays : \t");
scanf("%d", &n);
printf("\n\t enter the maximum lenght of the arrays :");
scanf("%d", &m);
p = (char**)malloc(sizeof(char) * n);
for (int i{}; i < n; i )
p[i] = (char*)malloc(sizeof(char) * m);
char t = 'Y';
while (t == 'Y')
{
size_t z = 0;
printf("\n\t enter your arrays :");
for (int i{}; i < n; i ) {
scanf("%s", p[i]);
z = strlen(p[i]);
}
v=(char* )malloc(z * sizeof(char));
for (int i{}; i < n; i )
if (i == 0)
strcpy(v, p[i]);
else
strcat(v, p[i]);
if (v) {
puts(v);
free(v);
}
if (p)
for (int i{}; i < n; i )
free(p[i]);
printf("\n\t wanna continue ? (Y/N)");
scanf("%d", &t);
}
}
When I want to free the memory to use again, I get a "head corruption error" from the debugger.
Any idea why?
CodePudding user response:
Allocation size mistake
Code allocated the wrong size. p
is a pointer, not a char
.
Cast not needed either.
char** p;
...
p = (char**)malloc(sizeof(char) * n); // Bad
Size to the tpye of the referenced object. It is easier to code right, review and maintain than attempting to code the matching type.
p = malloc(sizeof *p * n); // Good
...
p[i] = malloc(sizeof *p[i] * m);
Robust code would also check for errors.
if (scanf("%d", &n) != 1 || n < 0) {
fprintf(stderr, "No numeric input or negative count\n");
// Perhaps exit here.
}
p = malloc(sizeof *p * n);
if (p == NULL && n > 0) {
fprintf(stderr, "Allocation failed\n);
// Perhaps exit here.
}
CodePudding user response:
I get warnings, maybe I forgot some checks (malloc/scanf).
I hope I helped you even though I’m a beginner.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stdbool.h>
struct cstring {
char* data;
size_t size;
};
bool create_cstring(struct cstring* const object, const size_t size) {
return (object->data = calloc(size, sizeof(char))) ?
(object->size = size 1U) :
(object->size = 0U);
}
bool destroy_cstring(struct cstring* const object) {
free(object->data);
object->size = 0U;
}
struct cvector_string {
struct cstring* data;
size_t size;
};
bool create_cvector_string(struct cvector_string* const object, const size_t size) {
return (object->data = calloc(size, sizeof(struct cstring))) ?
(object->size = size) :
(object->size = 0U) ;
}
void destroy_cvector_string(struct cvector_string* const object) {
free(object->data);
object->size = 0U;
}
int main()
{
struct cvector_string cv = { NULL, 0U };
// Allocations
{
// Allocate n arrays of chars
{
size_t cv_n = 0;
printf("\n\t Enter the number of the arrays : \t");
scanf("%zu", &cv_n);
if (!create_cvector_string(&cv, cv_n)) {
fprintf(stderr, "Error : Bad allocation\n");
return 1;
}
}
// Allocate arrays of n chars
{
size_t cv_m = 0;
printf("\n\t Enter the maximum lenght of the arrays : \t");
scanf("%zu", &cv_m);
for (struct cstring* it = cv.data; it != cv.data cv.size; it) {
if (!create_cstring(it, cv_m)) {
fprintf(stderr, "Error : Bad allocation\n");
return 1;
}
}
}
}
struct cstring r = { NULL, 0U };
{
char cont = '\0';
do {
/* Initialize arrays of chars, calculate the length of the resulting string
* and create the resulting string */
{
size_t length_sum = 0;
for (struct cstring* it = cv.data; it != cv.data cv.size; it) {
scanf("%s", it->data);
length_sum = strlen(it->data);
}
if (!create_cstring(&r, length_sum)) {
fprintf(stderr, "Error : Bad allocation\n");
return 1;
}
}
// Initialize and concatenate the resulting string
{
strcpy(r.data, cv.data[0].data);
// or using destination = strcpy(malloc, source), same for strcat
for (struct cstring* it = cv.data 1; it != cv.data cv.size; it) strcat(r.data, it->data);
}
// Print and deallocate the resulting string
puts(r.data);
destroy_cstring(&r);
// Prompt to continue
printf("\n\t Wanna continue? (Y/N) ");
scanf(" %c", &cont);
} while (cont == 'Y');
}
// Deallocations
{
// Deallocate all the arrays of chars
for (struct cstring* it = cv.data; it != cv.data cv.size; it) destroy_cstring(it);
// Deallocate the array of arrays of chars
destroy_cvector_string(&cv);
}
}
Errors :
- You’re freeing the allocated memory for character arrays and then reading into that memory.
Deallocating
for (int i{}; i < n; i )
free(p[i]);
Using
for (int i{}; i < n; i ) {
scanf("%s", p[i]);
z = strlen(p[i]);
}
You have to allocate memory for pointers, not allocate memory for characters.
p = (char**)malloc(sizeof(char) * n);