Strange characters when writing to csv files using fprintf in C

user8859314 Source

I am trying to insert First Name, Last Name and Phone Number using fprintf to a CSV file. But after the insertion additional strange characters and commas are being inserted at the end of each line, and while reading the file it is creating problems.

Following is my code:

FILE *fp;
    fp = fopen(filePath, "r");
    int i = 0;
***** Writing *****
FILE *fp;
    fp = fopen("input.csv", "a");
    fprintf(fp,"%s %s ,%s\n", firstname, lastname , phone_number);

***** Reading *****

while(!feof(fp)){   
        fscanf(fp, "%s %s,%s", phone_directory[i].First_Name, phone_directory[i].Last_Name, phone_directory[i].Phone_Number);
        printf("%s %s,%s\n", phone_directory[i].First_Name, phone_directory[i].Last_Name, phone_directory[i].Phone_Number);
        i=i+1;
}

***** Input ******

//First Entry

abc xyz,65656565

//Second Entry

uvw efg,6979679679

***** Output *****

abc xyz,65656565,
, uvw,
efg,6979679679 ,,
 ,

Please Help!!!

ccsvprintfscanf

Answers

answered 3 months ago J...S #1

When you use fscanf(fp, "%s %s,%s", phone_directory[i].First_Name, phone_directory[i].Last_Name, phone_directory[i].Phone_Number); to read a string like abc xyz,65656565, the second %s will read the entire xyz,65656565 part instead of stopping by the comma.

To avoid this, you can use

fscanf(fp, "%s %[^,],%s", phone_directory[i].First_Name, phone_directory[i].Last_Name, phone_directory[i].Phone_Number);

%[^,] means to keep scanning till but not including a , is encountered.

fscanf() returns the number of successful assignments (or EOF on error). You can check its return value (which in this case should be 3 if successful) to see if all the variables were assigned values.

if( fscanf(fp, "%s %[^,],%s", str1, str2, str3)!=3 )
{
    printf("\nSomething went wrong!");
}

To prevent overflow, you might want to specify the filed width in the format string like

fscanf(fp, "%49s %49[^,],%49s", str1, str2, str3)

if 50 is the size of each character array. The last character would be needed to store the \0 character.

Also, check the return value of fopen() to see if the file was successfully opened or not. It returns NULL on error.

For example,

if( (fp=fopen('input.txt', 'r'))==NULL )
{
    perror("\nError opening file!");
}

And as was suggested in the comments, read this post.

answered 3 months ago Pablo #2

First things first: Why is while ( !feof (file) ) always wrong?

A problem with fscanf & friends is that they will leave the newline in the input buffer and this is a problem for subsequent calls of fscanf, specially if you mix different conversion specifiers. There is also an error in the way you stated the format, more on this later in the answer. If you want to know how to use sscanf in a while-loop, read this.

You should check the return value of fscanf, it tells you how many conversions were done and if EOF has been reached:

int convs;

while((convs = fscanf(fp, "%s %[^,],%s", s1, s2, s3)) && convs != 3 && convs != EOF)
{
    printf("%s %s,%s\n", s1, s2, s3);
    i++;
}

I changed the arguments to s1, s2 and s3 because you orginal are just too long and it's hard to read. The idea is what matters.

Here you end the loop when fscanf did not convert all three values and when fscanf reached EOF. The problem with this is however that it is hard to recover from errors, because you don't know exactly where it happened. There is a second problem though, which I explaint in the next part of the answer.

For this reason it is far superior to read the whole line with fgets and then to parse it with sscanf. If sscanf fails to parse, you can recover and use other parsing strategies (such as using strtok, or strstr, etc):

char line[1024];

while(fgets(line, sizeof line, fp))
{
    int convs = sscanf(line, "%s %[^,],%s", s1, s2, s3);
    if(convs != 3)
    {
        // error handling
        // return/exit/use another parsing strategy/whatever
    }
}

One problem with %s,%s is that for the input "a,b", only one string will be converted: "a,b". That's because %s matches a sequence of non-white-space characters and , is not a white-space, so scanf won't stop until it finds a non-white-space character. That's why I changed it to "%[^,],%s" so that the first conversion matches everything until the comma.

comments powered by Disqus