Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.66/29: Рейтинг темы: голосов - 29, средняя оценка - 4.66
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66

Функция getline считывает несколько строк из файла, игнорируя символ новой строки

23.10.2012, 18:28. Показов 6046. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго дня!

В С++ я новичок, сам себе придумываю задачки, просто для тренировки. Столкнулся с непонятным для меня поведением функции getline, не могу разобраться, в чем может быть косяк? Собственно, задачка совсем простенькая: хотел взять файл субтитров (текстовый, расширение .srt) и выкинуть оттуда все лишнее, сконвертировав в чистый текст.
Ну т.е. из такого вот:

1
00:00:00,122 --> 00:00:00,893
Subtitles: swsub.com

2
00:00:00,000 --> 00:00:01,719
<i>Previously on</i>

3
00:00:02,003 --> 00:00:04,055
I was working on my piece...


Получить просто строки текста:
"<i>Previously on</i> I was working on my piece...

Ну и так далее. Решил использовать getline, вот как-то так:
C++
1
2
3
4
5
6
7
8
9
10
    while (inFile.good())   // считываем до EOF
    {
    inFile.getline (sublines, LINE);
     if ((sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
                        continue;               
    else if ((sublines[0] == '\0') || (sublines[1] == '\0') || (sublines[2] == '\0') || (sublines[3] == '\0'))
                        continue;
    else
    {код, форматирующий текст, с ним все ок  }                                                                                    
    }
Т.е. текст построчно считывается в массив, проверяется на наличие "-->", эта строка (тайминги) отбрасывается, затем отбрасываются пустые строки, либо те, в которых только 3 символа, а текст форматируется - убираются пробелы и ещё пару мелких "косметических" операций. И все бы хорошо, но почему-то getline считывает не всегда по 1 строке, а в некоторых случаях сразу несколько и, соответственно, отбрасывается всякая "мелочь" из 1-2 слов в строке. Поэтому после такой "конвертации" некоторые строки, состоящие из 1-2 коротких слов, выкидываются. Проверял - происходит это только со строками, которые состоят из 1-2 слов, где-то около 10 символов, несмотря на то, что все строки заканчиваются символом '\n', т.е. по идее все же должно быть построчное считывание. Если в первом "if"
C++
1
if ((sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
вместо continue пишу inFile << "имя массива"; то выводится все, но при этом, само собой и строка таймингов (00:00:00,000 --> 00:00:01,719) не отбрасывается.
В чем фишка, не могу понять. Пробовал писать inFile.getline (sublines, LINE, '\n'); явно указывая символ конца строки - то же самое, на некоторых итерациях записывает в массив лишние строки, т.е. сначала идет строка с таймингами, а следом за ней в тот же массив дописывается пустые строки, или строки, состоящие из малого количества символов.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.10.2012, 18:28
Ответы с готовыми решениями:

Чтение из файла: считывает символ новой строки и табуляции "\t\n"
В общем проблема следующая: при нажатии кнопки происходит запись в файл, потом чтение из него...на локальном сервере все работает нормально...

Скрыть символ новой строки при выводе строк из файла
Всем доброго времени суток, Изучая запись и чтение из файла в Пайтоне, наткнулся на такую проблему, которую пока не могу решить. Вот...

Как убрать символ новой строки (\n) при чтении строк из файла pascal>
Здравствуйте, дорогие программисты! Помогите сделать программу, которая будет считывать текст из txt в строку разделяя ее на отдельные...

8
31 / 31 / 4
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 18:50
чему у тебя равен параметр LINE?
Не может ли быть так что размер массива меньше чем длина строки?
Можешь выложить код целиком?
0
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 18:54  [ТС]
Цитата Сообщение от ksandro Посмотреть сообщение
чему у тебя равен параметр LINE?
Не может ли быть так что размер массива меньше чем длина строки?
Можешь выложить код целиком?
Могу, конечно. Параметр LINE - установил в 100, этого за глаза хватит для 1 строки.
Целиком это выглядит так:

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
#include "stdafx.h"
#include <iostream>
#include <fstream>                  // for file I/O
#include <cstdlib>  
#include <string>
 
// support for exit()
 
const int SIZE = 60;
const int LINE = 100;
 
int _tmain(int argc, _TCHAR* argv[])
{
    using namespace std;
    char filename[SIZE];
    ifstream inFile;        // object for handling file input
    ofstream outFile;               // create object for output
    outFile.open("Re-formattedSubtitle.txt");    // associate with a file
    
    cout << "Enter name of a subtile file you wish to convert: ";
    cin.getline(filename, SIZE);
    inFile.open(filename);  // ассоциируем файл
    if (!inFile.is_open())  // проверка на ошибку
    {
        cout << "Could not open the file " << filename << endl;
        cout << "Program terminating.\n";
        // cin.get();  
        exit(EXIT_FAILURE);
    }
    
    char sublines[LINE];
    char outlines[LINE];
    const int CUTOFF = 3;
    int counter = 0;
 
    while (inFile.good())   // считываем до EOF
    {
        
        inFile.getline (sublines, LINE, '\n');
                    if ((sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
                        continue;               
                    else if ((sublines[0] == '\0') || (sublines[1] == '\0') || (sublines[2] == '\0') || (sublines[3] == '\0'))
                        continue;
                    else
                    {for (int i = 0, k = 0; sublines[i] != '\0'; i++)
                          { if (sublines[i+1] == '\0')
                            {outlines[k] = sublines[i]; 
                            outlines[k+1] = '\0'; }
                            else if ((sublines[i] == '<') && (sublines[i+1] == '/') && (sublines[i+2] == 'i') && (sublines[i+3] == '>') && (sublines[i+4] == '\0'))
                            {outlines[k] = '*';
                            outlines[k+1] = '/';
                            outlines[k+2] = '\0';
                            k += 2;
                            i += 3;}
                            else if ((sublines[i] == '<') && (sublines[i+1] == 'i') && (sublines[i+2] == '>') && (sublines[i+3] == '\0'))
                            {outlines[k] = '*';
                            outlines[k+1] = '/';
                            outlines[k+2] = '\0';
                            k += 2;
                            i += 3;}
                            else if ((sublines[i] == '<') && (sublines[i+1] == 'i') && (sublines[i+2] == '>'))
                            {outlines[k] = '/';
                            outlines[k+1] = '*';
                            k += 2;
                            i += 2;}
                            else if ((sublines[i] == '<') && (sublines[i+1] == '/') && (sublines[i+2] == 'i') && (sublines[i+3] == '>'))
                            {outlines[k] = '*';
                            outlines[k+1] = '/';
                            k += 2;
                            i += 3;}
                            else if ((sublines[i] == ' ') && (sublines[i+1] == ' '))
                            continue;
                            else 
                            {outlines[k] = sublines[i];
                            k++;}
                          }
                            outFile << outlines << " ";
                            for (int i = 0; sublines[i] < 100; i++)
                                sublines[i] = '!';
                        }                                           
                                            
    }
    if (inFile.eof())
        cout << "End of file reached.\n";
    else if (inFile.fail())
        cout << "Input terminated by data mismatch.\n";
    else
        cout << "Input terminated for unknown reason.\n";
    
    inFile.close();         
    outFile.close();              
    // cin.get();
    // cin.get();
    return 0;
    }
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
23.10.2012, 19:02
Если можно, выложите файл, с которым пробуете.
0
31 / 31 / 4
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 19:17
Пока вижу одну проблему.
у тебя 2 строки
00:00:00,000 --> 00:00:01,719
<i>hello</i>

Ты прочитал первую строку. Массив заполнился данными "00:00:00,000 --> 00:00:01,719"
Ты проверил наличие --> и отбросил строку.
Все OK вроде, но когда читаешь вторую строку, ты ее читаешь в тот же массив. Если строка длинная то она перетирает символы --> на 13 14 и 15 позиции, а если строка короткая, то там так и остаются эти символы, и она отбрасывается.

Прежде чем проверять (sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>')
проверяй что длина строки не меньше 13.
1
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 19:17  [ТС]
Цитата Сообщение от alsav22 Посмотреть сообщение
Если можно, выложите файл, с которым пробуете.
Ноу проблем, это просто файл субтитров к одной из серий "Декстера"
Прикладываю, только запаковать пришлось, txt до 20 кб только можно вложить.
Вот, скажем, в исходном тексте этого файла есть фраза "not you", она просто отсекается, хотя если добавить еще несколько символов к этой строке - все ок. Странный какой-то глюк.
Вложения
Тип файла: 7z Dexter.7z (14.5 Кб, 4 просмотров)
0
31 / 31 / 4
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 19:21
длину строки можно определить функцией strlen()

http://cpp.com.ru/shildt_spr_po_c/14/strlen.html


Надо что-то типа
Code
1
if ((strlen(sublines) > 16) && (sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
23.10.2012, 19:40
Только глянул. Мне кажется, дело в самом файле. Это не текстовый файл, а вы с ним работаете, как с текстовым.
1
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 19:45  [ТС]
Цитата Сообщение от ksandro Посмотреть сообщение
длину строки можно определить функцией strlen()

http://cpp.com.ru/shildt_spr_po_c/14/strlen.html


Надо что-то типа
Code
1
if ((strlen(sublines) > 16) && (sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
Супер! )) Спасибо! Дело именно в этом, что-то я затупил. Ты прав - это действительно не в getline дело, а в том, что в массиве остаются прежние данные. Но только со strlen не получилось - эффект тот же (только что попробовал) - видимо, она возвращает размер всего массива, а он у меня 100 (и, соотвественно, всегда больше 16, точнее даже 5, потому что больше 5 символов - это уже, скорее всего, что-то нужное).

Но пофигу, я по другому сделал - просто перед вызовом функции getline каждый раз перезатираю массив:

C++
1
2
for (int i = 0; sublines[i] < 100; i++)
sublines[i] = '!';
И все стало ок.

Добавлено через 2 минуты
Цитата Сообщение от alsav22 Посмотреть сообщение
Только глянул. Мне кажется, дело в самом файле. Это не текстовый файл, а вы с ним работаете, как с текстовым.
Да не, ksandro уже нашел баг, за что ему спасибо
Файл текстовый, пофигу, какое там расширение.

Просто нужно перезатереть массив перед вызовом функии getline и все норм.

тема закрыта, всем ещё раз thanx!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.10.2012, 19:45
Помогаю со студенческими работами здесь

Функция getline не считывает пробелы
Написал код программы для вывода из файла строк, где есть двузначные цифры. Пользовался функцией getline. Но указанные в процессе работы...

Функция getc (FILE*) при первом вызве считывает НЕ ПЕРВЫЙ символ файла.Почему?
Друзья! Здравствуйте! Вот код. #include &lt;iostream&gt; using namespace std; int main () { FILE* zapis_v_fail; FILE*...

Функция,которая считывает из файла только n последних строк
Привет! Подскажите как прописать функцию, перед этим уже прописала потоковое чтение из файла и посчитала количество строк в файле. Спасибо!

Функция ReadLine() считывает не все строки из текстового файла (пропускает строки)
Здравствуйте. Изучаю Visual Basic 2010. Сейчас разбираюсь со считыванием информации из текстового файла. С функцией ReadToEnd(), вроде все...

Не считывает одну строку из файла с getline()
string s; char l; ifstream file1; file1.open(&quot;in_1.dat&quot;, ios::in); cout &lt;&lt; &quot;ФАЙЛ 1\n\n&quot;; while (!file1.eof()) { ...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru