'My code reads the last field with the first field of he next line from csv. Any advice fixing it please?

I want the program to read the last field of the line without reading the next field on the next line. I tried separating the lines with commas but in my opinion, it was not the correct approach to fix the problem. I saw some tutorial videos and all of them don't have to separate each lines with commas in the source csv file.

Here are the details about my code and my input file.

My struct defination:

typedef struct UserData{
    char NAME[50];
    char LAST[50];
    char TEL[11]; 
    } USER;

This is what my csv file look like:

test,test,1234567890
qwerty,qwertyy,0123456789
qqqqq,wwwww,1323284828
eeeee,rrrrr,4342424950
test1,test1,1234562234

This is my function used to read data in to struct:

int GetUserData(USER users[])
{
    FILE * file = fopen("test.csv", "r");

    if (file == NULL)
    {
        printf("Error opening file.\n");
        return 1;
    }

    char buffer[1024]; //storing 1024 lines into buffer

    int row_count = 0;
    int field_count = 0;

    int i = 0;

    while (fgets(buffer, sizeof(buffer), file)) //inputting data in file to the struct
    {
        field_count = 0;
        row_count++;
        if (row_count == 1) continue; //Skip header
        char *field = strtok(buffer, ","); //separate buffer with commas
        while(field)
        {
            if(field_count == 0)
                strcpy(users[i].NAME, field);

            if(field_count == 1)
                strcpy(users[i].LAST, field);

            if(field_count == 2)
                strcpy(users[i].TEL, field);

            field = strtok(NULL, ","); //update field value
            field_count++;
        }
        i++;
    }
    fclose(file);

    return row_count;
}
void PrintUserData(USER users[], int row_count)
{
    //printf("%d", row_count);                //row_count counts header which is ignored
    for(int i = 0; i < row_count - 1; i++){   //row_count has to be - 1
        printf("\nName: %s\nLast: %s\nTel : %s", users[i].NAME, users[i].LAST, users[i].TEL);
        printf("\n");
    }
}

This is the output:

Name: qwerty
Last: qwertyy
Tel : 0123456789
qqqqq

Name: qqqqq
Last: wwwww
Tel : 1323284828
eeeee

Name: eeeee
Last: rrrrr
Tel : 4342424950
test1

Name: test1
Last: test1
Tel : 1234562234

I want the output to be like this instead:

Name: qwerty
Last: qwertyy
Tel : 0123456789

Name: qqqqq
Last: wwwww
Tel : 1323284828

Name: eeeee
Last: rrrrr
Tel : 4342424950

Name: test1
Last: test1
Tel : 1234562234


Solution 1:[1]

fgets leaves the line feed character of each line as the last character read. You can find it by calling strrchr(field,'\n') and then replace it with a \0.

Depending on how well you trust this file, it might be wise to check the string length of each substring before calling strcpy. In that case you can integrate the line feed check with that code:

size_t length = strlen(field);
if(field[length-1] == '\n')
{
  field[length-1] = '\0';
  length--;
}

if(length > TEL_SIZE) // a constant of value 10
{
  halt_and_catch_fire();
}

// strcpy code here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lundin