Сканирование CSV-файла с помощью scanf () в цикле прекращается после первой строки и начала второй - PullRequest
0 голосов
/ 28 августа 2018

Мне нужно прочитать огромный CSV-файл и сохранить его в структуре, чтобы вставить в двоичное дерево поиска (но это уже другая история), однако я могу получить только первые четыре столбца для чтения (одна строка имеет четыре колонки) - есть идеи?

Предполагаемая мощность:

Michael,21,M,12345
Susan,34,F,13342
Robin,12,F,45423
Teddy,43,M,56231
Ed,21,M,34354
Ramirez,21,F,79563
Toby,32,M,34277
Guy,23,M,90765
Desiree,21,F,67453
Molly,24,F,45434
Alison,23,F,62356
Tara,26,F,45223
Sally,21,F,34545
Mike,20,M,67676
Roger,19,M,83737
David,21,M,78554
Davis,23,M,66554
Sheng,22,M,31211
Wesley,31,M,21436

и т.д.. но я получаю

Michael,21,M,12345
Susan

Код:

#include <stdlib.h>
#include <stdio.h>

#define MAXLEN 128

typedef struct{
    char name[MAXLEN];
    char age[MAXLEN];
    char sex[MAXLEN];
    char courseID[MAXLEN];
}input_t;

typedef struct{
    input_t input;
    struct bst *left;
    struct bst *right;
} bst;

void parse_csv(bst *node);
void print_csv(bst node);

void parse_csv(bst *node){
    while (scanf(" %[^,],%[^,],%[^,],%[^,]\n", node->input.name, node->input.age, node->input.sex, node->input.courseID) == 4) {
        break;
    }
}

void print_csv(bst node){
  printf("%s,%s,%s,%s\n",node.input.name, node.input.age, node.input.sex, node.input.courseID);
}

int main(int argc, char *argv[]) {
    bst node;
    parse_csv(&node);
    print_csv(node);
    return 0;
}

как выглядит CSV, нам будут предоставлены тестовые файлы большего размера, хотя

1 Ответ

0 голосов
/ 28 августа 2018

Это может быть прочитано несколько раз (при условии, что форматирование отлично и см. Ниже);
хотя всегда в один и тот же узел.

while (scanf(" %[^,],%[^,],%[^,],%[^,]\n", 
       node->input.name,  
       node->input.age, 
       node->input.sex, 
       node->input.courseID) == 4) {

Это портит веселье, безоговорочно останавливаясь после первого раза.

    break;
}

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

В комментарии вы подтверждаете, что изменение ,]\n -> ,\n] исправляет разбор строки и дает вам правильно отсканированную первую строку.

Если вы также удалите break, сканирование CSV должно работать.
«Работа», как в «читать все CSV, игнорируя большую часть этого и сохраняя только последнюю строку». Чтобы показать более одной строки, вам, конечно, нужно

  • структура данных, которая может хранить более одной строки (вероятно, ваш BST)
  • заполните тот BST, где в настоящее время ваш break равен
  • изменить print_csv(), чтобы каким-то образом показать все дерево

или

  • вызов print_csv(), чтобы показать все дерево

Также см. Дополнительные комментарии Джонатана Леффлера в комментариях к этому ответу.
Они относятся к тому, что вы описываете как «другую историю».

В качестве примечания (также упоминаемого Джонатаном Леффлером):
Этот вариант использования идеально отформатированного и предполагаемого (возможно, сгенерированного) CSV может быть обработан scanf() как одно из немногих исключений. Для всего, что имеет малейшие сомнения в правильности форматирования, особенно для пользовательского ввода, семейство scanf () неуместно, чтение целых строк и явный синтаксический анализ с ошибками - путь туда.
Однако даже в случае, если предполагаемый ввод будет идеально отформатирован, рассмотрите возможность злонамеренного ввода и защитите себя, ограничив длину отсканированных полей, чтобы избежать записи за пределы ваших массивов, например, за пределами char name[MAXLEN] или char courseID[MAXLEN] в зависимости от того, как ваш компилятор упорядочивает структуры.

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