从文件中读取带有空格的固定大小的寄存器

时间:2019-07-02 08:09:07

标签: c file scanf

我正在尝试从c中的文本文件读取固定大小的寄存器。

寄存器的结构如下:

  

00030REGIST X1Y005.0

  • 5个字符为整数
  • 字符串(带空格)的10个字符
  • 浮点数为5个字符

当我尝试读取寄存器时,得到以下结果:

  

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);
}

2 个答案:

答案 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正在寻找特定字符10s(这将失败-下一个字符将是换行符或末尾-file,因为您没有为扫描集指定大小。测试应该针对预期的转化次数;其他任何东西都是某种错误。

如果寄存器名称中可以包含数字,那么您会感到费解,因为REGISTER XVY是12个字符来计算空格(这与您声称寄存器名称最多10个字符的说法相矛盾)。在%12[^\n0-9]中指定小于12的任何值都不会转换该名称和以下数字,因为它将在输入中保留非数字字符。

如果寄存器名称中必须包含数字,则必须采用其他策略。您已读完该行,然后剥离前5位数字并进行转换,剥离后5位数字并进行转换,然后将剩下的作为寄存器名称,可能会除去前导和尾随空白。