使用fprintf和fscanf时出错

使用fprintf和fscanf时出错,c,string,windows,printf,scanf,C,String,Windows,Printf,Scanf,我有一个归档文件results.csv,我需要阅读此归档文件的第一行并将其打印在output.txt上。不知怎的,这是打印随机字符后,一切,我无法找出什么是错的 命令:a.c results.csv 第一行: 日期、主队、客队、主队得分、客队得分、锦标赛、城市、国家、中立 output.txt:日期,主队,客队,主队,客队,比赛,城市,国家,中立,(!£,(!£,(!£,(!£,@,(!£,(!£,(!£,),(!£ #include <stdio.h> #include <s

我有一个归档文件
results.csv
,我需要阅读此归档文件的第一行并将其打印在
output.txt
上。不知怎的,这是打印随机字符后,一切,我无法找出什么是错的

命令:
a.c results.csv

第一行:
日期、主队、客队、主队得分、客队得分、锦标赛、城市、国家、中立

output.txt:
日期,主队,客队,主队,客队,比赛,城市,国家,中立,(!£,(!£,(!£,(!£,@,(!£,(!£,(!£,),(!£

#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;
}
#包括
#包括
#包括
#包括
类型定义结构
{
字符*line1;
char*line1a;
char*line1b;
char*team1;
char*team2;
原因;
查尔*城市;
char*国家;
字符*中性_字段;
}数据;
无效打开_输入(字符*argv[],文件**输入)
{       
if((*input=fopen(argv[1],“r”)==NULL)
{
printf(“%s未找到”\n“,argv[1]);
出口(1);
}
}
无效打开_输出(字符*字符串,文件**输出)
{       
if((*output=fopen(字符串,“w”))==NULL)
{
printf(“%s未找到\n”,字符串);
出口(1);
}
}
无效alloc_数据(数据*d,整数大小)
{
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));
城市=(char*)malloc(4*sizeof(char));
d->country=(char*)malloc(7*sizeof(char));
d->中性_字段=(字符*)malloc(7*sizeof(字符));
}
无效存储(数据*d,文件*输入,文件**输出)
{
fscanf(输入,“%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d[0]。行1,d[0]。队1,d[0]。队2,d[0]。行1a,d[0]。行1b,d[0]。原因,d[0]。城市,d[0]。国家,d[0]。中性字段);
fprintf(*输出,“%s,%s,%s,%s,%s,%s,%s,%s\n”,d[0]。第1行,d[0]。第1组,d[0]。第2组,d[0]。第1a行,d[0]。第1b行,d[0]。原因,d[0]。城市,d[0]。国家,d[0]。中性字段);
}
int main(int argc,char*argv[])
{
文件*输入;
文件*输出;
char*string=“output.txt”;
int size=1000;
打开_输入(argv,&input);
打开\u输出(字符串和输出);
数据*d;
d=(数据*)malloc(尺寸*尺寸(数据));
alloc_数据(d,大小);
存储(d、输入和输出);
免费(d);
返回0;
}

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


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

你的缓冲区不是big足以容纳终止的NUL字节。
scanf
存储该NUL字节(超出缓冲区),但实际拥有该字节的对象可能会覆盖它,因此当
printf
查找NUL时,直到很久以后在内存中才找到它

缓冲区溢出是一个比您所看到的更大的问题,谁知道那些没有为其留出空间的NUL字节正在粉碎哪些对象?以及当您读取一个标题拼写稍有不同的数据文件时会发生什么情况?突然之间,您的硬编码分配大小将比以前更加错误

fscanf(输入,“%s,%s,%s,%s,%s,%s,%s,%s”,d[0]。行1,d[0]。团队1,…

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

您必须更改
fscanf
,如下所示:

fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...
其中3是4-1,4是
d[0]的大小

或者,您可以使用
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;
}
此外,对于每个
malloc
,应该有一个相应的
free

fscanf(输入,“%s,%s,%s,%s,%s,%s,%s,%s”,d[0]。行1,d[0]。团队1,…

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

您必须更改
fscanf
,如下所示:

fscanf(input, "%3[^ ,\n\t],%9[^ ,\n\t],...
其中3是4-1,4是
d[0]的大小

或者,您可以使用
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;
}

另外,对于每个
malloc
都应该有一个相应的
免费

%c
用于打印
char
d[0]。第1行(和其他行)是
char*
。你是说scanf for char数组中的
%s
%c
用于单个char。你将要了解为什么
f()
太可怕了。使用
扫描()读取数据
格式字符串无法通过同一格式字符串可靠地打印。也可以使用
%s
打印
字符*
,但在这里它可能会失败,因为字符数组没有正确终止。另外,您真的需要
文件**输出
在函数
存储
中吗?使用
文件*输出
有什么问题吗>%c
用于打印
char
d[0]。line1
(和其他)是
char*
。您的意思是在scanf for char数组中的
%s
吗?
%c
用于单个字符。您将要了解
scanf()
为什么可怕。使用
scan()读取数据
格式字符串无法通过同一格式字符串可靠地打印。也可以使用
%s
打印
字符*
,但在这里它可能会失败,因为字符数组没有正确终止。另外,您真的需要
函数
存储中的
文件**输出
?使用该函数有什么问题吗