【问题标题】:Logical OR not operating as expected逻辑 OR 未按预期运行
【发布时间】:2019-01-14 20:54:53
【问题描述】:

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

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

案例1:用户输入一个有效路径,其中输入字符

案例 2:用户输入有效路径,其中 input chars == 3 ex: "abc"

案例 3:用户输入的路径无效,其中 input chars > 3 ex: "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;
}

就像我上面所说的,只有 case 3 应该触发 if 但它总是被触发,即使我什么也没输入。如果您删除 ||,这是真正的错误。并测试 || 的每一侧独立地,它按预期工作。只有结合起来,它才会停止产生正确的结果。在此先感谢您的帮助,对于任何格式或任何堆栈溢出错误,我深表歉意。这是我的第一篇文章,我有点着急。

我想我实际上已经发现了我的 if 语句的问题。我的印象是 if 语句的只有一侧需要被标记为 false 并且它会跳过。我忘记了这两个条件都必须评估为 false 才能使其不进入块。例如:使用案例 2 作为我的测试是 a[n] = "abc\n"

a[3] = '\n'

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

does '\n' != '\0' true(我们进入了区块,哎呀)

抱歉新手错误并感谢您的帮助!

【问题讨论】:

  • 您是否尝试过在调试器中运行您的代码并检查您的变量以确保您的假设是正确的?
  • a [n-2] != '\n' || a [n-2] !='\0'总是正确的a[n-2] 必须同时等于换行符和空字符才能使此表达式为假。
  • @dandan78 我正在使用 xcode 的调试器,但我不知道它是否可以显示 OR 的哪一侧被标记为 true 并进入块。
  • @jasonharper 我想你已经发现了问题所在。我希望代码用简单的英语实现的是:“如果在倒数第二个索引处,除了 '\n' 或 '\0' 之外还有任何字符,则进入块,否则跳过。”我将如何重写它?
  • 那只是&& 而不是||。 “该字符不是换行符,并且它不是空值”。

标签: c99


【解决方案1】:

TLDR:不要忘记德摩根定律: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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2021-06-12
    • 1970-01-01
    • 2021-08-02
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多