逻辑或未按预期运行

时间:2019-01-14 20:54:54

标签: c99

我正在编写一个辅助函数,以检查用户输入的路径是否比缓冲区溢出少2个字符。我正在使用fgets()作为输入,所以我知道两件事。

  1. 最后一个索引将包含一个'\ 0'字符(以null终止的字符)
  2. 如果用户输入的字符超出了我的限制,则字符'\ n'或'\ 0'都不在倒数第二个索引中,例如:char a [n] are:n = 5 my限制将为n = 3,我为换行符char保留2个空格,默认情况下fgets()在最后一个索引
  3. 插入'\ 0'

情况1:用户输入有效路径,其中输入字符<3例如:“ a”

情况2:用户输入有效路径,其中输入字符== 3,例如:“ abc”

情况3:用户输入无效的路径,其中输入的字符> 3,例如:“ abcd”

对于我的问题,我有以下if语句: if(a [n-2]!='\ n'|| a [n-2]!='\ 0')

无论哪种情况,它总是会进入if块,我对为什么感到困惑。只能输入情况3。

我可以使用简单的字符数更改检查方式,即遍历字符串并计算除'\ n'或'\ 0'以外的所有字符,但我确信我编写它的方式应该可以,在尝试其他方法之前,我倾向于弄清楚为什么不这样做。

我已经包括了自上而下调用的函数。该if语句是check_file_name内的第二条if语句

const unsinged int file_name_size = 5;

int main(){
    char file[file_name_size] = {'\0'};
    get_file_name(file);
}

void get_file_name(char file_name[file_name_size]){

int is_valid = 1;

do {
    puts("Please enter the relative path");
    fgets(file_name, file_name_size, stdin);
    is_valid = check_file_name(file_name, is_valid);
} while(is_valid > 0);
}

int check_file_name(char file_name[file_name_size], int is_valid){

if(file_name[0] == '\n') {
    puts("Error: a file path must be provided, you entered nothing. Please enter the relative path");
}

if(file_name[file_name_size - 2] != '\n' || file_name[file_name_size - 2] != '\0') {
    puts("Error: the file path provided is too large.");
    exit(EXIT_FAILURE);
}

else {
    is_valid = 0;
}

return is_valid;
}
就像我上面说的那样,即使我什么也不输入,情况3也应该触发if,但它总是会被触发。如果删除||,这是真正的bugger。并测试||的每一面独立地,它按预期工作。只有结合使用,它才会停止产生正确的结果。在此先感谢您的帮助,对于流格式的任何格式或任何堆栈,我深表歉意。这是我的拳头文章,我有点着急。

我认为我的if语句确实发现了问题。我的印象是,仅if语句的一侧需要标记为false,并且它将跳过。我忘记了这两个条件都必须评估为false才能使其不进入该块。例如:使用案例2作为我的测试是a [n] =“ abc \ n”

a [3] ='\ n'

是否为'\ n'!='\ n'为假(我以为它会在这里跳过,但它也会评估另一面)

是'\ n'!='\ 0'是正确的(我们输入了代码块,哎呀)

对不起,菜鸟错误,感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

TLDR:不要忘了De Morgan的定律:https://en.wikipedia.org/wiki/De_Morgan%27s_laws

if(file_name[file_name_size - 2] != '\n' && file_name[file_name_size] != '\0')

因为我否定了条件,所以我也需要否定运算符。因此,我需要使用&&代替||

!(a || b) != !a || !b

!(a || b) == !a && !b