Разбить строку на слова - C (СИ)
Формулировка задачи:
здравствуйте, помогите разобраться.
задание: вводится строка произвольной длинны. нужно сформировать несколько новых строк. в каждой строке должно содержаться одно слово.
вот мой код:
у меня это дело работает так:
Я не понимаю откуда мусор берётся в новых строках. ЧЯДНТ?
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
void clear (char *q){
int i=0;
for(; i<strlen(q); ++i) *q='\0';
}
char *trim(char *str){
const char *p;
char *q;
int l;
q = malloc(strlen(str)+1);
strcpy(q, "");
for (p=str; *(p+=strspn(p, " \t")); p+=l){
l=strcspn(p, " \t");
if (*q) strcat(q, " ");
strncat(q, p, l);
}
q = realloc(q, strlen(q)+1);
return q;
}
char *obtain_data(char *q){
int n=0;
char *q1;
char *str=malloc(strlen(q)+1);
clear(str);
printf("Put some text here:\n");
do{
n=scanf("%10[^\n]", q);
if (str[0]=='\n') strcpy(str, q);
if (str[0]!='\n'){
str=realloc(str, strlen(str)+strlen(q)+1);
strcat(str, q);
}
clear (q);
} while (n!=0);
str=trim(str);
q1=malloc(strlen(str)+1);
strcpy(q1, str);
free (str);
free (q);
return q1;
}
int findword(char *q){
int i=0, k=0;
for(; i<strlen(q)+1; ++i){
if (q[i]==' ') break;
if (q[i]=='.') break;
++k;
}
return k;
}
char* cut (char *r, char *q){
int l=strlen(q), len=0;
char *q1;
char * f = strchr(q, ' ');
len=findword(q);
r=realloc(r, len+1);
strncpy(r, q, len);
q1=malloc(l-len);
strncpy(q1, f+1, l-len-1);
clear (q);
q=realloc(q, l-len);
strcpy(q, q1);
free (q1);
return r;
}
/*void defrag (char* q){
планируется сделать цикл из cut()
}*/
int main() {
int k=0; char* c=malloc(101);
char *buff=malloc(11);
buff=obtain_data(buff);
c=cut(c, buff);
printf ("%s\n%s\n", c, buff);
getch();
}Решение задачи: «Разбить строку на слова»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 50 //длина буфера для слова
//в русском влезет: тысячадевятьсотвосьмидесятидевятимиллиметровый
//в английском влезет: Supercalifragilisticexpialidocious
//записываем текст в файл посимвольно, попутно считаем длину
int lenOfSentence()
{ int cur = 0;
char c;
FILE *f = fopen("sentence.txt","w");
if(f == NULL)
{ printf("Scusi, temporary difficulties finding room for your sentence\n");
getchar(); exit(1);
}
printf("Put your sentence. Press ENTER' at the end:\n");
do
{ c = getchar();
if(c!= '\n') fputc(c,f); //убираем ENTER
cur++;
} while (c!= '\n');
fputc('\0',f); //добавляем символ конца строки
fclose(f);
return cur; //возвращаем длину текста в файле
}
//считываем текст из файла в динамическую строку заданной длины
char *veryLongString(int len)
{ char *sentence;
FILE *g = fopen("sentence.txt","r");
if(g == NULL)
{ printf("Scusi, temporary difficulties reading your sentence\n");
getchar(); exit(1);
}
sentence = (char*) malloc (len);
fgets(sentence,len,g);
fclose(g);
return sentence;
}
//проверка: является ли символ знаком препинания
int inDelimiters(char c)
{ int i;
char delimiters [] = {' ','.',',','-',':',';','!','?'};
for(i=0;i<8;i++)
if(c == delimiters[i])
return 1;
return 0;
}
//укоротить текст на слово слева
char *cutSentenceByWord(char *sentence, char* word)
{ int i,cur;
cur=strlen(word);
while(inDelimiters(sentence[cur]))
cur++;
char *cut = (char*) malloc (strlen(sentence) - cur);
for(i=cur;i<strlen(sentence);i++)
cut[i-cur]=sentence[i];
cut[i-cur]= '\0';
return cut;
}
//////////////////////////////////////////////////////////
int main()
{ char word [N];
int len = lenOfSentence(); //вводим текст, подсчитываем его длину
char *sentence = veryLongString(len); //создаем строку с текстом
printf("\nWords:\n"); //разбираем на слова
while(strlen(sentence)>0)
{ sscanf(sentence,"%s",word); //считываем слово как набор символов до пробела
if(inDelimiters(word[strlen(word)-1])) //если захватили и знак препинания справа
word[strlen(word)-1] = '\0'; //убираем его
printf("\t%s\n",word);
strcpy(sentence,cutSentenceByWord(sentence,word)); //срезаем текст на найденное
//слово слева
}
flushall(); getchar();
return 0;
}
Объяснение кода листинга программы
- Объединение всех строк в одну переменную sentence с помощью функции fgets.
- Проверка на отсутствие знаков препинания с помощью функции inDelimiters.
- Функция cutSentenceByWord для разделения предложения на слова.
- Использование функции sscanf для чтения слова из строки.
- В цикле while происходит чтение слов из строки и их вывод на экран.
- Если последнее символ в слове является знаком препинания, он удаляется.
- После вывода слова, функция cutSentenceByWord используется для удаления этого слова из строки sentence.
- В конце программы используется функция flushall и getchar для очистки буфера ввода.
- Программа возвращает 0, что означает успешное завершение работы.