读入文本文件 - 一次1个字符。用C

时间:2010-11-14 21:05:12

标签: c arrays text-files

我正在尝试逐行读取文本文件并单独处理每个字符。

例如,我的文本文件中的一行可能如下所示: ABC XXXX XXXXXXXX ABC

行中总会有不同数量的空格。但是相同数量的字符(包括空格)。

这就是我到目前为止......

char currentLine[100];
fgets(currentLine, 22, inputFile);

然后我尝试遍历currentLine数组并使用每个字符......

for (j = 0; j<22; j++) {
    if (&currentLine[j] == 'x') {
        // character is an x... do something
     }
}

任何人都可以帮我解决这个问题吗?

你可能会说 - 我刚刚开始使用C。

4 个答案:

答案 0 :(得分:8)

以下是按字符处理文件的规范方法:

#include <stdio.h>

int main(int argc, char **argv) 
{

    FILE *fp;
    int c;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s file.txt\n", argv[0]);
        exit(1);
    }
    if (!(fp = fopen(argv[1], "rt"))) {
        perror(argv[1]);
        exit(1);
    }
    while ((c = fgetc(fp)) != EOF) {

        // now do something with each character, c.

    }
    fclose(fp);
    return 0;
}

请注意,c已声明为int,而非char,因为EOF的值与可存储在char中的所有字符不同

对于更复杂的解析,一次读取一行文件通常是正确的方法。但是,您希望对未正确格式化的输入数据更加防御。从本质上讲,编写代码来假设外部世界是敌对的。永远不要假设文件完好无损,即使它是您刚写的文件。

例如,您使用100个字符的缓冲区来读取行,但将读取的数量限制为22个字符(可能是因为您知道22是“正确的”行长度)。额外的缓冲区空间很好,但您应该考虑文件可能包含长度错误的行的可能性。即使这是一个错误,您还必须决定如何处理该错误并重新同步您的流程或放弃它。

编辑:我为规范的简单案例添加了一些假定的程序的骨架。对于C的新用户,有一些事情要指出。首先,我假设一个简单的命令行界面来获取要处理的文件的名称,并使用argc验证参数是否真的存在。如果没有,我打印一个简短的用法消息,利用argv[0]的内容按惯例以某种有用的方式命名当前程序,并以非零状态退出。

我打开文件以便以文本模式阅读。文本和二进制模式之间的区别在Unix平台上并不重要,但在其他模式上尤为重要,尤其是Windows。由于讨论是一次处理文件一个字符,我假设文件是​​文本而不是二进制文件。如果fopen()失败,则返回NULL并将全局变量errno设置为描述性代码,以解释失败的原因。对perror()的调用将errno翻译为人类可读的内容,并将其与提供的字符串一起打印出来。这里我提供了我们试图打开的文件的名称。结果看起来像“foo.txt:没有这样的文件”。在这种情况下,我们也以非零状态退出。我没有打扰过,但出于不同的原因退出不同的非零状态代码通常是明智的,这可以帮助shell脚本更好地理解错误。

最后,我关闭了文件。原则上,我还应该测试fclose()的失败。对于只读取文件的进程,大多数错误条件已经被检测为某种内容错误,并且在结束时不会添加任何有用的状态。但是,对于文件写入,在调用fclose()之前,您可能不会发现某些I / O错误。在编写文件时,最好检查返回代码,并期望在触摸文件的任何调用中处理I / O错误。

答案 1 :(得分:4)

您不需要地址运算符(&amp;)。你试图比较变量currentLine [j]和'x'的值,而不是它的地址。

答案 2 :(得分:1)

ABC XXXX XXXXXXXX ABC有21个字符。还有换行符(22个字符)和终止空字节(23个字符)。

您需要fgets(currentLine, 23, inputFile);才能阅读整行。

但是你将currentLine声明为100的数组。为什么不全部使用呢?

fgets(currentLine, sizeof currentLine, inputFile);

当使用所有这些时,并不意味着每次调用fgets时系统都会放置多行。阅读fgets后,'\n'始终停止。

答案 3 :(得分:0)

尝试

while( fgets(currentLine, 100, inputFile) ) {
    for (j = 0; j<22; j++) {
        if (/*&*/currentLine[j] == 'x') { /* <--- without & */
        // character is an x... do something
        }
    }
}