Linux |Ошибка сегментации в C ++ - из-за функции ifstream - PullRequest
1 голос
/ 03 августа 2011

Думаю, мне следует начать с того, что я только что установил linux (debian) на свой компьютер и ничего не знаю о работе в linux. Эта проблема, вероятно, из-за какой-то очень простой вещи.

Соответствующая часть кода похожа на это:

ifstream stockNames("names.txt");

    while (!stockNames.eof())
    {
        string snline;
        getline(stockNames,snline);
        cout << snline << endl;
        .
        .
        .
    }

это должно напечатать первую строку файла names.txt. Вместо этого он печатает пустую строку. И когда я пытаюсь использовать snline в качестве входных данных для другой функции, я получаю сообщение об ошибке «Ошибка сегментации». Как мне изменить свой код, чтобы сделать это? Есть ли разница в использовании ifstream в linux? Потому что в Windows код работает просто отлично


Я написал простой код ниже

#include <string>
#include <fstream>
#include <iostream>

using namespace std;

int main(int argc, const char *argv[])
{
    string dos = "names.txt";
    ifstream stockNames(dos.c_str() );

    string snline;
    while (getline(stockNames,snline))
    {
       cout << snline << " ";

    }
    return 0;
}

содержимое файла names.txt

ABC

DEFG

ГБО

вместо того, чтобы показывать эти строки, cout << snline ничего не производит </p>


Еще одно обновление: я написал еще два кода.

(1)

#include <string>
#include <fstream>
#include <iostream>

using namespace std;

int main(int argc, const char *argv[])
{
    cout << "program has initiated" << endl;

    ifstream stockNames("names.txt");

    if( !stockNames )
        cout << "unable to open" << endl;

    string snline;
    while (getline(stockNames,snline))
    {
        cout << snline << endl;

    }
    return 0;
}

Результат такой, как я хотел. Сначала «программа инициирована», затем ABC, DEFG, HBO в разных строках. Но когда я изменяю эту часть

        cout << snline << endl;

в

        cout << snline << " hey" << endl;

Тогда ABC DEFG HBO не появляется и вместо этого выводится только «эй».

Это безумие, как это может быть ??

Кстати, я попытался отладить ddd, и когда я проверяю переменную snline, ddd выводит следующую строку (GDB) Печать Snline $ 2 = {статические npos = 4294967295, _M_dataplus = {> = {<__ gnu_cxx :: new_allocator> = {},}, _M_p = 0x804c1a4 "ABC \ r"}}

новое мини-обновление: когда я меняю соответствующую строку как "cout << snline <<" "<< endl;" то, что напечатано, это «BC», «FGH», «BO» в отдельных строках. Почему оператор << переписывает через snline ?? </strong>

Ответы [ 5 ]

3 голосов
/ 03 августа 2011

Прежде всего, ваш цикл while неправильный, потому что флаг eof (или любой другой флаг сбоя) установлен после попытка чтения из потока не удалась; это означает, что если попытка чтения не удалась с помощью getline(), цикл не завершается немедленно, вместо этого цикл продолжается, что является серьезной ошибкой в ​​вашем коде.

Итак, напишите свой цикл как (идиоматическим образом):

string snline;
while (getline(stockNames,snline))
{
    cout << snline;
    //..
}

std::getline возвращает istream&, который может быть неявно преобразован в логический тип. Таким образом, если getline успешно прочитано, возвращаемое значение преобразуется в true, и цикл продолжится, иначе он преобразуется в false и цикл завершится.


После редактирования вашего вопроса, все, что я могу сказать, что вам нужно проверить объект потока, прежде чем использовать его для чтения содержимого из файла. В частности, вам нужно проверить, правильно ли инициализирован поток и действительно ли он открыл входной файл (т.е. names.txt) и готов ли считывать данные из него.

Итак, попробуйте сделать это:

//...
ifstream stockNames(dos.c_str() );
if (!stockNames) 
{
     cout << "file couldn't open properly" << endl;
     return 0;
}
string snline;
while (getline(stockNames,snline))
{
   cout << snline << " ";
}

Теперь запустите это и посмотрите, что он печатает.

1 голос
/ 04 августа 2011

У вас есть файл dos, который использует \ r \ n в конце каждой строки. Linux не распознает \ r как часть окончания строки, поэтому он включается в строку snline. \ r приводит к тому, что следующая напечатанная вещь появляется в начале строки, поэтому «эй» перезаписывает названия акций, которые вы ожидали увидеть.

Попробуйте

cout << snline << " " << endl;

и вы поймете, что я имею в виду

1 голос
/ 03 августа 2011

ответить на ваш вопрос;нет, нет существенной разницы в том, как ifstream работает на Linux и Windows.Конечно, если вы напишите код с ошибками (как указано в двух других ответах), вы можете столкнуться с проблемами, но я не могу понять, как ошибка eof вызовет описанные вами проблемы.сконцентрируйтесь на той части, где вы говорите, что использование snline вызывает ошибку сегментации, что указывает на более серьезную проблему.Не могли бы вы опубликовать код, который демонстрирует это?

1 голос
/ 03 августа 2011

stockNames на самом деле не будет достигать «конца файла», пока не попытается что-то ввести и не получит символ EOF.Поэтому вы захотите переписать ваш цикл следующим образом:

ifstream stockNames("names.txt");

string snline;
getline(stockNames,snline);

while (!stockNames.eof())
{
    cout << snline << endl;
    .
    .
    .
    getline(stockNames,snline);
}

или намного просто

ifstream stockNames("names.txt");

string snline;
while (getline(stockNames, snline))
{
    cout << snline << endl;
    .
    .
    .
}
0 голосов
/ 03 августа 2011

Вы не проверяете, правильно ли открыт поток.

std::ifstream stockNames("names.txt");
if (! stockNames) {
    std::cerr << "Unable to open file 'names.tex'\n";
}
else {
   // Do the rest of your stuff here.
}

Всегда проверяйте статус.Не просто пахать вперед и предполагать, что все в порядке.

Кстати, using namespace std; - это то, что вы видите во многих плохих книгах, которые пытаются сэкономить небольшое количество чернил.Попробуйте избавиться от этой вредной привычки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...