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

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

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

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

13.12.2012, 17:19. Просмотров 360. Ответов 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++):

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

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

Цикл While странно себя ведет - C++
Пишу программу которая считывает из каждой строки массив неизвестной длины.Цикл while(который помечен комментом) странно себя...

класс 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; ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
veslogrebov
0 / 0 / 0
Регистрация: 06.11.2012
Сообщений: 9
14.12.2012, 17:19  [ТС] #2
Ну неужели никто не знает, что делать в таких случаях?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.12.2012, 17:19
Привет! Вот еще темы с ответами:

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

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

Есть блок с positioin:fixed; почему он так странно себя ведет? - HTML, CSS
Разметка: &lt;div class=&quot;one&quot;&gt; &lt;div class=&quot;two&quot;&gt;&lt;/div&gt; &lt;/div&gt; Стили:

Почему DHCP ведет себя так? - Mikrotik
Добрый день, В здании несколько организаций, но Интернет общий, настроил Mikrotik RB951G-2HnD таким образом, что на каждом сетевом...


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

Или воспользуйтесь поиском по форуму:
Ответ Создать тему
Опции темы

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