简单循环中不可预测的行为来检查文件中是否存在 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++;
}
下面是 函数 的代码,它检查提供给它的行和列 '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++;
}