【问题标题】:reading a file in C: leading zeros在 C 中读取文件:前导零
【发布时间】:2018-08-15 12:59:49
【问题描述】:

在我的程序中,我试图从文本文件中每行读取两个值。 它适用于我下面的代码,但是当我面对带有前导零的数字时,它会将每个零存储为一个值。

我希望能够阅读例如"007" 是普通的 "7",但我仍然希望能够将 "0" 读取为值。

任何人都可以帮助我改进我的代码或指出可以改进的地方/地方吗?

提前致谢

valuelist.txt

55 009
63 10
12 0

输出

counter: 0 | Value A: 55 Value B: 0 
counter: 1 | Value A: 9 Value B: 0 
counter: 2 | Value A: 9 Value B: 0 
counter: 3 | Value A: 63 Value B: 0 
counter: 4 | Value A: 10 Value B: 0 
counter: 5 | Value A: 12 Value B: 0 
counter: 6 | Value A: 0 Value B: 0 

主要

int main(void) {

        char name[] = "valuelist.txt";
        unsigned int counter = 0;
        unsigned int lines = 3;
        unsigned int num;
        unsigned int numtwo;


        FILE* ff = fopen(name,"r");
        if(ff == NULL) {
             fprintf(stderr, "Error \n");
            return -1;
        }

        char *tempp = (char*) malloc(lines + 1 );

        while(fgets(tempp,lines+1,ff) != NULL){

              sscanf(tempp,"%u %u",&num, &numtwo);

              printf("counter: %u | ",counter);
              printf("Value A: %u ",num);
              printf("Value B: %u \n",numtwo);

              counter++;
        }
        free(tempp);
        tempp = NULL;


return 0;
}

【问题讨论】:

  • 这段代码似乎和你期望的一样。请发布“valuelist.txt”的内容以及预期和实际输出。此外,此代码不会按原样编译,因为未定义 countlinesnumnumtwo
  • 为什么要计算???
  • ...然后读取lines*2字节但只有lines+1字节?
  • @dbush 更新了文件 + 当前输出,认为你看到了什么问题...... – David Dabrue 刚刚编辑
  • 请不要通过更改代码的相关部分来使大多数命令和答案无效,从而使您的问题成为移动目标!

标签: c text-files scanf fgets leading-zero


【解决方案1】:

在您更新的代码和数据中,问题肯定是lines 的值对于您的使用来说太小了。您正在使用它来测量 tempp 缓冲区需要多少空间,但这需要最大行 width (加上一个用于换行符,另一个用于终止符)。相反,您给它一行count,以及一个只有几行的文件。因此,fgets() 会在多次通话中中断您的线路。

您确实可以预先扫描文件以找到合适的宽度,然后分配那么多,但是在这里使用fgets 而不是fscanf 会很麻烦。对于许多问题,确实有理由更喜欢它,但你的问题看起来不像其中之一。这样做可以省去很多麻烦和代码:

unsigned num, numtwo;
while (fscanf(ff, "%u%u", &num, &numtwo) == 2) {
    // update counter, print results, etc...
}

【讨论】:

    【解决方案2】:

    您没有分配足够的空间来读取每一行。您使用行数作为行的长度,但它们并不相同。

    您为 ttemp 分配了 4 个字节 (lines + 1),用于在一行中读取。但是,第一行文本中有 6 个字符。所以第一次调用fgets只读取前3个字节,即"55 "。这就是 sscanf 解析的内容。下一个调用获取接下来的 3 个字节,即 "09\n" 并在换行处停止读取,因此只解析出第一个数字。

    由于您在循环中使用fgets 来读取行并打印内容,因此您实际上不需要知道有多少行。但是,您确实需要知道一条线的最大长度。由于您正在读取两个十进制整数,因此 30 个字节应该足以读取一整行。所以制作一个该大小的固定缓冲区:

        char tempp[30];
        while(fgets(tempp,sizeof(tempp),ff) != NULL){
            ...
    

    【讨论】:

    • Nitpick: fgets(tempp, 4, ff) 从文件中读取最多 3 个字节,而不是 4 个(并在最后一个字节读取后附加一个空终止符)。
    • 首先,感谢您的解释。如果有二十个前导零怎么办?我的问题是,由于创建 valuelist.txt 的程序,我不知道会有多少前导零..
    • @JohnBollinger 很好。固定。
    • @DavidDabrue 如果您无法预测一行的日志,但您知道每行有两个值,那么您最好按照 John Bollinger 的建议直接使用 fscanf。跨度>
    • 每个前导零线变长还是我错了?
    【解决方案3】:

    您的根本问题是您的 lines 变量。它太小了。 (它应该是“线条大小”吗?)

    我建议您去掉lines 变量、tempp 变量和malloc 调用。声明一个数组

    char line[1000];
    

    对于任何可以想象的输入,1000 个字符应该足够长。那么你的循环可以是

    while(fgets(line, sizeof(line), ff) != NULL) { ...
    

    您的其余代码看起来还不错。通过此更改,您应该不会再遇到数字被奇怪地分解的问题了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-26
      • 2014-02-17
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多