Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> текстовые файлы 
:(
    Опции темы
шарлотта
Дата 18.4.2017, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Здравствуйте! В текстовом файле требуется определить в каждой строке количество слов, длина которых больше 4. Вывести количество найденных слов и сами слова. Удалить из файла строку, в которых таких слов меньше всего.Если таких слов нет - оставить файл без изменений.
void CountDelete(FILE *f, FILE *g) {
    int i, j = 0, len = 0, count = 0, num_line_min, cur_num_line = 0, count_min = 1.0e+10;
    char line[100];
    char word[100];
    char buf[100] = {'\0'};
    bool key = false;
    f = fopen("first.txt", "r");
    while (fgets(line, 100, f) != NULL) {
        for (i = 0; i <= strlen(line); i++) {
            if ((line[i] != ' ') && (line[i] != '\0') {
                word[j] = line[i];
                len++;
                j++;
            } else {
                if (len > 4) {
                    word[j] = '\0';
                    count++;
                    buf[strlen(buf)] = ' ';
                    strcat(buf, word);
                }
                word[0] = '\0';
                len = 0;
                j = 0;
            }
            if (line [i] == '\0') {
                if ((count < count_min) && (count != 0)) {
                    key = true;
                    count_min = count;
                    num_line_min = cur_num_line;
                }
                strcpy(buf, buf + 1);
                printf("count = %d\n  ", count);
                if (count != 0) {
                    puts(buf);
                }
                cur_num_line++;
                count = 0;
                buf[0] = '\0';
                fflush(stdin);
            }
        }
    }
    if (key == true) {
        printf("count_min = %d\n ", count_min);
        printf("num_line_min = %d\n ", num_line_min);
        cur_num_line = 0;
        fseek(f,0L,SEEK_SET);
        while (fgets(line, 100, f) != NULL) {
            if (cur_num_line != num_line_min) {
                fputs(line, g);
            }
            cur_num_line++;
        } 
//и после этого удалить старый файл и переименовать новый
    } else {
        puts("Нет слов, длиннее 4");
    }
    fclose(f);
    fclose(g);
}
Определение нужной строки неверно работает при определении последнего слова(если я верно понимаю, из-за того, что после идет пробел) и при работе с несколькими строками. Во второй файл ничего не пишет. Не могу разобраться, как исправить ошибки. Большое спасибо за помощь!

Это сообщение отредактировал(а) шарлотта - 18.4.2017, 00:21

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  текстовые_1.png 957,54 Kb
PM MAIL   Вверх
шарлотта
Дата 18.4.2017, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Так при работе с несколькими строками

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  текстовые_2.png 811,99 Kb
PM MAIL   Вверх
rudolfninja
Дата 18.4.2017, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



Как-то у вас тяжело код написан.
Поместите между соответсвующими тегами и было бы здорово, если бы вы добавили комментарии к каждой логически обособленной части функции.
По делу сразу могу сказать, что я бы еще на вашем месте проверял line[i] на  '\n', а не только на '\0', как признак конца строки.
PM MAIL Skype   Вверх
шарлотта
Дата 18.4.2017, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Код

void CountDelete(FILE *f, FILE *g) {
    int i, j = 0, len = 0, count = 0, num_line_min, cur_num_line = 0, count_min = 1.0e+10;
    char line[100];
    char word[100];
    char buf[100] = {'\0'};
    bool key = false;
    f = fopen("first.txt", "r");
    while (fgets(line, 100, f) != NULL) { //пока в файле есть информация, читаю строки
        for (i = 0; i <= strlen(line); i++) { //прохожу по строке
            if ((line[i] != ' ') && (line[i] != '\0') { //если не пробел и не конец строки
                word[j] = line[i]; // пишу символ в word
                len++; //увеличиваю длину
                j++; //увеличиваю счетчик (проще, наверно, будет использовать len)
            } else { //если пробел или конец строки
                if (len > 4) {//если длина слова > 4
                    word[j] = '\0'; //добавляю символ конца строки
                    count++; //увеличиваю счетчик- количество слов длиннее 4 символов
                    buf[strlen(buf)] = ' '; //все подходящие слова буду записывать в строку.добавляю в строку пробел для разделения слов
                    strcat(buf, word); //присоединяю к строке слово
                }
                word[0] = '\0'; //обнуляю слово
                len = 0; //обнуляю длину
                j = 0; //обнуляю счетчик
            }
            if (line [i] == '\0') { //если конец строки
                if ((count < count_min) && (count != 0)) { //если количество подходящих слов меньше минимального, но не равно 0
                    key = true; //ставлю ключ
                    count_min = count; //минимальное кол-во равно посчитанному
                    num_line_min = cur_num_line; //запоминаю номер строки, которую надо будет удалить
                }
                strcpy(buf, buf + 1); //так как в начале строки есть пробел, удаляю его
                printf("count = %d\n  ", count); //вывожу количество слов
                if (count != 0) { //если такие слова есть
                    puts(buf); //вывожу строку с этими словами
                }
                cur_num_line++; //увеличиваю номер строки
                count = 0; //обнуляю кол-во слов
                buf[0] = '\0'; //обнуляю буфер
                fflush(stdin);
            }
        }
    }
    if (key == true) { //если есть строка с минимальным количеством слов, но большим 0
        printf("count_min = %d\n ", count_min); //вывожу минимальное количество слов
        printf("num_line_min = %d\n ", num_line_min); //вывожу номер строки
        cur_num_line = 0; //обнуляю счетчик строк
        fseek(f,0L,SEEK_SET); //помещаю указатель на начало файла
        while (fgets(line, 100, f) != NULL) {//пока есть информация, считываю строки
            if (cur_num_line != num_line_min) { //если строка не является строкой с минимальным кол-вом нужных слов
                fputs(line, g);//пишу строку в новый файл
            }
            cur_num_line++;//увеличиваю счетчик строк
        } 
//и после этого удалить старый файл и переименовать новый
    } else {
        puts("Нет слов, длиннее 4"); //иначе вывожу сообщение, что таких слов нет
    }
    fclose(f);
    fclose(g);
}


Это сообщение отредактировал(а) шарлотта - 18.4.2017, 18:51
PM MAIL   Вверх
rudolfninja
Дата 18.4.2017, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



В вашем случае слово может заканчиваться и на '\n', а не только на пробел и на '\0'
PM MAIL Skype   Вверх
шарлотта
Дата 18.4.2017, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Сделала так.
Код

void CountDelete(FILE *f, FILE *g) {
    int i, len = 0, count = 0, num_line_min, cur_num_line = 0, count_min = 1.0e+10;
    char line[100];
    char word[100];
    char buf[100] = {'\0'};
    bool key = false;
    f = fopen("first.txt", "r");
    while (fgets(line, 100, f) != NULL) {
        for (i = 0; i <= strlen(line); i++) {
            if ((line[i] != ' ') && (line[i] != '\n') && (line[i] != '\0')) {
                word[len] = line[i];
                len++;
            } else {
                if (len > 4) {
                    word[len] = '\0';
                    count++;
                    buf[strlen(buf)] = ' ';
                    strcat(buf, word);
                }
                word[0] = '\0';
                len = 0;
            }
            if (line [i] == '\n') {
                if ((count < count_min) && (count != 0)) {
                    key = true;
                    count_min = count;
                    num_line_min = cur_num_line;
                }
                strcpy(buf, buf + 1);
                printf("count = %d\n  ", count);
                if (count != 0) {
                    puts(buf);
                }
                cur_num_line++;
                count = 0;
                buf[0] = '\0';
                fflush(stdin);
            }
        }
    }
    if (key == true) {
        printf("count_min = %d\n ", count_min);
        printf("num_line_min = %d\n ", num_line_min);
        cur_num_line = 0;
        fseek(f,0L,SEEK_SET);
        while (fgets(line, 100, f) != NULL) {
            if (cur_num_line != num_line_min) {
                fputs(line, g);
            }
            cur_num_line++;
        } 
    } else {
        puts("Нет слов, длиннее 4");
    }
    fclose(f);
    fclose(g);
}

Мне кажется, теперь ошибка в том, что не обнуляет buf. При выводе второй строки соединяет часть предыдущей и новую.

Это сообщение отредактировал(а) шарлотта - 18.4.2017, 22:46
PM MAIL   Вверх
xvr
Дата 18.4.2017, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Код

                    buf[strlen(buf)] = ' ';
                    strcat(buf, word);
Первый оператор затрет завершающий нуль в buf, а второй допишет к получившейся строке неизвестной длинны нечто. Результат непредсказуемый.

PM MAIL   Вверх
rudolfninja
Дата 19.4.2017, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 341
Регистрация: 19.2.2013
Где: г. Минск

Репутация: 1
Всего: 6



В общем, вот рабочий вариант. Я не знаю, что пишется в файл, но слова выводит верно для каждой строки:
Код

void CountDelete(FILE *f, FILE *g) {
    int i, len = 0, count = 0, num_line_min, cur_num_line = 0, count_min = 1.0e+10;
    char line[100];
    char word[20] = { '\0' };
    char buf[100] = { '\0' };
    bool key = false;
    f = fopen("first.txt", "r");
    while (fgets(line, 100, f) != NULL) {
        line[strlen(line) - 1] = '\0';
        for (i = 0; i <= strlen(line); i++) {
            if ((line[i] != ' ') && (line[i] != '\0')) {
                word[len] = line[i];
                len++;
            }
            else {
                if (len > 4) {
                    word[len] = '\0';
                    count++;
                    buf[strlen(buf)] = ' ';
                    fflush(stdin);
                    strcat(buf, word);
                }
                memset(word, 0, 20);
                len = 0;
            }
            if (line[i] == '\0') {
                if ((count < count_min) && (count != 0)) {
                    key = true;
                    count_min = count;
                    num_line_min = cur_num_line;
                }
                strcpy(buf, buf + 1);
                printf("in string '%s' words with length more than 4 symbols %d\n", line, count);
                if (count != 0) {
                    printf("they are: %s\n", buf);
                }
                cur_num_line++;
                count = 0;
                memset(buf, 0, 100);
            }
        }
    }
    if (key == true) {
        printf("count_min = %d\n ", count_min);
        printf("num_line_min = %d\n ", num_line_min + 1);
        cur_num_line = 0;
        fseek(f, 0L, SEEK_SET);
        while (fgets(line, 100, f) != NULL) {
            if (cur_num_line != num_line_min) {
                fputs(line, g);
            }
            cur_num_line++;
        }
    }
    else {
        puts("Нет слов, длиннее 4");
    }
    fclose(f);
    fclose(g);
}

Вы не правильно очищали массив, в котором было слово и буфер со словами, которые нужно вывести. word[0]='\0' не очищает весь массив, а только зануляет первый элемент, оставив остальные элементы неизменными. Получается, что вы накладываете слова друг на друга. Я очищаю массив с помощью функции memset.
Еще я решил, что лучше будет сразу заменить символ перевода строки ('\n') на символ конца строки ('\0') при чтении строки из файла:
Код

line[strlen(line) - 1] = '\0';

В общем, разбирайтесь. Если будут вопросы или что то не будет работать, пишите, завтра попробуем найти ошибку.
PM MAIL Skype   Вверх
шарлотта
Дата 19.4.2017, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Большое Вам спасибо! Попробую разобраться.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1307 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.