2015-09-02 3 views
0

Я пытаюсь создать код для чтения ввода из текстового файла, разделенного запятыми, по строкам. Меня интересуют только 3 поля, поэтому .. Я перепрыгивал остальную Проблема заключается в том, что 2 из полой строка, содержащаяся в кавычках, и один из них на самом деле необязательноC regex как соответствовать любой строке, заканчивающейся «или любой пустой строкой?

Например, две последовательных строки могут выглядеть следующим образом:

0,,10004,10004,"Albany Hwy After Galliers Av","",-32.13649428,116.0176090070,3 
0,,10005,10005,"Albany Hwy Armadale Kelmscott Hospital","Armadale Kelmscott Hospital",-32.13481555555560,116.017707222222,3 

Поскольку меня не интересуют строки (меня интересуют только некоторые из чисел), я просто пропускаю их с помощью оператора * в scanf. Для первой строки это легко, так как это мандато чень поле, так что я могу просто пропустить первый двойной кавычки матч в регулярном выражении всего до второй двойной кавычки, например:

\"%*[^\"] 

Что у меня возникают проблемы с является вторым полем, сразу после того, первый. Проблема в том, что это поле не является обязательным; таким образом, он может иметь текст, он может и не быть. Всякий раз, когда этого не происходит, регулярное выражение, указанное выше, не работает должным образом, и вся операция scanf не работает для этой строки. Несмотря на все мои усилия, я не могу создать регулярное выражение, которое бы соответствовало всем значениям ко второй двойной кавычки, а также сопоставление пустых строк. Кто-нибудь знает, как я могу изменить мое регулярное выражение для выполнения такой функции?

p.s. Вот пример того, что моя операция зсапЕ выглядит следующим образом:

res = sscanf(buf, "%*d,,%ld,%*ld,\"%*[^\"]\",\"%*[]\",%lf,%lf,%*d", &cursid, &curslat, &curslong); 
+2

Семейство функций '' scanf' (http://en.cppreference.com/w/c/io/fscanf) делает * not * использование регулярных выражений. –

+0

Извините, мой плохой, это не регулярное выражение. Это просто использование функции% [chars] для scanf, где считывается все, что соответствует [chars]. Вопрос по-прежнему касается того, как я могу добиться того, что я пытаюсь сделать. – Ammar

+0

Что касается того, как читать ваш CSV-файл, это не так просто, как можно было бы подумать, потому что форматы файлов CSV обычно содержат много угловых случаев, что затрудняет их анализ, чем можно было бы подумать. Попробуйте найти существующую библиотеку для чтения и анализа вашего файла. –

ответ

1

Ниже приведен основной CSV парсер:

void readCSVline(char *line); 
char *readCSVfield(char *line, char *buf); 
void readCSVdemo(void) 
{ 
    char line[]= "0,,10004,10004,\"Albany Hwy After Galliers Av\",\"\",-32.13649428,116.0176090070,3"; 
    readCSVline(line); 

} 
/* readCSVline is where you put your "intelligence* about fields to read 
* and what to do with them 
*/ 
void readCSVline(char *line) 
{ 
    char field1[80], *lineptr=line; 
    int nfields=0; 

    while (*lineptr) { 
     lineptr= readCSVfield(lineptr, field1); 
     printf("%s\n", field1); 
     nfields++; 
    } 
    printf("%d fields read.\n", nfields); 
} 
/* readCSVfield reads a field from a CSV line until the next comma or end-of-line. 
* It returns where the reading stopped. 
*/ 
char *readCSVfield(char *line, char *buf) 
{ 
    int instr= FALSE; // track whether we are in a string 
    char *cptr= line; 

    while (*cptr) 
    { 
     if (instr) { 
      if (*cptr=='"') { 
       char cc= *++cptr; 
       if (cc=='"')  // escaped double quote 
        *buf++ = '"'; 
       else { 
        *buf='\0'; 
        cptr--; 
        instr= FALSE; 
       } 
      } 
      else *buf++ = *cptr; 
     } 
     else switch (*cptr) { 
     case '"': instr= TRUE; break; 
     case ',': cptr++; *buf= '\0'; return(cptr); 
     case ' ': case '\t': case '\n': case '\r': break; 
     default: *buf++ = *cptr; 
     } 
     cptr++; 
    } 
    *buf= '\0'; 
    return(cptr); 
} 

Примечание: обработка перевода строки в кавычках

Часто парсер вызывается с линией, которую читатель вызывал. Чтобы иметь возможность обрабатывать возврат каретки/переводы строк, которые находятся в кавычной строке, анализатор должен обработать вид \n, получив следующую строку. Подпись для readCSVfield должна включать буфер строки и его размер.

Смежные вопросы