在C语言中使用fprintf写入csv文件时出现奇怪的字符

时间:2022-09-15 15:11:58

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.

我试图将fprintf的名、姓和电话号码插入到CSV文件中。但是在插入之后,会在每行末尾插入额外的奇怪字符和逗号,在读取文件时,会产生问题。

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!!!

请帮助! ! !

2 个解决方案

#1


0  

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.

当您使用fscanf(fp,“%s %s,%s”,phone_directory[i]。First_Name、phone_directory[我]。Last_Name、phone_directory[我].Phone_Number);要读取abc xyz、65656565这样的字符串,第二个%s将读取整个xyz、6565656565部分,而不是以逗号结束。

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.

fscanf()返回成功分配的数量(或EOF on error)。您可以检查它的返回值(在本例中应该是3,如果成功的话),看看是否所有的变量都被赋值了。

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.

如果50是每个字符数组的大小。需要最后一个字符来存储\0字符。

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

另外,检查fopen()的返回值,查看文件是否已成功打开。它在错误时返回NULL。

For example,

例如,

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

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

正如评论中所建议的,阅读这篇文章。

#2


0  

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

首先:为什么while (!feof (file))总是错的?

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.

fscanf和friends的一个问题是,他们将在输入缓冲区中保留换行,这是fscanf后续调用的一个问题,特别是如果您混合了不同的转换说明符。在你陈述格式的方式上也有一个错误,在后面的答案中会有更多。如果您想知道如何在while循环中使用sscanf,请阅读本文。

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

您应该检查fscanf的返回值,它会告诉您进行了多少转换,如果达到EOF:

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.

我将参数改为s1, s2和s3,因为初始值太长,很难读。想法才是最重要的。

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.

在这里,当fscanf没有转换所有三个值时,当fscanf到达EOF时,结束循环。但是,问题是很难从错误中恢复,因为您不知道错误发生的确切位置。但是还有第二个问题,我在后面的部分解释了。

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):

由于这个原因,使用fget读取整行,然后使用sscanf解析这行要优越得多。如果sscanf未能进行解析,您可以恢复并使用其他解析策略(例如使用strtok或strstr等):

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.

%s,%s的一个问题是,对于输入“a,b”,只有一个字符串将被转换:“a,b”。这是因为%s匹配一个非空白字符序列,而不是空白字符,所以scanf在找到非空白字符之前不会停止。这就是为什么我把它改为“% ^,,% s”这第一个转换匹配一切直到逗号。

#1


0  

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.

当您使用fscanf(fp,“%s %s,%s”,phone_directory[i]。First_Name、phone_directory[我]。Last_Name、phone_directory[我].Phone_Number);要读取abc xyz、65656565这样的字符串,第二个%s将读取整个xyz、6565656565部分,而不是以逗号结束。

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.

fscanf()返回成功分配的数量(或EOF on error)。您可以检查它的返回值(在本例中应该是3,如果成功的话),看看是否所有的变量都被赋值了。

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.

如果50是每个字符数组的大小。需要最后一个字符来存储\0字符。

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

另外,检查fopen()的返回值,查看文件是否已成功打开。它在错误时返回NULL。

For example,

例如,

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

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

正如评论中所建议的,阅读这篇文章。

#2


0  

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

首先:为什么while (!feof (file))总是错的?

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.

fscanf和friends的一个问题是,他们将在输入缓冲区中保留换行,这是fscanf后续调用的一个问题,特别是如果您混合了不同的转换说明符。在你陈述格式的方式上也有一个错误,在后面的答案中会有更多。如果您想知道如何在while循环中使用sscanf,请阅读本文。

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

您应该检查fscanf的返回值,它会告诉您进行了多少转换,如果达到EOF:

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.

我将参数改为s1, s2和s3,因为初始值太长,很难读。想法才是最重要的。

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.

在这里,当fscanf没有转换所有三个值时,当fscanf到达EOF时,结束循环。但是,问题是很难从错误中恢复,因为您不知道错误发生的确切位置。但是还有第二个问题,我在后面的部分解释了。

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):

由于这个原因,使用fget读取整行,然后使用sscanf解析这行要优越得多。如果sscanf未能进行解析,您可以恢复并使用其他解析策略(例如使用strtok或strstr等):

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.

%s,%s的一个问题是,对于输入“a,b”,只有一个字符串将被转换:“a,b”。这是因为%s匹配一个非空白字符序列,而不是空白字符,所以scanf在找到非空白字符之前不会停止。这就是为什么我把它改为“% ^,,% s”这第一个转换匹配一切直到逗号。