ibilalkayy Ответов: 2

Как напечатать первое слово каждой строки с разделением запятыми плюс дайте мне возможность выбирать эти слова по одному при печати


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRING_LEN 200

int main(){
  char string[STRING_LEN], data[STRING_LEN];
  FILE * fp1 = fopen("file.csv", "r");
  
  while(fgets(string, STRING_LEN, fp1)){
    // strtok(string, ",");
    sscanf(string, "%s", data);
    printf("%s\n", data);
  }
  
  return 0;
}


Что я уже пробовал:

В этом коде я пытаюсь получить первое слово каждой строки с разницей в запятую, потому что это CSV-файл, а имя содержит два слова. Но sscanf это разделение слов с разницей в пространстве. Так что я не могу узнать его фамилию. Я могу использовать функции strtok чтобы отделить, но я также хочу распечатать данные один за другим, как data[0], data[1] позже, что невозможно с помощью strtok.

2 Ответов

Рейтинг:
2

Rick York

Ричард на правильном пути. Для этого я использую функцию, которая оборачивает strtok в цикл и сохраняет указатель на каждый токен, найденный в массиве. Он не идеально подходит для работы с CSV-файлами, потому что он не обрабатывает запятые, встроенные в строку в кавычках правильно. Вот как это выглядит :

int ParseTokens( char * buffer, const char * delims, char * tokens[], int maxTokens )
{
    char * cptr = nullptr;
    char * pbuffer = buffer;
    int tokenCount = 0;
    int x;
    for( x = 0; x < maxTokens; x += 1 )
    {
        cptr = strtok( pbuffer, delims );
        if( ! cptr )
            break;

        tokens[ tokenCount ] = cptr;
        ++tokenCount;
        pbuffer = nullptr;
    }
    return tokenCount;
}
Чтобы вызвать его вы можете сделать это :
#define MAX_TOKENS 16
    char * tokens[ MAX_TOKENS ] = { nullptr };
    const char * delimiters = ",";
    int tokenCount = ParseTokens( string, delimiters, tokens, MAX_TOKENS );


Rick York

Если вам нужно обрабатывать запятые в строке в кавычках, вы можете выполнить двухэтапный синтаксический анализ, где сначала разделяете строки в кавычках, а затем удаляете значения, разделенные запятыми. Обратите внимание, что strtok разрушителен в том смысле, что он обнуляет токены, поэтому, если вам нужно знать, что такое разделители, это не самая лучшая вещь для синтаксического анализа.

Richard MacCutchan

Совершенно верно, я бы, конечно, не использовал объявленный массив фиксированного размера в реальной ситуации.

Rick York

У меня есть еще одна версия, которая использует вектор токенов, но эта тема-C. Есть также версия, которая не использует strtok, поэтому она не разрушительна. Это делает вектор скопированных строк и разделителей, поэтому он довольно медленный, но полезный для определенных целей. Я делаю много простых, основанных на строках синтаксических анализов, и это семейство функций охватывает около 95% моих вариантов использования.

Рейтинг:
0

Richard MacCutchan

То strtok функция будет делать то, что вы хотите, если вы действительно захватываете каждое поле, когда вы его маркируете. Если вы знаете, что в каждой строке есть ровно два поля, то:

char* data[2];
data[0] = strtok(line, " ,");
data[1] = strtok(NULL, " ,");