【问题标题】:Can anyone figure out why my program (in C) for splitting sentence to word didn't work?谁能弄清楚为什么我的将句子拆分为单词的程序(在 C 中)不起作用?
【发布时间】:2018-10-25 18:43:03
【问题描述】:

我已经编写了两个代码来将句子拆分为单词,其中一个有效,另一个无效。 唯一的区别在于 for 循环下的 if 条件。 第一个没有输出。而第二个是给出预期的输出。请逻辑解释,不要教德摩根定律。我已经完全应用了我的逻辑,我认为这在第一个代码中也是正确的。

不工作一个:

  #include <stdio.h>
  void main(void){
  int i=0, m=0, n=0, j, l=0;
  char sen[500], wrd[500][500];

  printf("Input a sentence:\n");
  gets(sen);

  while(sen[i]!='\0'){
  l++;
  i++;
  }

  for(i=0;i<=l;i++){
    if(sen[i] != ' '||sen[i] != '\0'){    //Here is the difference.
        wrd[m][n]=sen[i];
        n++;
    }
    else{
        wrd[m][n]='\0';
        puts(wrd[m]);
        printf("\n");
        m++;
        n=0;
    }
    }
}

工作一:

 #include <stdio.h>
 void main(void){
 int i=0, m=0, n=0, j, l=0;
 char sen[500], wrd[500][500];

 printf("Input a sentence:\n");
 gets(sen);

 while(sen[i]!='\0'){
 l++;
 i++;
 }

 for(i=0;i<=l;i++){
    if(sen[i] == ' '||sen[i] == '\0'){        //Here is the difference.
        wrd[m][n]='\0';
        puts(wrd[m]);
        printf("\n");
        m++;
        n=0;

    }
    else{
        wrd[m][n]=sen[i];
        n++;
    }
    }
}

唯一的区别在于for循环的if条件。 第一个有:if(sen[i] != ' '||sen[i] != '\0') 二有:if(sen[i] == ' '||sen[i] == '\0')

【问题讨论】:

  • 你看不出!===之间的区别?他们做了两个完全相反的比较。
  • 永远不要永远使用getsa dangerous function 甚至已从 C 语言中删除。使用例如fgets 代替。
  • 在无效代码中,条件始终为假。
  • 是的,有区别。 :) 还有……什么?
  • 您需要一个新的学习源 C。您当前的学习源已经完全过时了。此外,您不应在堆栈上分配 500x500 字节。

标签: c string for-loop if-statement


【解决方案1】:

您的印象似乎是:

(sen[i] != ' '||sen[i] != '\0')

是逻辑否定:

(sen[i] == ' '||sen[i] == '\0')

事实并非如此。 DeMorgan's Laws 规定布尔语句的逻辑等价性。

您想要的一般情况是!(A || B) == (!A &amp;&amp; !B)。因此,您可以在分组表达式中移动否定,但逻辑 OR 会变成逻辑 AND,反之亦然。

在您的具体情况下,后一种情况的倒数是:

!(sen[i] == ' ' || sen[i] == '\0')

变成:

(sen[i] != ' ' && sen[i] != '\0')

通过此讨论,如果sen[i] 不是空格且sen[i] 不是换行符,您想追加到wrd。相反,您说如果sen[i] 不是空格或sen[i] 不是换行符,则要附加到wrd任何字符要么不是空格,要么不是换行符,所以这个条件永远为真。

【讨论】:

  • 但我没有明白其中的逻辑。我很早就知道德摩根定律了。但是你能解释一下它在我的特定代码中是如何工作的吗?
  • @Vartika 您对每个子表达式应用了否定,但未能将|| 切换到&amp;&amp;。那是你的错。
  • 你能从逻辑上解释一下吗?我的第一个代码怎么出错了?忘记我已经编写了第二个代码和 demorgan 定律。我没有在其中任何一个中使用过德摩根法。我只使用了我的逻辑,我认为第一个代码是正确的。
【解决方案2】:

第一个没有输出,因为 if(sen[i] != ' '||sen[i] != '\0') 总是评估为 True
好的,我将尝试在不通过 DeMorgan Laws 的情况下从逻辑上解释你。 假设输入一个字符串:
This is a string.
控制将通过循环。
考虑i=3,在索引3字符是's' (sen[3]='s')。
现在,if 条件将被检查。
sen[3] != ' ' == True
sen[3] != '\0' == True
现在, if(sen[i] != ' '||sen[i] != '\0') >>> True||True >>> True.
因此,if 块的主体将被执行。因此,没有输出。
现在i=4,在索引4字符是' ' (sen[3]=' ')。
现在,if 条件将被检查。
sen[4] != ' ' == False
sen[4] != '\0' == True
现在,if(sen[i] != ' '||sen[i] != '\0') >>> False||True >>> True。 同样,if 块的主体将被执行。因此,没有输出。
else 永远不会执行包含输出语句的块。 更合乎逻辑的是,如果 sen[i] 不是空格 OR sen[i] 不是空字符,您想追加到 wrd每个 字符要么不是空格,要么不是换行符,所以这个条件总是成立的。 在你的逻辑中,else blok 只有在遇到space\0(null) 这样的字符时才会执行。由于此类字符不存在 else 代码中的块将永远不会执行。因此,没有输出。

【讨论】:

  • 最好的解释。
  • 同样,您可以尝试对第二个代码进行空运行,您将了解为什么第二个代码是正确的。
【解决方案3】:

这里是等价的:

if(sen[i] == ' '||sen[i] == '\0'){
  // code block #1
} else {
  // code block #2
}

逻辑上等价于以下内容:

if(sen[i] != ' ' && sen[i] != '\0'){
  // code block #2
} else {
  // code block #1
}

基本上,当您反转单个条件时,您忽略了将 OR 也更改为 AND。

【讨论】:

  • 但我没有明白其中的逻辑。我很早就知道德摩根定律了。但是你能解释一下它在我的特定代码中是如何工作的吗?
  • 你能从逻辑上解释一下吗?我的第一个代码怎么出错了?忘记我已经编写了第二个代码和 demorgan 定律。我没有在其中任何一个中使用过德摩根法。我只使用了我认为在第一个代码中是正确的逻辑。
【解决方案4】:

关于你的代码中的逻辑,在不工作的代码中,在句子中:

if(sen[i] != ' '||sen[i] != '\0'){ 

如果发现一个空格,你会得到第一个参数为假,但第二个参数与字符串的结尾进行比较,但它不相等!所以这个比较变成了真的……false or true 给了你真的……所以代码做你期望用一个字符或一个词做的事情

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    相关资源
    最近更新 更多