我正在尝试从c中的文本文件读取固定大小的寄存器。
寄存器的结构如下:
00030REGIST X1Y005.0
当我尝试读取寄存器时,得到以下结果:
00030REGIST X1Y005.00.00000
在字符串末尾得到0.00000
#include <stdio.h>
#include <stdlib.h>
int main () {
int id;
float price;
char desc[11];
FILE * data_file;
//Reading from file
if(!(data_file = fopen("./products.txt","r"))){
printf("\nError reading file\n");
exit(2);
}
// The value of the register is 00030REGIST X1Y005.0
// But i get 00030REGIST X1Y005.00.00000
while (fscanf(data_file,"%05d %[^\n]10s %05f", &id, desc, &price) != EOF) {
printf("%05d%s%05f\n",id , desc, price);
}
fclose(data_file);
return(0);
}
答案 0 :(得分:1)
编辑:我将程序更改为读取10个可以包含数字的字符串字符。
格式说明符%[^\n]10s
是%s
和%[]
的奇怪混合体。我建议以下内容,此处仅出于示例目的而使用单个字符串,并为清楚起见在输出中添加了换行符。
#include <stdio.h>
int main(void)
{
int id;
float price;
char desc[11];
char input[] = "00030REGIST X1Y005.0";
int res = sscanf(input, "%d%10[^\n]%f", &id, desc, &price);
if(res == 3) {
printf("%05d\n%s\n%05f\n",id , desc, price);
}
}
程序输出:
00030 REGIST X1Y 5.000000
答案 1 :(得分:1)
您有:
while (fscanf(data_file,"%05d %[^\n]10s %05f", &id, desc, &price) != EOF)
您可能需要:
while (fscanf(data_file,"%5d %40[^\n0-9] %5f", &id, desc, &price) == 3)
40
基于desc
的大小(您在格式字符串中指定的长度要比为数组声明的长度少1)。请注意,扫描集%[…]
本身就是转换。您的版本中的10s
正在寻找特定字符1
,0
和s
(这将失败-下一个字符将是换行符或末尾-file,因为您没有为扫描集指定大小。测试应该针对预期的转化次数;其他任何东西都是某种错误。
如果寄存器名称中可以包含数字,那么您会感到费解,因为REGISTER XVY
是12个字符来计算空格(这与您声称寄存器名称最多10个字符的说法相矛盾)。在%12[^\n0-9]
中指定小于12的任何值都不会转换该名称和以下数字,因为它将在输入中保留非数字字符。
如果寄存器名称中必须包含数字,则必须采用其他策略。您已读完该行,然后剥离前5位数字并进行转换,剥离后5位数字并进行转换,然后将剩下的作为寄存器名称,可能会除去前导和尾随空白。