I'm writing a function that needs to:
Get a full sentence from the user
Dynamically assign for each word a memory block that can contain it
Copy it to it and save the address to the * words pointer array
I wrote a loop that in each iteration gets a word from the sentence the user inserted, but I can't Dynamically allocate it properly. This is what I have:
char str[50];
while(scanf("%s", str) != EOF)
{
int len = strlen(str);
char *words = (char*) malloc((len+1)*sizeof(char));
}
I also need to make sure that:
If the function succeeds, it returns the number of words entered.
If memory allocation fails the function returns -1.
The condition while(scanf("%s", str) != EOF)
is a potencial infinite loop, this will only stop if you feed the program with EOF
signal through the command line.
For a single string that hodls all the words you are going to need to reallocate memory at every read to increase the memory space where the string is saved.
You can do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ret_words(char **words) { //double pointer argument
char str[50];
char *temp = malloc(1); //first allocation required
int count = 0;
if(temp == NULL){ //allocation error
return -1;
}
do{
temp = realloc(temp, strlen(str) + strlen(temp) + 2); //reallocate space on
//each iteration
if(temp == NULL){
return -1;
}
count++; //count words
} while (scanf("%49s", str) == 1 && strcat(temp, str) //scan str and append to temp
&& getchar() != '\n' && strcat(temp, " ")); //with spaces between
*words = temp; //assign temp to words
return count; //return word count
}
int main() {
int ret;
char *words; //pointer to the array of strings
puts("Enter the string");
putchar('>');
ret = ret_words(&words); //returned number of words on success, -1 on error
printf("Inputed string: %s\nNumber of words: %d", words, ret); //test print
}
Constraints: There cannot be any spaces after the last inputed word for the cycle to conclude.
Now, if you want bi-dimensional array like structure, dynamically allocated not only for the words themselves, but also for the pointers that point to those strings you will need something a bit more special, a triple pointer.
Think of it as a pointer to an array of strings, this is what you need as an argument of your function in order to make the changes permanent in the caller function, in this case, the main function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ret_words(char ***words) { //triple pointer argument
char str[50];
int count = 0;
char **temp = malloc(sizeof *temp); //allocate a pointer to pointer to char
if(temp == NULL){ //allocation error
return -1;
}
do {
temp = realloc(temp, (count + 1) * sizeof *temp); //reallocate space at every scan
if(temp == NULL){
return -1;
}
temp[count] = malloc(strlen(str) + 1);
count++;
} while (scanf("%49s",temp[count - 1]) == 1 //scan str and append to temp
&& getchar() != '\n'); //with spaces between
*words = temp; //assing the allocated array of pointer to the argument
return count; //return word count
}
int main()
{
char **words; // pointer to pointer to navigate the array of strings
int ret;
puts("Enter the string");
putchar('>');
ret = ret_words(&words); //returned number of words on success, -1 on error
for(int i = 0; i < ret; i++) //print each stored one word string
printf("Word %d: %s\n",i + 1, words[i]);
printf("Word count: %d", ret); //print the number of words
}
Constraints: There cannot be any spaces after the last inputed word for the cycle to conclude.
Note that there is an extra level of indirection due to the fact that these assignments are made through the arguments of the function, if they were to be used in place or returned by the function you would only need a simple pointer, in the first sample, and a double pointer in the second sample.