【问题标题】:Error using fprintf and fscanf使用 fprintf 和 fscanf 时出错
【发布时间】:2018-06-07 14:22:08
【问题描述】:

我有一个存档results.csv,我需要阅读该存档的第一行并将其打印到output.txt。不知何故,它在所有内容之后都打印了随机字符,我不知道出了什么问题。

命令:a.c results.csv

第一行: date,home_team,away_team,home_score,away_score,tournament,city,country,neutral

输出.txt:date,home_team,away_team,home_score,away_score,tournament,city,country,neutral,(!£,(!£,(!£,(!£,(!£,@,£,(!£,(!£

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>


typedef struct
{
    char *line1;
    char *line1a;
    char *line1b;
    char *team1;
    char *team2;
    char *reason;
    char *city;
    char *country;
    char *neutral_field;

}data;


void open_input(char *argv[], FILE **input)
{       

        if((*input=fopen(argv[1], "r")) == NULL)
        {
            printf("%s not found\n", argv[1]);
                exit(1);
        }

}
void open_output(char *string, FILE **output)
{       

        if((*output=fopen(string, "w")) == NULL)
        {
            printf("%s not found\n", string);
                exit(1);
        }

}

void alloc_data(data *d, int size)
{
d->line1 = (char*)malloc(4*sizeof(char)); 
d->team1 = (char*)malloc(9*sizeof(char)); 
d->team2 = (char*)malloc(9*sizeof(char)); 
d->line1a = (char*)malloc(10*sizeof(char)); 
d->line1b = (char*)malloc(10*sizeof(char)); 
d->reason = (char*)malloc(10*sizeof(char)); 
d->city = (char*)malloc(4*sizeof(char)); 
d->country = (char*)malloc(7*sizeof(char)); 
d->neutral_field = (char*)malloc(7*sizeof(char)); 
}

void store(data *d, FILE *input, FILE **output)
{

    fscanf(input,  "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );
    fprintf(*output,  "%s,%s,%s,%s,%s,%s,%s,%s,%s\n", d[0].line1, d[0].team1, d[0].team2, d[0].line1a, d[0].line1b, d[0].reason, d[0].city, d[0].country, d[0].neutral_field );


}

int main(int argc, char *argv[])
{
    FILE *input;
    FILE *output;
    char *string = "output.txt";
    int size = 1000;

    open_input(argv, &input);   
    open_output(string, &output);   

    data *d;
    d = (data*)malloc(size*sizeof(data)); 
    alloc_data(d, size);

    store(d, input, &output);

    free(d);

    return 0;
}

【问题讨论】:

  • %c 用于打印chard[0].line1(和其他人)是char*
  • 你的意思是 %s 在 scanf for char 数组中吗? %c 用于单个字符。
  • 您即将了解为什么scanf() 如此可怕。使用scan() 格式字符串读取的数据无法通过相同的格式字符串可靠地打印。
  • 也使用%s 打印char*,但这里可能会失败,因为char 数组没有正确终止
  • 另外,你真的需要FILE **output 在函数store 中吗?使用FILE *output 有什么问题?

标签: c string windows printf scanf


【解决方案1】:

fscanf(input, "%s,%s,%s,%s,%s,%s,%s,%s,%s", d[0].line1, d[0].team1,...

上面的代码试图将整行读入d[0].line1,这会导致缓冲区溢出。 team1,其余的将包含未初始化的数据。

你必须改变fscanf如下:

fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...

其中 3 是 4 - 1,4 是 d[0].line1 的大小

您也可以使用strtok

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void store(FILE *input, FILE *output)
{
    char buf[500];
    while(fgets(buf, sizeof(buf), input))
    {
        //strip end-of-line from `buf`
        if(strlen(buf))
            if(buf[strlen(buf) - 1] == '\n')
                buf[strlen(buf) - 1] = 0;

        //tokenize with strtok
        char *token = strtok(buf, ",");
        while(token)
        { 
            fprintf(output, "%s", token);
            token = strtok(NULL, ",");
        }
        fprintf(output, "\n");
    }
}

int main(int argc, char *argv[])
{
    FILE *input = fopen("input.txt", "r");
    FILE *output = fopen("output.txt", "w");
    store(input, output);
    return 0;
}

使用上面的代码,您不需要额外的结构。


如果您确实使用数据结构,则必须更加小心。似乎您正在尝试创建一个包含 1000 个 data 的数组,但以下仅创建一个超大指针,而不是一个 data 数组
int size = 1000;
data *d;
d = (data*)malloc(size*sizeof(data)); 
alloc_data(d, size);

此外,对于每个malloc,应该有一个对应的free

【讨论】:

    【解决方案2】:

    您的缓冲区不够大,无法容纳终止的 NUL 字节。 scanf 存储该 NUL 字节(超出缓冲区),但真正拥有该字节的对象可能会覆盖它,因此当printf 查找 NUL 时,它直到很久以后才在内存中找到它。

    缓冲区溢出是一个比您所看到的更大的问题,谁知道您没有为这些 NUL 字节腾出空间的对象是什么?当您读取标题拼写略有不同的数据文件时会发生什么?突然之间,您硬编码的分配大小将比现在更加错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-25
      相关资源
      最近更新 更多