Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
veslogrebov
0 / 0 / 0
Регистрация: 06.11.2012
Сообщений: 9
#1

Работаю с файлом *.txt. Прога ведет себя странно если последняя строка файла пуста. Почему так? - C++

13.12.2012, 17:19. Просмотров 345. Ответов 1
Метки нет (Все метки)

Добрый день! Помогите пожалуйста с небольшой проблемой.

Что хотел сделать: Есть текстовый файл, в нем содержатся любые последовательности символов разделенные пробельными символами (пробелом, табуляцией).
Хочу сделать, без использования сторонних библиотек, класс, объекты которого принимают С-строку из этого файла и строят двусвязный список слов (1 элемент - 1 слово), игнорируя символы пробелов и табуляции.
И в общем то все сделал и все работает, но только если последняя строка в файле содержит хоть какие то символы.
Если же последняя строка файла пуста, у меня происходит лишняя итерация цикла, в результате которой до того, как я достигну конца файла, прога повторно выводит на экран последний объект.
Т.е. вот выполняется в main() этот код:
C++
1
2
3
4
5
 do{
        fgets(str, 1000, fp); //беру строку из файла
        Sentence S(str); // передаю строку в конструктор
        S.Show(); // вывод списка слов
    }while ( !feof(fp) ); // пока не достигнут конец файла
Последняя строка файла в конструктор не передается, S.Show() показывает последний созданный объект со списком заново, и только потом я достигаю конца файла. А как игнорировать такую пустую строку?

вот прога полностью:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <stdio.h>
#include <conio.h>
#include <locale.h>
#include <string.h>
 
const int SIZE = 1000;
const int WORDLEN = 50;
 
bool Whitespace (char c); // Проверяет является ли симовол "с" пробельным или NULL-символом.
 
class Sentence
{
private:
    struct Word
    {
        char wd[WORDLEN];
        bool isStopWord;
        
        Word *next;
        Word *prev;
    };
 
    int wordsAmmount; // Количество слов в строке
 
public:
    Word *Begining;
    void Show();
    Sentence(char *str);
 
};
 
Sentence::Sentence(char *str)
{
    printf("Конструктор=================================\n"); 
    /* Проверим, есть ли вообще какие-либо слова в строке. 
    Если их нет, создаем особый тип объекта, содержащий один элемент списка c NULL символом в поле wd,
    с нулевым счетчиком слов wordsAmmount. */
    int size = strlen(str);
    bool empty = true;
    wordsAmmount = 0;
 
    int indexWordBegin = -1; // первая буква первого слова (если оно вообще есть) в строке
    for (int c = 0; c < size; c++)
    {
        if (!Whitespace(str[c]))
        {
                empty = false;
                indexWordBegin = c;
                break;
        }
 
    }
    if (empty) 
    { 
        Begining = new Word;
        Begining->prev = NULL;
        Begining->next = NULL;
        Begining->wd[0] = '\0';
        Begining->isStopWord = true;
 
        wordsAmmount = 0;
 
        printf("empty\n"); 
        return;
    }
 
    /* Если дошли до этого момента, значит строка не пуста. Создадим первый элемент списка, и сразу
    запишем туда первое слово (его первая буква сохранена в indexWordBegin) */
    Begining = new Word;
    Begining->prev = NULL;
    Begining->next = NULL;
 
    int indexWordEnd = -1; // Последняя буква первого слова
    for(int i = indexWordBegin ; !Whitespace(str[i]) ; i++)
    {
        Begining->wd[i - indexWordBegin] = str[i];
        indexWordEnd  = i;
    }
    Begining->wd[indexWordEnd - indexWordBegin + 1] = '\0';
 
 
    wordsAmmount++;
 
    // Проверим, не достигли ли мы конца строки
    if ( str[indexWordEnd+1] == '\0' ) return;
 
    /* Если не достигли конца строки, сканируем ее, находим слова, создаем для них новые элементы списка */
    Word *iTemp = Begining;
    int car; // сокр. carriage, общий указатель на символы строки
    while (1)
    { 
        for (car = indexWordEnd+1 ; Whitespace(str[car]) && str[car] != '\0' ; car++); // После всех итераций в car хранится индекс первой буквы следующего слова, либо символ конца строки.
        
        // Проверим, не достигли ли мы конца строки
        if (str[car] == '\0') return;
        
        // Значит car указывает на начало следующего слова. Создадим для него новый элемент списка.
        iTemp->next = new Word;
        iTemp->next->prev = iTemp;
        iTemp->next->next = NULL;
        iTemp = iTemp->next;
 
        // Запишем это слово в элемент списка
        for(int i = car ; !Whitespace(str[i]) ; i++)
        {
            iTemp->wd[i - car] = str[i];
            indexWordEnd  = i;
        }
        iTemp->wd[indexWordEnd - car + 1] = '\0';
 
        wordsAmmount++;
 
        // Проверим, не достигли ли мы конца строки
        if ( str[indexWordEnd+1] == '\0' ) return;
    }
}
 
