我是否在使用sscanf函数时出错?
我试图通过sscanf从hoge.txt获取数据 但我得到了奇怪的结果 我不明白为什么会这样 请帮忙 我用Borland C/C++5.5.1 for Win32编译并链接了它-如果有帮助的话我是否在使用sscanf函数时出错?,c,C,我试图通过sscanf从hoge.txt获取数据 但我得到了奇怪的结果 我不明白为什么会这样 请帮忙 我用Borland C/C++5.5.1 for Win32编译并链接了它-如果有帮助的话 #include<stdio.h> #include<string.h> int main(int argc, char *argv[]){ FILE *fp; char buf[100]; char name1[100]; char name2
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[]){
FILE *fp;
char buf[100];
char name1[100];
char name2[100];
int distance1;
int distance2;
/* file open */
fp = fopen(argv[1],"r");
if(fp == NULL){
return -1;
}
/* get a line */
fgets(buf,100,fp);
/* change \n to \0 */
strtok(buf,"\n");
/* get values from buf */
sscanf(buf,"%s,%d; %s,%d;",name1,&distance1,name2,&distance2);
/* for tests */
printf("%s\n",name1);
printf("%s\n",name2);
printf("%d\n",distance1);
printf("%d\n",distance2);
return 0;
}
#包括
#包括
int main(int argc,char*argv[]){
文件*fp;
char-buf[100];
字符名称1[100];
字符名称2[100];
整数距离1;
int距离2;
/*文件打开*/
fp=fopen(argv[1],“r”);
如果(fp==NULL){
返回-1;
}
/*接电话*/
fgets(buf,100,fp);
/*将\n更改为\0*/
strtok(buf,“\n”);
/*从buf获取值*/
sscanf(buf、%s、%d;%s、%d;、名称1和距离1、名称2和距离2);
/*测试*/
printf(“%s\n”,名称1);
printf(“%s\n”,名称2);
printf(“%d\n”,距离1);
printf(“%d\n”,距离2);
返回0;
}
【hoge.txt】※就一行
Ramytdb,2683;Voclqmb,5236
【结果】
Ramytdb,2683;
ワLレwD
1.
256使用
sscanf(buf,"%[^,],%d; %[^,],%d;",name1,&distance1,name2,&distance2);
而不是
sscanf(buf,"%s,%d; %s,%d;",name1,&distance1,name2,&distance2);
您的代码失败,因为当看到,
时,%s
不会停止扫描。当遇到\n
或空格时,它停止扫描。在您的例子中,它扫描Ramytdb,2683代码>并在下一个字符为空格时停止。这会把事情搞得一团糟
您还可以通过使用限制要读取的字符量来提供更高的安全性
sscanf(buf,"%99[^,],%d; %99[^,],%d;",name1,&distance1,name2,&distance2);
请注意,字符串末尾的\0
字符需要一个空格,这就是我使用99而不是100的原因
您可以通过检查sscanf
的结果来进一步改进它。返回已填充的变量数。因此,使用
if(sscanf(buf,"%[^,],%d; %[^,],%d;",name1,&distance1,name2,&distance2)==4)
//sscanf was successful
else
//sscanf was not successful
您还可以在sscanf
的末尾添加%*c
。这将读取一个字符并丢弃它。如果文件中的行尾有一个\n
字符,这可能很有用。使用
sscanf(buf,"%[^,],%d; %[^,],%d;",name1,&distance1,name2,&distance2);
而不是
sscanf(buf,"%s,%d; %s,%d;",name1,&distance1,name2,&distance2);
您的代码失败,因为当看到,
时,%s
不会停止扫描。当遇到\n
或空格时,它停止扫描。在您的例子中,它扫描Ramytdb,2683代码>并在下一个字符为空格时停止。这会把事情搞得一团糟
您还可以通过使用限制要读取的字符量来提供更高的安全性
sscanf(buf,"%99[^,],%d; %99[^,],%d;",name1,&distance1,name2,&distance2);
请注意,字符串末尾的\0
字符需要一个空格,这就是我使用99而不是100的原因
您可以通过检查sscanf
的结果来进一步改进它。返回已填充的变量数。因此,使用
if(sscanf(buf,"%[^,],%d; %[^,],%d;",name1,&distance1,name2,&distance2)==4)
//sscanf was successful
else
//sscanf was not successful
您还可以在sscanf
的末尾添加%*c
。这将读取一个字符并丢弃它。如果文件中的行尾有一个\n
字符,这可能会很有用。从手册页面开始转换
匹配一系列非空白字符;下一个指针
必须是指向字符数组的指针,该数组的长度足以容纳
输入序列和添加的终止空字节('\0')
自动地输入字符串在空白处或最大值处停止
字段宽度,以先到者为准
因此,前%s将读取尽可能多的非空白字符。包括逗号。因此,通过检查返回值,您会注意到这一点
您将需要使用另一个转换-可能是']'?查看网页将帮助您从手册页面决定转换
匹配一系列非空白字符;下一个指针
必须是指向字符数组的指针,该数组的长度足以容纳
输入序列和添加的终止空字节('\0')
自动地输入字符串在空白处或最大值处停止
字段宽度,以先到者为准
因此,前%s将读取尽可能多的非空白字符。包括逗号。因此,通过检查返回值,您会注意到这一点
您将需要使用另一个转换-可能是']'?查看网页将帮助您确定第一个错误,而不是检查sscanf()
的返回值。。。这将告诉您成功解析的参数数…并且,尝试使用返回值strtok()
@Gopi-its将换行符设置为空字符(如果存在);这不是一种很常见的方法。当然,在这种情况下它是毫无意义的。@chux如果只显示“\n”
,OP的代码应该无法完全去除分隔符,是的,返回NULL。第一个错误,没有检查sscanf()的返回值。。。这将告诉您成功解析的参数数…并且,尝试使用返回值strtok()
@Gopi-its将换行符设置为空字符(如果存在);这不是一种很常见的方法。当然,在这种情况下它是毫无意义的。@chux如果只显示“\n”
,OP的代码应该无法完全去除分隔符,是的,返回NULL。建议char虚拟;sscanf(buf,“%99[^,],%d;%99[^,],%d;%c,…,&dummy)==4”
,并检查结果。注:不需要最后的代码>除非像%c@chux,如果成功,您评论中的sscanf
将返回5,对吗?只有4是正确的。5表示在之后发生了额外的事情代码>。有许多方法可以确保代码>已发生,其他情况均未发生。这只是一个简单的想法n在最后的之后代码>是另一种方法。intn;sscanf(bif,…%n,…&n)
只需将偏移量保存在buf
中,此时正在进行扫描。示例int n=0;sscanf(buf,“%[^,]”,%d;“%[^,]”,%d;%n“,…,&n);如果(n&&buf[n]=='\0')成功()
。让我们建议char dummy;sscanf(buf),%99[^,],%d;%99[^,],%d;