Как правильно читать составной ключ и числовое значение из входного файла? - PullRequest
3 голосов
/ 06 октября 2019

Я пытаюсь прочитать текстовый файл, состоящий из многочисленных строк, которые либо представляют ключ / значение (ключ - это номер машины в формате буквы / '' / 3digits / '' / 2letters; значениедлинная строка без знака; \ t или '' между ними) или пустая строка, например:

пустая строка
пустая строка
Z 999 ZZ 80
A 000 AA 124
Z 666 ZZ 42

Для этого я использую функцию cin.getline (), читая целую строку и просматривая каждый символ,сохранение ключа и значения в переменную 'element' и последующее их добавление в вектор. Но по какой-то причине программа работает неожиданно, выдавая странный вывод:

0
0
Z 999 ZZP 80
A 000 AA |124
Z 666 ZZ * 42

До сих пор я пытался проанализировать, что может пойти не так, но я просто не вижу этого. Я также пытался использовать другие инструменты, такие как scanf () или cin.get (), но с треском провалился. Может кто-нибудь объяснить мне, почему это происходит, и, возможно, показать более правильный способ решения этой задачи? Вот код:

struct kv {
    char key[8];
    unsigned long long val;
};

int main()
{
    std::vector<kv> data_vector;
    kv element;

    char str[64] = {};
    char num[32] = {};
    while (std::cin.getline(str, 64)) {
        if (str[0] == ' ' || str[0] == '\n' || str[0] == '\t' || str[0] == EOF) {
            continue;
        }
        size_t i = 0, n = 0;
        for (i = 0; i < 8; i++)
            element.key[i] = str[i];
        while (!(str[i] >= '0' && str[i] <= '9'))
            i++;
        while (str[i] >= '0' && str[i] <= '9')
            num[n++] = str[i++];
        element.val = atoi(num);
        data_vector.push_back(element);
        for (n = 0; n < 32; n++)
            num[n] = 0;
        for (i = 0; i < 64; i++)
            str[i] = 0;
    }
    for (size_t i = 0; i < data_vector.size(); i++) {
        std::cout << data_vector[i].key << "\t" << data_vector[i].val << std::endl;
    }
    return 0;
}

РЕДАКТИРОВАТЬ : как указано @JimRhodes, изменив ключ [8] на ключ [9] и добавив element.key [8] = '\ 0 'помогло, , но пустые строки по-прежнему обрабатываются неправильно (как их следует игнорировать), давая вывод 0.

1 Ответ

1 голос
/ 06 октября 2019

Я думаю, вы не понимаете, как работает std::cin.getline(). Прежде всего, вы не хотите проверять возвращаемое значение std::cin.getline() на true или false. Вам нужно проверить на eof или fail. Во-вторых, std::cin.getline() отбрасывает символ новой строки, поэтому нет необходимости проверять '\ n'. Ваш цикл может начаться так:

for ( ; ; )
{
    str[0] = '\0'; // Clear any previous data
    std::cin.getline(str, 64);
    if ( std::cin.eof() )
    {
        break; // No more data, exit loop
    }
    if ( std::cin.fail() || (str[0] < 'A') )
    {
        continue; // Empty line or line does not start with a letter
    }
    . . .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...