void Sentence::Show()
{
    Word *iTemp = Begining; 
    while (iTemp->next != NULL)
    {
        printf ("%s \n",iTemp->wd);
        iTemp = iTemp->next;
    }
    printf ("%s \n",iTemp->wd); // вывод последнего элемента списка
}
 
int main()
{
    setlocale(LC_ALL, "russian");
 
    FILE *fp;
    fp = fopen("Text.txt", "r");
    
    char str[SIZE];
    do{
        fgets(str, 1000, fp);
        Sentence S(str);
        S.Show();
    }while ( !feof(fp) );
 
    getch();
    return 0;
}
 
bool Whitespace (char c)
{    
    // Функция проверяет является ли симовол "с" пробельным или NULL-символом. Если является - возвращает true
    // Коды пробельных символов:
    const int LF = 10;    // перевод строки
    const int CR = 13;    // возврат каретки
    const int SP = 32;    // пробел
    const int HT = 9;    // горизонтальная табуляция
 
    if (c == LF || c == CR || c == SP || c == HT || c == '\0') return true;
    else return false;
}
Вот тестовый файл Text.txt, должен лежать в корне проекта. Обратите внимание на 12-ю пустую строчку, из за нее все проблемы
C++
1
2
3
4
5
6
7
8
9
10
11
     aaaa!!!!    bbbb       cccc..
                dddd'd???? eeee
fffff
 
 
 
               
 
                    
                    
gggg                      hhhhhh            iiiiii
Вложения
Тип файла: txt Text.txt (147 байт, 1 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2012, 17:19     Работаю с файлом *.txt. Прога ведет себя странно если последняя строка файла пуста. Почему так?
Посмотрите здесь:

Почему программа себя странно ведет: зацикливается после ввода значений? - C++
Зацикливается после воода значений. Подскажите пожалуйста в чем может быть проблема. #include &lt;fstream&gt; #include &lt;iostream&gt; ...

cin странно себя ведет - C++
Здравствуйте! Если в самом начале в майне написать char tch; cin.getline(tch,32) То все Ок, работает как надо. Но в в мэйне...

класс string. Программа странно себя ведет - C++
Программа странно себя ведет. После первого ввода имени и номера сотрудника, пропускает последующие вводы имен, переходя сразу к номеру. ...

Как ведет себя cin, если пользователь вводит некорректные данные? - C++
Читаю C++ Primer Plus by Stephen Prata. В седьмой главе у него есть следующий пример. // lotto.cpp -- probability of winning ...

Почему так странно работает калькулятор - C++
Здраствуйте, я сегодня решил взяться за C++, решил написать самое простое, калькулятор: #include &lt;cstdlib&gt; #include &lt;iostream&gt; ...

Обьясните, почему код так странно считает факториалы - C++
Добрый день, ув. форумчане. Есть код, считающий факториалы:#include &quot;stdio.h&quot; #include &quot;windows.h&quot; __int64 factorial(__int64 n) { ...

Почему так странно находятся углы в сферической системе координат - C++
Добрый вечер! Вот краткая вырезка, которая меня и интересует. Всё по инфе из WIKI СФЕРИЧЕСКИЕ КООРДИНАТЫ. 1 Есть координаты точки и...

Непонятно почему ведёт себя так программа - C++
Задачка: //На шахматной доске 8х8 расположены три фигуры: ферзь, ладья и конь. //Требуется определить количество пустых полей...

Дана квадратная таблица a[1:n,1:n]. Переставить местами строки 1 и 2, 3 и 4 и т.д. Если n нечетно, то последняя строка остается на месте. - C++
помогите разобраться с пару задачками. 1)Дана квадратная таблица a. Переставить местами строки 1 и 2, 3 и 4 и т.д. Если n нечетно, то...

При чтении текстового файла дублируется последняя строка - C++
Всем доброго времени суток, мне нужно было написать программу в С++ следующего условия: В текстовом файле - данные о длине трех сторон 14...

При загрузке списка из файла дублируется последняя строка - C++
Здравствуйте! Такая проблема: Выгружаю список в файл. С процедурой выгрузки проблем нет. Всё сохраняет корректно. Но при загрузке списка...

Нюансы работы с массивами: почему программа ведёт себя не так, как ожидается? - C++
// ConsoleApplication20.cpp: определяет точку входа для консольного приложения. // #include &quot;stdafx.h&quot; #include &quot;windows.h&quot; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
veslogrebov
0 / 0 / 0
Регистрация: 06.11.2012
Сообщений: 9
14.12.2012, 17:19  [ТС]     Работаю с файлом *.txt. Прога ведет себя странно если последняя строка файла пуста. Почему так? #2
Ну неужели никто не знает, что делать в таких случаях?
Yandex
Объявления
14.12.2012, 17:19     Работаю с файлом *.txt. Прога ведет себя странно если последняя строка файла пуста. Почему так?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru