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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.72
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 18:28     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #1
Всем доброго дня!

В С++ я новичок, сам себе придумываю задачки, просто для тренировки. Столкнулся с непонятным для меня поведением функции 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'); явно указывая символ конца строки - то же самое, на некоторых итерациях записывает в массив лишние строки, т.е. сначала идет строка с таймингами, а следом за ней в тот же массив дописывается пустые строки, или строки, состоящие из малого количества символов.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.10.2012, 18:28     Функция getline считывает несколько строк из файла, игнорируя символ новой строки
Посмотрите здесь:

Функция getc (FILE*) при первом вызве считывает НЕ ПЕРВЫЙ символ файла.Почему? C++
C++ Функция сравнивает две строки, игнорируя различия в регистрах
Функция getline не считывает пробелы C++
C++ Определить функцию, которая, игнорируя исходное деление файла на строки, переформатирует его
Символ новой строки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ksandro
31 / 31 / 1
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 18:50     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #2
чему у тебя равен параметр LINE?
Не может ли быть так что размер массива меньше чем длина строки?
Можешь выложить код целиком?
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 18:54  [ТС]     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #3
Цитата Сообщение от 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;
    }
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.10.2012, 19:02     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #4
Если можно, выложите файл, с которым пробуете.
ksandro
31 / 31 / 1
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 19:17     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #5
Пока вижу одну проблему.
у тебя 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.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 19:17  [ТС]     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #6
Цитата Сообщение от alsav22 Посмотреть сообщение
Если можно, выложите файл, с которым пробуете.
Ноу проблем, это просто файл субтитров к одной из серий "Декстера"
Прикладываю, только запаковать пришлось, txt до 20 кб только можно вложить.
Вот, скажем, в исходном тексте этого файла есть фраза "not you", она просто отсекается, хотя если добавить еще несколько символов к этой строке - все ок. Странный какой-то глюк.
Вложения
Тип файла: 7z Dexter.7z (14.5 Кб, 2 просмотров)
ksandro
31 / 31 / 1
Регистрация: 15.04.2011
Сообщений: 81
23.10.2012, 19:21     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #7
длину строки можно определить функцией strlen()

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


Надо что-то типа
Код
if ((strlen(sublines) > 16) && (sublines[13] == '-') && (sublines[14] == '-') && (sublines[15] == '>'))
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.10.2012, 19:40     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #8
Только глянул. Мне кажется, дело в самом файле. Это не текстовый файл, а вы с ним работаете, как с текстовым.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.10.2012, 19:45     Функция getline считывает несколько строк из файла, игнорируя символ новой строки
Еще ссылки по теме:

Считывание из файла строк с getline() C++
Функция getline пропускает ввод строки C++
C++ Функция, сравнивающая две строки, игнорируя количество пробелов между словами

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

Или воспользуйтесь поиском по форуму:
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
23.10.2012, 19:45  [ТС]     Функция getline считывает несколько строк из файла, игнорируя символ новой строки #9
Цитата Сообщение от ksandro Посмотреть сообщение
длину строки можно определить функцией strlen()

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


Надо что-то типа
Код
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!
Yandex
Объявления
23.10.2012, 19:45     Функция getline считывает несколько строк из файла, игнорируя символ новой строки
Ответ Создать тему
Опции темы

Текущее время: 08:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru