Условие while(scanf("%s", str) != EOF)
является потенциально бесконечным l oop, это прекратится только в том случае, если вы загрузите в программу сигнал EOF
через командную строку.
Для одной строки, которая содержит все слова, которые вам понадобятся для перераспределения памяти при каждом чтении, чтобы увеличить пространство памяти, в котором сохраняется строка.
Вы можете сделать что-то вроде этого:
Live demo
#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
}
Ограничения: не может быть пробелов после последнего введенного слова для завершения цикла.
Теперь, если вы хотите двумерный массив, подобный структуре, динамически выделяемый не только для самих слов, но и для указателей, указывающих на эти строки, вам понадобится нечто более особенное, тройной указатель.
Думайте об этом как об указателе на массив строк, это то, что вам нужно в качестве аргумента вашей функции, чтобы сделать изменения постоянными в вызывающей функции, в данном случае в основной функции.
Li ve demo
#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
}
Ограничения: не может быть пробелов после последнего введенного слова для завершения цикла.
Обратите внимание, что там является дополнительным уровнем косвенности из-за того, что эти назначения выполняются через аргументы функции, если бы они использовались на месте или возвращались функцией, вам понадобился бы только простой указатель в первом примере и двойной указатель во втором примере.