首页 > 解决方案 > 对文件内容使用 atoi() 时出现意外结果,逐字符读取

问题描述

我有一个文本文件,其中只有数字(0、1、2 和 3),我想处理数据以了解每个数字出现的次数。

以下程序适用于小文本文件(<100 个数字),但对于较大的文件(我最终需要处理数千个数据),程序会读取文本文件中没有的数字。

这是我的代码:

FILE *file;
char c;
int nb;
int th0 = 0, th1 = 0, th2 = 0, th3 = 0;

file = fopen("../data", "r");

if (file == NULL) {
    printf("ERROR FILE: %s", strerror(errno));
    return EXIT_FAILURE;
}

while (1) {
    if (fscanf(file, "%c", &c) == EOF)
        break;

    nb = atoi(&c);

    printf("%d", nb);

    switch (nb) {
      case 0:
        th0++;
        break;

      case 1:
        th1++;
        break;

      case 2:
        th2++;
        break;

      case 3:
        th3++;
        break;

      default:
        break;
    }
}

我将不胜感激任何建议。

编辑,带有输出的输入文本:

数据文件(181 个数字):

001110120101010102012012021201021202102012012012012010210210210120120230103120130230123201320310231023102302301231203213210131032103210230120320310320213202301320123120312302321023

输出: 读取的结尾不是数据文件中的内容,计数 156 个数字

标签: cfileatoi

解决方案


你的问题是atoi需要一个字符串,你这样称呼它:

nb = atoi(&c);

c只是一个char. 有时这可能会起作用,但您基本上会遇到未定义的行为,因为您不能保证之后的内存c是空的。

相反,您想要以nb不同的方式计算。

nb = c - '0';

这依赖于这样一个事实,即在 ASCII 表中,数字 0 到 9 一起在一个块中。减去“0”的值c将得到该字符的数值......假设它是一个数字。

为了确保它是一个数字,您应该将此if语句包装在您的代码周围

if(isdigit(c)) // Check if c is a digit
    {
    nb = c - '0';

    switch(nb) {
        case 0: th0++;
        break;
    // rest of switch goes here....
         }
    }

推荐阅读