I'm a beginner programmer, I got a home assignment to seperate a string into words, and put each word in an array of strings. We are practicing dynamic memory allocations. the assignment says that the size of the array must be [10] and i need to change the size of the array with malloc accoring to the number of words in the string, and allocate room for every word in the array. when i reach the end of the programm and free the allocated memory it says "Project.exe has triggered a breakpoint" and i can't find my mistake in the code.
P.S this is my first question on stack so i apologize in advance if I posted wrong somehow.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fillArray(char string[], char* array[], int* pointer);
int countCharacters(char string[], int index, int* pointer);
void freeArray(char* arr[], int size);
void main()
{
char string[] = { "i have two dreams" };
printf("Your sentence is: %s", string);
int sentenceLength = 1;
for (int i = 0; string[i] != '\0'; i++)
{
if (string[i] == ' ') sentenceLength++;
}
int* point = &sentenceLength;
char* array[10];
fillArray(string, array, point);
printf("\n\nYour array is: \n");
for (int i = 0; i < *point; i++) puts(array[i]);
freeArray(array, *point);
}
void fillArray(char string[], char* array[], int* pointer)
{
*array = (char*)malloc(*pointer * sizeof(char));
if (array == NULL)
{
printf("--NO MEMORY--");
exit(1);
}
int i = 0;
int j = 0;
for (i; i < *pointer; i++)
{
array[i] = (char*)malloc(sizeof(char) * countCharacters(string, j, pointer));
if (array[i] == NULL)
{
printf("--NO MEMORY--");
exit(1);
}
for (j; string[j] != ' '; j++)
{
if (string[j] == '\0')
{
array[i][j] = '\0';
return;
}
array[i][j] = string[j];
}
if (string[j] == ' ' || string[j] == '\0')
{
array[i][j] = '\0';
j++;
}
}
}
int countCharacters(char string[], int index, int* pointer)
{
int size = 1;
if (string[index] == ' '&& index<= *pointer) index++;
for (index; string[index] !=' '&& string[index]!='\0'; index++)
{
size++;
}
return size;
}
void freeArray(char* arr[], int size)
{
for (int i = 0; i < size; i++)
{
free(arr[i]);
arr[i] = NULL;
}
}
"the assignment says that the size of the array must be [10] and i need to change the size of the array with malloc accoring to the number of words in the string" ... "it says "Project.exe has triggered a breakpoint" and i can't find my mistake in the code."
There may be other issues in your code, but based on comments, the largest question you expressed has been the problem of allocating and freeing memory. The following addresses those points only.
This statement:
char* array[10];
Creates an array of 10 pointers to char
. In the context of your assignment parameter stated above this limits you to a maximum of 10 words in any given sentence. This fact appears to be in conflict with the assumption made in your statement need to change the size of the array with malloc according to the number of words. The dynamic allocation of each pointer will set the number of characters. (not number of words.). Because there are 10 pointers, there can be up to 10 calls to malloc()
, 1 for each pointer that you have created. But in your design, you will only make the number of call as there are words in your sentence, each allowing enough memory to accommodate each word
For example, "i have two dreams" has 4 words, requiring 2, 5, 4 and 7 bytes of memory respectively (accounting for an extra byte for null termination.) This will require 4 calls to malloc, each with a unique length value.
(Assuming _length_values below are being returned from your call to countCharacters(string, j, pointer)
include the terminating null, the following will use: length
Note that in your code, this first call to malloc
is not necessary:
*array = (char*)malloc(*pointer * sizeof(char));
And in the loop ( for (i; i < *pointer; i++)
) the call array[i] = (char*)malloc(sizeof(char) * countCharacters(string, j, pointer));
should be broken up into 2 separate calls to mitigate failed calls to countCharacters
:
in length = countCharacters(string, j, pointer);
if (length > 0)
{
array[i] = malloc(length);//cast and sizeof(char) are removed
...
Based on your selected sentence: "i have two dreams"
, there should be 4 calls, each containing a value for length corresponding to your precending call to countCharacters
array[0] = malloc(length); //2
array[1] = malloc(length); //5
array[2] = malloc(length); //4
array[3] = malloc(length); //7
This will create memory that can be expressed as:
Correspondingly, each one explicit call to free
needs to occur for each previously made call to malloc
Based on above, there should be 4 calls in this segment, but indexed accordingly:
for (int i = 0; i < *point; i++) puts(array[i])
^ removed ;
freeArray(array[i]);
^^^
Using a modified version of freeArray
void freeArray(char* arr[])
{
free(arr[i]);
arr[i] = NULL;
}