0

I have a csv file that looks like this:

Jake, 25, Montreal
Maria, 32, London
Alex, 19, New York
Jake, 22, Dubai

The function I'm trying to implement is find_name that should iterate through the first field of each record and compare it to the name that is being searched for.

I've tried fgets, fscanf, but either the code doesn't work or I get a segmentation fault.

This is what I have so far:

void find_name(const char *csv_filename, const char *name){
    FILE *csvFile = fopen(csv_filename, "r");
    char word[1000];

    if (csvFile == NULL)
            exit(EXIT_FAILURE);

    while ( !feof(csvFile) ) {
            fscanf(csvFile, "%s%*[^,]", word);
            if ( strcmp(word, name) == 0 )
                    printf("name found");
    }
    fclose(csvFile);
}

Any help is appreciated.

EDIT: I would not like to use any tokenizer function, I'd rather understand how to use fscanf.

Sami
  • 185
  • 2
  • 15
  • Possible duplicate of [Read .CSV file in C](https://stackoverflow.com/questions/12911299/read-csv-file-in-c) – Dougie Mar 29 '19 at 22:09
  • 2
    First, you should read [Why is “while (!feof(file))” always wrong?](https://stackoverflow.com/q/5431941/3545273). Then you should test the return value from `fscanf`, finally you should use `%999s` for a buffer of size 1000... – Serge Ballesta Mar 29 '19 at 22:12
  • 1
    `"%s%*[^,]"` is certainly amiss. Thinking of `"%999s%*1[,]"` ? – chux - Reinstate Monica Mar 29 '19 at 22:27
  • regarding: ` if (csvFile == NULL) exit(EXIT_FAILURE);` When an error occurs, always inform the user before exiting. When the error is from a C library function, also output the text reason the system thinks the error occurred. Suggest: using: `perror( "fopen failed" );` just before the call to `exit()` – user3629249 Mar 29 '19 at 22:57
  • 1
    "I'd rather understand how to use fscanf." --> `fscanf()` is not your friend here. Use `fgets()`, then parse the string. – chux - Reinstate Monica Mar 29 '19 at 23:10
  • regarding this line: `fscanf(csvFile, "%s%*[^,]", word);` it should replace the call to `feof()` in the `while()` statement and be written as: `while( fscanf( csvFile, " %999[^,] %*[^'\n']", word) == 1)` Notice the leading space to consume the white space (the newline) left over from the prior call to `fscanf()` – user3629249 Mar 29 '19 at 23:49

2 Answers2

0

If you read one field at a time, it becomes quite tricky to deal with the end of a line, so suggest you take it a line at a time, something like:

int FieldScanCount = 0;
char city[1000];
int age = 0;
while ((FieldScanCount = fscanf(csvFile, "%1000[A-Za-z0-9 ],%i,%1000[A-Za-z0-9 ]\r\n", &word, &age, &city)) > 0) {

I've assume there is a \r\n at the end of each line, but depending on your your file this might need just \n.

myk
  • 708
  • 2
  • 8
  • 20
0

regarding:

 while ( !feof(csvFile) ) {
        fscanf(csvFile, "%s%*[^,]", word);
        if ( strcmp(word, name) == 0 )
                printf("name found");
}

suggest using:

while ( fgets( word, sizeof(word), csvFile ) )
{
    char *token = strtok( word, ", " );
    if( strcmp( token, name )  == 0 )
    {
         printf("name found");
    }
}

However, if you do not want to use strtok() then suggest:

while ( fgets( word, sizeof word, csvFile ) )
{
    char *comma = strchr( word, ',');
    *comma = \0';

    if( strcmp( word, name )  == 0 )
    {
         printf("name found");
    }
}

however, if you really want to use the scanf() family of functions:

while ( fgets( word, sizeof word, csvFile ) )
{
    char possibleMatch[1000];
    if( sscanf( "%999[^,]", word, possibleMatch ) == 1 )
    {
        if( strcmp( possibleMatch, name )  == 0 )
        {
            printf("name found");
        }
    }
}

However, if you really want to use fscanf():

while ( fscanf( csvFile, "%999[^,]", word ) == 1 )
{
    if( strcmp( word, name )  == 0 )
    {
        printf("name found");
    }

    //consume rest of input file line
    int ch;
    while( ( ch = getchar() ) != EOF && ch != '\n' ){;}
}

or perhaps even better:

while ( fscanf( csvFile, " %999[^,] %*[^\n]", word ) == 1 )
{
    if( strcmp( word, name )  == 0 )
    {
        printf("name found");
    }
}
user3629249
  • 16,402
  • 1
  • 16
  • 17