简单循环中不可预测的行为来检查文件中是否存在 line & col

Unpredictable behaviour in simple loop to check if line & col exists in file

下面是 函数 的代码,它检查提供给它的行和列 'co-ordinates' 是否对传递给它的指针的文件有效。

12 个小时的混乱之后,我不知道为什么会这样 随机

在 运行 这在它自己的源文件上,它会在任何大于 10 的列值处抛出错误。我假设一些过度热情的编译器优化将 q 计数变量和 chk 变量并列,并且由于 '\n' 具有十进制值 10,因此打破了我的循环。

假设,我尝试使用 GCC 进行编译(之前我使用的是 Apple Clang)。同样的问题。

在每个文件上,任何大于某个 random col 值的值都会失败。在一个文件上,这是 12,在另一个文件上,15.. 为什么 ??

void check_valid(FILE *ffind,long long line,long long col){

    long long unsigned i,q; int f=0; i=0;int chk;q=0; // counter, character holder and control variables
    if(line>=1 && col>=1){ // -ve lines/columns invalid
        while(i<line){
            // tests if line is valid for file
            chk = fgetc(ffind);
            if(chk==EOF){
                f=-1;printf("\nInvalid Line.\n");break; // line invalid if EOF encountered before reaching line count
            }
            else if(chk=='\n')
                i++;    
        }
        if(f==0){
            //if line was valid, checks if the col value is valid.
            rewind(ffind); 
            while(i<line-1){chk=fgetc(ffind);if(chk=='\n')i++;} // brings fptr @ last char of prev. line, so the next char read is 1st char of given line.
            while(q<col){
                chk=fgetc(ffind);
                if(chk==EOF||chk=='\n'){ // if EOF or newline found before reaching col, col is invalid.
                    f=-1;printf("\nInvalid column = %d\n",chk);break;
                }
                else
                    q++;
            }
            if(f==0) printf("\nValid !\n");
        }
}

发布的代码有两个问题。

  • if(f==0){ /* line was valid */ } 不会在以下 while(i<line-1) 循环之前重置 i = 0。因为 i == line-1 在前一个循环之后,第二个 while 被完全跳过,读取从文件的开头开始,而不是第 line.

  • if(chk=='\n') 计算结果为真之前,一行不算完整。如果它没有以 \n 换行符终止,这将跳过文件中的最后一行。在最简单的情况下,只有一行 (non-empty) 但没有 \n 终止符的文件将始终无法通过 check_valid 测试。

虽然每个问题都可以轻松修复,但更直接的方法是一次完成检查。

while(i < line){
    chk = fgetc(ffind);
    if(chk == EOF){
        printf("\nInvalid %s.\n", (i == line - 1) ? "Column" : "Line"); break;
    }
    else if(chk == '\n'){
        if(i == line - 1){
            printf("\nInvalid Column.\n"); break;
        }
        i++; q = 0;
    }
    else if(i == line - 1 && q == col - 1){
        printf("\nValid Line/Column.\n"); break;
    }
    else
        q++;
}