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

读取文本文件-一次读取1个字符。使用C,c,arrays,text-files,C,Arrays,Text Files,我试图逐行读取文本文件,并分别处理每个字符 例如,我的文本文件中的一行可能如下所示: ABC XXXXXXXX ABC 行中始终会有不同数量的空格。但是相同数量的字符(包括空格) 这就是我目前所拥有的 char currentLine[100]; fgets(currentLine, 22, inputFile); 然后我尝试遍历currentLine数组并处理每个字符 for (j = 0; j<22; j++) { if (&currentLine[j] == 'x'

我试图逐行读取文本文件,并分别处理每个字符

例如,我的文本文件中的一行可能如下所示:
ABC 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
     }
}

for(j=0;j您不需要地址运算符(&)。您正在尝试将变量currentLine[j]的值与“x”进行比较,而不是它的地址。

请尝试

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

对于(j=0;j类似的内容,以下是一个字符一个字符地处理文件的标准方法:

#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;
}
#包括
int main(int argc,字符**argv)
{
文件*fp;
INTC;
如果(argc!=2){
fprintf(stderr,“用法:%s file.txt\n”,argv[0]);
出口(1);
}
如果(!(fp=fopen(argv[1],“rt”)){
perror(argv[1]);
出口(1);
}
而((c=fgetc(fp))!=EOF){
//现在对每个角色做些什么,c。
}
fclose(fp);
返回0;
}
请注意,
c
声明为
int
,而不是
char
,因为
EOF
的值不同于
char
中可以存储的所有字符

对于更复杂的解析,一行一行地读取文件通常是正确的方法。但是,您需要对格式不正确的输入数据进行更多的防御。本质上,编写代码时假设外部世界是敌对的。永远不要假设文件是完整的,即使它是您刚刚创建的文件写

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

Edit:我已经为规范的简单案例添加了一些假定的程序其余部分的框架。对于C的新用户,这里有几点需要指出。首先,我假定使用一个简单的命令行界面来获取要处理的文件名,并使用
argc
验证是否确实存在参数。如果不,我利用
argv[0]
的内容打印一条简短的用法消息,按照惯例,它以某种有用的方式命名当前程序,并以非零状态退出

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


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

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

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

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

fgets(currentLine, sizeof currentLine, inputFile);

当使用所有这些功能时,这并不意味着每次调用
fgets
时系统将放置多行。
fgets
总是在读取
后停止。'\n'

+1使用
fgetc
保持简单。初学者不太可能希望/需要使用数组和指针在问题是关于一次处理一个字符。
fgets
将始终读取n-1个字节,或者直到第一个回车符返回,然后nul终止缓冲区,所以您只需要
currentline
为22个字节(如果每行不超过21个字符)。@Martin:回车符本身呢?