Имена файлов передаются через параметры функции main()
Есть текстовый файл содержащий русские и латинские слова. Нужно оставить в нем только те фразы, в которых содержится не менее трех слов. Имена входных файлов передаются программе при ее запуске через параметры функции main(). Если параметры при запуске программы не заданы, имена файлов вводятся с клавиатуры. Предложения может располагаться на нескольких строках, разделяются точками, а слова - пробелами, знаками препинания и символами строки. В конце файла фраза может быть без точки.
Вроде код рабочий, но переписывает до какого-то определенного момента и завершается, не могу понять в чем проблема. Еще так понимаю не правильно передаются параметры через функцию main(). Буду признателен, если поможете.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int simb(char *);
int main(int argc, char *argv[])
{
system("chcp 1251");
FILE * f1, * f2;
char c, fname, str[1000], file1[50], file2[50]="t.txt";
int len=0, i=0;
while (((f1=fopen("f.txt","r"))==NULL))
{
printf("name file: ");
fname=fgets(file1,sizeof(file1),f1);
if(((f1=fopen(file1,"r"))==NULL)) puts("Error");
}
if ((f2 = fopen("t.txt","w")) == NULL)
{
puts("Error");
system("pause");
}
// как-то так надо передавать или по другому?
/*if(argc>2){
strcpy(f1,argv[1]);
strcpy(f2,argv[2]);
} else {
strcpy(f1,"f.txt");
strcpy(f2,"t.txt");
*/}
do
{
c = fgetc(f1);
if((c=='.')||(c==EOF))
{
*(str+len) = (c=='.')?'.':' ';
*(str+len+1) = '\0';
if(simb(str))
{
fputs(str,f2);
puts(str);
}
len=0;
}
else
{
*(str+len)=c;
len++;
}
}
while(c!=EOF);
fclose(f1);
fclose(f2);
remove("f.txt");
rename("t.txt","f.txt");
return 0;
}
int simb(char *str)
{
int i=0, a=0;
while(str[i]!='\0')
{
if((str[i]==' ')||(str[i]==',')||(str[i]==':')||(str[i]==';')||(str[i]=='-'))
{
a++;
}
i++;
}
if(a<3)
return 0;
a=0;
return 1;
}
Ответы (1 шт):
Вы неправильно считаете количество слов в фразе, почему-то предполагаете, что слова разделены ровно одним разделителем и после последнего слова в фразе тоже должен быть разделитель.
Для подсчета слов нужно отслеживать состояние in_word т.е. текущий символ относится к слову или нет. При переходе от разделителей (пробелы, знаки пунктуации) к другому символу, состояние меняется и счетчик слов увеличивается.
Вот пример такого кода:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define IS_DELIM(c) (ispunct(c) || isspace(c))
int
main (int ac, char *av[])
{
char f1_name[1024], f2_name[1024];
if (ac < 3) {
puts("Enter file names:");
if (!fgets(f1_name, 1024, stdin) ||
!fgets(f2_name, 1024, stdin))
perror("get files\n"), exit(1);
f1_name[strlen(f1_name) - 1] = 0;
f2_name[strlen(f2_name) - 1] = 0;
} else {
strcpy(f1_name, av[1]);
strcpy(f2_name, av[2]);
}
printf("input: `%s` output: `%s`\n", f1_name, f2_name);
FILE *in = fopen(f1_name, "r");
if (!in)
perror(f1_name), exit(2);
FILE *out = fopen(f2_name, "w");
if (!out)
perror(f2_name), exit(2);
int lim = 1000;
int in_word = 0;
int n_words = 0;
char *str = malloc(lim + 3);
if (!str)
perror("malloc"), exit(3);
int len = 0;
for (;;) {
int c = fgetc(in);
if (c == '.' || c == EOF) { // end of phrase
if (n_words > 2) {
if (c == '.')
str[len++] = c;
str[len] = 0;
fputs(str, out);
}
if (c == EOF)
break;
n_words = 0;
len = 0;
in_word = 0;
continue;
}
if (len > lim)
if ((str = realloc(str, (lim *= 2) + 3)) == 0)
perror("realloc"), exit(3);
// accumulate symbols of current phrase and calculate number of words in it
str[len++] = c;
if (!IS_DELIM(c)) {
if (!in_word)
n_words++; // first character of the word
in_word = 1; // now state is 'in the word'
} else // delimiter found, now current state is 'not in the word'
in_word = 0;
} // end for (;;)
fputs("\n", out); // for nicer output, because the last phrase outputs without '\n'
fclose(out);
return puts("End") == EOF;
}
О возможно незнакомых пока вам функциях (ispunct, isspace, malloc, realloc, exit, perror) прочтите в manpages (например, man ispunct (можно набивать в поисковой строке гугла))
P.S.
Вот фрагмент кода без malloc/realloc, как вы просили в комментарии
....
int in_word = 0;
int n_words = 0;
char str[10000];
int lim = 9998;
int len = 0;
for (;;) {
int c = fgetc(in);
if (c == '.' || c == EOF) { // end of phrase
if (n_words > 2) {
if (c == '.')
str[len++] = c;
str[len] = 0;
fputs(str, out);
}
if (c == EOF)
break;
n_words = 0;
len = 0;
in_word = 0;
continue;
}
if (len > lim)
fputs("Phrase too long, exited...\n", stderr), exit(3);
// accumulate symbols of current phrase and calculate number of words in it
str[len++] = c;
if (!IS_DELIM(c)) {
if (!in_word)
n_words++; // first character of the word
in_word = 1; // now state is 'in the word'
} else // delimiter found, now current state is 'not in the word'
in_word = 0;
} // end for (;;)
....