Разбиение строки на слова - C (СИ)
Формулировка задачи:
Хочу разбить сроку на отдельные слова. Вроде разбивается, но когда вывожу, слова которые меньше или равны 3 символам выводятся хорошо, а вот которые больше с какой-то плохой штукой. Перед тем как использовать буфер чищу, но все равно ничего хорошего не дает.
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#define n 100
struct words
{
char *wrd;
};
words slova[n];
int main()
{
char string[255],*pos_point;
printf("Enter a string ");
gets(string);
strcat(string," ");
int number=0,i,to=0,from=0;
for (i=0;i<strlen(string);i++) //Поиск количество пробелов в строке.
{
if (string[i]==' ') number++;
}
for (i=0;i<number;i++)
{
slova[i].wrd = (char*)malloc( sizeof(100) );
memset (slova[i].wrd, 0, sizeof (slova[i].wrd));
pos_point=strchr (string,' ');
strncpy (slova[i].wrd,string,pos_point-string);
to=pos_point-string;
memmove(string + from, string + from + (to+1), strlen(string + from + to) + 1);
}
for (i=0;i<number;i++)
{
printf("\n%s %d ",slova[i].wrd,strlen(slova[i].wrd));
}
getch();
}Решение задачи: «Разбиение строки на слова»
textual
Листинг программы
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
char *duplicate_string(const char *str)
{
char *result = malloc(strlen(str) + 1);
if(result != NULL)
strcpy(result, str);
return result;
}
#define ENSURE(TEST, LABEL, FMT, ...) \
do \
{ \
if(!(TEST)) \
{ \
fprintf(stderr, "%s:" FMT, \
errno, #__VA_ARGS__); \
goto LABEL; \
} \
} while(0)
int main(void)
{
char buf[BUFSIZ], **words = NULL, *pch;
const char *delims = " ";
size_t actual_size = 0, actual_limit = 0, rank = 0, i;
int ret = EXIT_FAILURE;
printf("Enter words separated by spaces: ");
fflush(stdout);
fgets(buf, BUFSIZ, stdin);
ENSURE(buf != NULL, read_err, "%s", "read words");
if((pch = strchr(buf, '\n')) != NULL)
*pch = '\0';
for(pch = strtok(buf, delims); pch != NULL; pch = strtok(NULL, delims))
{
if(actual_size == actual_limit)
{
char **temp;
temp = realloc(words, (actual_limit = 1 << rank++) * sizeof *words);
ENSURE(temp != NULL, words_err, "%s", "allocate memory for words");
words = temp;
}
words[actual_size] = duplicate_string(pch);
ENSURE(words[actual_size] != NULL, words_err, "%s", "allocate memory for a single word");
++actual_size;
}
for(i = 0; i < actual_size; ++i)
printf("%s\t%d\n", words[i], strlen(words[i]));
ret = EXIT_SUCCESS;
words_err:
for(i = 0; i < actual_size; ++i)
free(words[i]);
free(words);
read_err:
exit(ret);
}
Объяснение кода листинга программы
- Включаем необходимые заголовочные файлы:
, , , - Создаем функцию duplicate_string, которая выделяет память под строку и копирует в нее исходную строку. Если память не может быть выделена, функция возвращает NULL.
- В функции main() создаем буфер для чтения строки, указатель на слова (массив указателей на строки), указатель на разделитель (пробел), переменные для отслеживания размеров массива слов и строки, а также переменную для отслеживания статуса чтения строки.
- Запрашиваем у пользователя ввод строки, разделяя ее на слова и сохраняя их в массиве words.
- Если во время выделения памяти или чтения строки произошла ошибка, выводим сообщение об ошибке и завершаем работу программы.
- Выводим на экран список слов и их длину.
- Освобождаем память, выделенную под слова, и завершаем работу программы.