сбой вектора push_back - PullRequest
       3

сбой вектора push_back

1 голос
/ 09 декабря 2011

У меня следующая структура.

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

struct station {
    std::string id;
    std::string code;
    std::string station_name;
    station(std::vector<std::string> &in) : id(in[0]), code(in[1]), 
                                            station_name(in[2]) {}
    station(): id (""), code (""), station_name(""){}

    bool operator<( const station& rhs ) const {
        return this->station_name < rhs.station_name;   
    }
};
int main(int argc, char **argv) {    
    std::ifstream ifs(argv[1]);
    if ( ifs.peek() == EOF )  {
        exit ( 1 );
    }
    // Read the input file and update the database
    std::string line;
    station prev, current;
    std::set<station> my_set;
    while( ifs.good()&& std::getline(ifs,line) ) {
        std::stringstream  lineStream(line);
        std::string        token;
        std::vector<std::string> input;        
        while(std::getline(lineStream,token,',')) {
            input.push_back(token);
        }
        station st(input);
        my_set.insert(st);

    }
}

Я читаю файл, содержащий информацию, связанную с railway stations, в следующем формате ID,Station Code,Station Name

Я читаю этот файл построчно и создаю объект station, а затем помещаю его в std::set<station>

Через некоторое время происходит сбой после прочтения строки 21448. У меня около 403523 строк

В чем здесь проблема.

Эта программа правильно работает в Linux, но не в Windows

Я получаю debug assertion failed

Ответы [ 3 ]

2 голосов
/ 09 декабря 2011

Здесь полезно знать некоторые методы отладки.Там, где вы создаете новый station, я бы поставил утверждение:

assert(station_init_vector.size() >= 3);

Это гарантирует, что вы не обращаетесь к векторным элементам, которые не существуют.

Альтернативным инструментом является использование векторного члена at() вместо оператора [], который выполняет проверку индекса во время выполнения и выдает исключение для индексации вне пределов:

station(std::vector<std::string> &in) : id(in.at(0)), code(in.at(1)),
                                        station_name(in.at(2)) {}
2 голосов
/ 09 декабря 2011

Мой конструктор беспокоит мой конструктор.

Редактировать

На основании обновленного вопроса:

Проблема в том, что конструктор принимает вектор.
Вы получаете доступ к элементам без проверки, существуют ли они.

Таким образом, если какая-либо строка ввода неверна (т. Е. Не все значения присутствуют), то вектор будет не таким большим, как требуется, и приведет к неопределенному поведению.

Если вы измените эти строки:

while(std::getline(lineStream,token,',')) {
            input.push_back(token);
        }

В:

std::getline(linestream, id,   ',');
std::getline(linestream, code, ',');
std::getline(linestream, name, ',');

Затем вызывается конструктор станции с этими параметрами (как было бы неплохо в коде ОО). Тогда бы вы не увидели крушения. Неплохая проверка ошибок.

Примечание:

while( ifs.good()&& std::getline(ifs,line) ) {

Здесь нет необходимости проверять good (). Если поток не в хорошем состоянии, тогда getline () ничего не сделает. Преобразование потока (возвращаемого значения getline ()) в bool также проверяет, является ли состояние потока действительным для дальнейшего чтения и, если нет, преобразуется в false (в конце концов).

// This is more idiomatic.
while(std::getline(ifs,line) ) {

Оригинал

попробуйте это:

struct station
{
    std::string id;
    std::string code;
    std::string station_name;
    friend std::istream& operator>>(std::istream& stream, station& data)
    {
        std::string  line;
        std::getline(stream, line);

        std::stringstream  linestream(line);
        std::getline(linestream, data.id, ',');
        std::getline(linestream, data.code, ',');
        std::getline(linestream, data.station_name);

        return stream;
    }
};

int main()
{
    std::ifstream   file("station.txt");
    std::vector<station>  stations;

    std::copy(std::istream_iterator<station>(file),
              std::istream_iterator<station>(),
              std::back_inserter(stations)
             );
}
0 голосов
/ 09 декабря 2011

На какой платформе создаются ваши входные файлы?Среда выполнения C ++ должна решить, каково оптимальное соглашение об окончании строки для вашей платформы.Так что с этим может быть какая-то проблема, но это не объясняет, почему программа ожидает сбоя до 21448 строк.

И ваша ошибка недостаточно информативна.Обычно, когда утверждение терпит неудачу, оно показывает, где оно провалилось.В вашем случае кажется, что это может быть ошибка в std :: vector.Попробуйте заменить оператор [] на at () в вашем конструкторе.Он выдает исключение вне допустимого диапазона при попытке доступа к недопустимому индексу.

Наконец, как уже отмечали другие, не рекомендуется передавать вектор конструктору, особенно если вытолько три аргумента.Мало того, что это может привести к труднопостижимым ошибкам, но вы платите цену за дополнительный конструктор и деструктор в каждой итерации цикла while.Надеюсь, это поможет.

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