Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.96/48: Рейтинг темы: голосов - 48, средняя оценка - 4.96
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
1

Чтение строк из файла

21.03.2015, 08:12. Показов 9116. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день имеется ряд вопросов касательно чтения строк из текстового файла.
В папке с программой содержится файл TEST.TXT, в котором записано следущее стихотворение:
Стихотворение

Приходит март. Я сызнова служу.
В несчастливом кружении событий
Изменчивую прелесть нахожу
В смешеньи незначительных наитий.

А следующая программа читает и выводит строки из этого файла:
Программа

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <iomanip>
#include <fstream>
#include <windows.h>
using namespace std;
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    const int MAX = 80;
    char buffer[MAX];
    ifstream infile("TEST.TXT");
    while (!infile.eof())
    {
        infile.getline(buffer, MAX);
        cout << buffer << endl;
    }
    system("pause");
    return 0;
}

Вопросы:

1) Почему при замене условия цикла на
C++
1
while (infile)
выводится дополнительный пробел после стихотворения?

2) Почему при замене метода считывания на
C++
1
infile.getline(buffer, '\n');
строка считывается не полностью, а лишь одним словом, включая последущий пробел?
Кликните здесь для просмотра всего текста
Чтение строк из файла

Ведь по идее строка должна считываться до символа '\n'.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.03.2015, 08:12
Ответы с готовыми решениями:

Чтение строк из файла
struct Questions { char quest; }QuestList; void main() { int numQuest=0; FILE *fp; fp =...

Чтение строк из файла
Мне нужно читать строки из фалйа разной длинны тоесть может быть вобще пустая строка. нужно...

Чтение строк из файла
Есть файл с 10 строками, необходимо вывести на экран четные строки ifstream file(&quot;C:\\1.txt&quot;);...

Чтение файла в массив строк
У меня есть код, не понимаю почему число строчек не влияет на количество работников массива...

19
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 08:20  [ТС] 2
А при замене той же строки на
C++
1
infile.getline(buffer, ' ');
строка выводится так, как изначально и задумывалось, но ведь она должна считываться только до первого пробела.
Кликните здесь для просмотра всего текста
Чтение строк из файла
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 08:53 3
Лучший ответ Сообщение было отмечено Ferrari F1 как решение

Решение

В случае с
C++
1
infile.getline(buffer, ' ');
ты неверное пользуешься функцией cin.getline(). Поэтому поведение программы не такое, как ты ожидаешь (насколько я понял ситуацию). У тебя символ типа char приводится к int и становится размером массива buffer, таким образом, метод getline() соответствует прототипу
C++
1
istream& getline (char* s, streamsize n );
Вот маленькая программка для иллюстрации:
C++
1
2
3
4
5
6
7
8
#include <iostream>
int main()
{
    char ch = ' ';
    int num = int(ch);  // приводим переменную типа char к типу int
    std::cout << num;
    return 0;
}
То есть, написав
C++
1
infile.getline(buffer, ' ');
ты практически написал то же самое, что и
C++
1
infile.getline(buffer, 32);
А тебе надо было писать так:
C++
1
infile.getline(buffer, MAX, ' ');
Тогда метод getline() будет соответствовать другому прототипу:
C++
1
istream& getline (char* s, streamsize n, char delim );
И всё должно получиться.
2
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 09:01  [ТС] 4
gru74ik,
Спасибо! Таким образом отводимый размер буфера определялся ASCII-кодом символа?
Каков был ASCII код ограничителя, столько символов и копировалось в буфер?
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 09:09 5
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
Таким образом отводимый размер буфера определялся ASCII-кодом символа?
Каков был ASCII код ограничителя, столько символов и копировалось в буфер?
Я думаю, да.
0
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 09:19  [ТС] 6
gru74ik, а можешь чего нибудь рассказать про
C++
1
while (infile)
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 10:11 7
Ferrari F1, программа читает весь файл и выводит его, но кроме этого, похоже, проверив условие, находит в потоке символ EOF или, возможно, '\n', интерпретирует его как true, входит лишний раз в цикл и выйдя за пределы массива читает следующий символ, который там лежит. В твоём случае там случайно оказался пробел, а мог быть любой мусор или кусок кода. Не уверен, что прав, но это единственное, что мне приходит в голову. Собственно, я свою догадку вот таким кодом проверял (твой код + проверка):
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
#include <iostream>
#include <iomanip>
#include <fstream>
#include <windows.h>
using namespace std;
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    const int MAX = 80;
    char buffer[MAX];
    ifstream infile("test.txt");
    bool flag = infile;
    while (infile)
    {
        infile.getline(buffer, MAX);
        cout << buffer << endl;
        if (flag)
            cout << "infile is true\n";
        else
            cout << "infile is false\n";
    }
    system("pause");
    return 0;
}
0
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 10:18  [ТС] 8
gru74ik,
а ведь символ eof вставляется манипулятором ends?
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 10:21 9
Может, причина в другом. В общем, про этот нюанс лучше спросить кого-то, кто знает наверняка.
0
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 10:44  [ТС] 10
Catstail, Humanoid, Jazon_deenAlt, ForEveR, zss, castaway, Evg,
ПОМОГИТЕ !!! =)
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 10:51 11
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
а ведь символ eof вставляется манипулятором ends?
Если ты про манипулятор std::endl, то нет - он всего лишь очищает поток и вставляет новую строку.

Про EOF:
Цитата Сообщение от Стивен Прата
По достижении конца файла — реального или эмулируемого — cin.get (void)
возвращает значение EOF, которое является символьной константой, определенной в заголовочном файле iostream. Эта архитектурная особенность делает возможным использование следующей конструкции для считывания ввода:
C++
1
2
3
4
5
int ch = EOF;
while ((ch = cin.get()) != EOF)
{
    // обработка ввода
}
В данном случае для переменной ch нужно использовать тип int вместо char,
поскольку значение EOF не может быть выражено как тип char.
0
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 10:53  [ТС] 12
gru74ik,
не, я про манипулятор std::ends;
C++
1
cout << "что-то" << ends << endl;
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
21.03.2015, 10:57 13
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
ПОМОГИТЕ !!! =)
У вас тут всё в кучу смешалось. С чем именно помочь?
0
805 / 532 / 158
Регистрация: 27.01.2015
Сообщений: 3,017
Записей в блоге: 1
21.03.2015, 10:58  [ТС] 14
castaway,
помоги пожалуйста разобрать вопрос с
C++
1
while (infile)
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
21.03.2015, 11:00 15
std::ends
Inserts a null character into the output sequence os as if by calling os.put(CharT()).

This is an output-only I/O manipulator, it may be called with an expression such as out << std::ends for any out of type std::basic_ostream.
Грубо говоря, это синоним '\0'.
2
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 11:00 16
И вот ещё про EOF, может будет полезно:
Цитата Сообщение от Стивен Прата
Если ввод поступает из файла, вы можете задействовать более мощный прием — обнаружение конца файла (end-of-file — EOF). Средства ввода C++ взаимодействуют с операционной системой для обнаружения момента достижения конца файла, и предоставляют эту информацию программе.
На первый взгляд чтение информации из файла имеет мало общего с cin и клавиатурным вводом, но между ними существуют две связи. Во-первых, многие операционные системы, включая Unix, Linux и режим командной строки Windows, поддерживают перенаправление, что позволяет легко подставлять файл вместо клавиатурного ввода. Например, предположим, что в среде Windows имеется исполняемая программа gofish.exe и текстовый файл по имени fishtale. В этом случае вы можете вести следующую команду в командной строке:
gofish <fishtale
Это заставит программу принять ввод из файла fishtale вместо клавиатуры.
Символом < обозначается операция перенаправления, как в Unix, так и в режиме командной строки Windows.
Во-вторых, многие операционные системы позволяют эмулировать условие EOF с клавиатуры. В Unix для этого необходимо нажать клавиатурную комбинацию <Ctrl+D> в начале строки. В режиме командной строки Windows для этого потребуется нажать <Ctrl+Z> и после этого <Enter> в любом месте строки. Некоторые реализации C++ поддерживают подобное поведение, даже если его не поддерживает операционная система. Концепция EOF для клавиатурного ввода в действительности унаследована от сред командной строки. Однако Symantec C++ для Mac имитирует Unix и распознает <Ctrl+D> как эмуляцию EOF. Версия Metrowerks Codewarrior распознает <Ctrl+Z> в средах Macintosh и Windows. Версии Microsoft Visual C++, Borland C++ 5.5 и GNU C++ для ПК распознают комбинацию <Ctrl+Z>, когда она встречается в начале строки, но требуют последующего нажатия <Enter>. Короче говоря, многие среды программирования для ПК распознают комбинацию <Ctrl+Z> как эмуляцию EOF, но конкретные детали (в любом месте строки или же только в начале, требуется последующее нажатие <Enter> или нет) могут варьироваться.
Если в среде программирования предусмотрена проверка EOF, вы можете использовать программу, подобную приведенной в листинге 5.17, с перенаправленными файлами либо с клавиатурным вводом, в котором эмулируется EOF Это выглядит удобным, поэтому давайте посмотрим, как такое делается.
Когда объект cin обнаруживает EOF, он устанавливает два бита (eofbit и failbit) в 1. Для проверки состояния eofbit можно использовать функцию-член по имени eof(); вызов cin.eof() возвращает булевское значение true, если EOF был обнаружен, и false — в противоположном случае. Аналогично, функция-член fail() возвращает true, если eofbit или failbit установлены в 1.
Обратите внимание, что методы eof() и fail() сообщают результат самой последней попытки чтения; т.е. они сообщают о прошлом, а не заглядывают в будущее.
Поэтому проверки cin. eof () и cin.fail() должны всегда следовать за попытками чтения.
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
21.03.2015, 11:06 17
C++
1
while (infile)
Тут вызывается оператор explicit operator bool() const;, который возвращает true если в потоке нет ошибок.
Там внизу есть познавательная табличка по которой видно, в каких случая возвращается true, а в каких false.
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 11:26 18
castaway, а когда дело доходит до EOF? Что происходит в
C++
1
while (infile)
?

Чтение из потока воспринимается как успешное и происходит ещё один (лишний) виток цикла?
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
21.03.2015, 11:29 19
Судя по всему, да:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
using namespace std;
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    const int MAX = 80;
    char buffer[MAX];
    ifstream infile("test.txt");
    for (int i=1; infile; ++i)
    {
        infile.getline(buffer, MAX);
        cout << i << endl;
    }
    system("pause");
    return 0;
}
Вложения
Тип файла: txt test.txt (127 байт, 7 просмотров)
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
21.03.2015, 11:33 20
Цитата Сообщение от gru74ik Посмотреть сообщение
Чтение из потока воспринимается как успешное и происходит ещё один (лишний) виток цикла?
Получается что так. Думаю, тут лучше использовать метод good().
1
21.03.2015, 11:33
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.03.2015, 11:33
Помогаю со студенческими работами здесь

Чтение из файла в массив строк
Всем добра! Пишу с таким вопросом: есть файл с текстом, длины строк не известны, надо задать...

Чтение из файла (массив строк)
Здравствуйте, не могли бы вы мне помочь, есть данная задача Реализовать структуру «Ticket» –...

Чтение файла в массив строк
Доброго времени суток!!! Как считать файл в массив строк? Заранее спасибо!!!

Чтение строк из бинарного файла.
Вот как происходит запись строк pr.login и pr.password: FILE *f; f=fopen(path,&quot;ab&quot;); if...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru