我正在与K& R学习C的道路上。除了书中的练习外,我自己也做了一些。我编写了以下代码,它的作用是,它会对您的输入进行计数,并为您提供反馈,以便为达到"目标" 10个单词,并在你达到10个单词时祝贺你。
#include <stdio.h>
main()
{
/* This programm will read your input, check the number of words,
and will congratulate when you reach a value of 10 words*/
int c, nw, counter;
nw = 0;
counter = 0;
while (nw < 10)
{
c = getchar();
if (c == ' ' || c == '\t' || c == '\n')
{
counter = 0;
}
else if (c != ' ' || c != '\t' || c != '\n')
{
if (counter == 0)
{
counter = 1;
++nw;
}
printf("Only %d words left\n", 10-nw );
}
}
}
好的,在这个版本中,代码不会将空白计为单词,从而导致正确输出单词。
起初我只用&#34来编写代码;如果&#34;而不是&#34;否则如果&#34;。它所做的是它还将空白视为单词。
我问的问题是为什么?使用if或者if if的区别是什么。
据我所知,该编译器将检查是否满足条件。仅使用if时也应如此。因为一切都是期望的,如果不是,我无法弄清问题是什么。
答案 0 :(得分:4)
不确定这是否是您正在寻找的答案。但无论如何,都会评估两个单独的 if 语句。使用&#34; 如果&#34;和&#34; 其他如果&#34;,如果评估,如果为真,则如果则跳过。当&#34; 如果&#34;不是真的&#34; 否则,如果&#34;被评估。
答案 1 :(得分:4)
看起来这可能是一个过度思考问题的案例。除了错误之外,你最终得到的逻辑过于复杂。您对if
和else if
之间区别的问题是公平的,我保证会在答案中解决这个问题。
首先,让我重申你想要做的事情:
阅读输入,计算单词数量,并在达到10个单词时祝贺您
从您的代码中,我相信您的意图是根据空格,制表符和换行符拆分单词。有很多方法可以分割单词,但就本问题而言,您的预期方法很好。
问题当然是你的逻辑不起作用。你的条件永远不会是假的:
else if (c != ' ' || c != '\t' || c != '\n')
考虑一下(提示:else
不会改变条件本身)。如果有帮助,请大声说出:您正在寻找c
不是空格,或c
不是标签,或c
不是&#39; ta newline。请记住,逻辑或(||
)是包含,换句话说,如果任何条件为true
,则表达式为true
c
1}}。例如,假设c != ' '
是一个空格。第一个条件(c != '\t'
)失败,但第二个条件true
为true
,因为空格不是标签。因此,整个表达式为c
。实际上,对于 else
的任何值,该表达式都是正确的。
else
呢?正如我所说,else if
的{{1}}部分在这里没有任何区别。 else if
唯一不同的做法就是将自己作为if
语句的新条件。让我们看一个更简单的例子:
if (a == 1) {
/* a is 1 */
}
if (a != 1 && b == 2) {
/* a isn't 1, but b == 2 */
}
这是两个完全独立的if
语句的示例。它是使用else
的完美示例,因为您可能已经注意到,第二个if
语句测试第一个的倒数。 (a != 1
)。因此,上述内容可以简化如下:
if (a == 1) {
/* a is 1 */
else if (b == 2) {
/* a isn't 1 and b is 2 */
}
在else if
区块中,我们无需对a != 1
进行测试,因为我们只考虑else
语句,如果第一个if
条件是假的。
另请注意,else if
实际上是两个单独关键字的组合。它相当于:
else {
if (b == 2) { ... }
}
但是,按照惯例,我们省略了可选的大括号并将其写为:
else if (b == 2) { ... }
事实上,在某些情况下,我们根本不需要第二个if
:
if (a == 1) {
printf("a is 1!\n");
} else {
printf("a isn't 1. In fact, it's %d.\n", a);
}
所以,现在没有必要陷入else if
。专注于您的逻辑,并尽力简化它。我会为你简化它,但我鼓励你跳过这一部分,先自己尝试一下:
char c;
int in_word = 0;
while (nw < 10) {
c = getchar();
if (c == ' ' || c == '\t' || c == '\n') {
/* If we were in a word, then count that word! */
if (in_word) {
nw++;
printf("You only have %d words to go!", 10 - nw);
}
in_word = 0; /* We are not in a word now */
} else {
in_word = 1; /* Now we're in a word
}
}
答案 2 :(得分:2)
else if (c != ' ' || c != '\t' || c != '\n')
这行代码可能没有按照你的意图行事。它作为else if
工作正常,但事实上它并没有真正检查任何东西(你实际上可以用简单的else
替换它)!对于任何可以想象的角色,它总是要么不是空格,要么不是制表符,或者不是换行符。你真正想要的是这些陈述的结合,而不是当前的分离:
else if (c != ' ' && c != '\t' && c != '\n')
这将检查字符既不是空格,也不是制表符,也不是换行符。即使将else
删除,它也可以作为单独的if
语句使用。但是,你真的应该选择一个简单的else
。
答案 3 :(得分:0)
在if
条件下,如果您使用简单的if .. else
构造,则它将等同于
if (c == ' ' || c == '\t' || c == '\n')
{
...
}
else if (c != ' ' && c != '\t' && c != '\n') //Notice &&.
//Apply De-morgan's law over if conditio.
{
...
}
在上述情况下,else if
不是必需的,if else
就足够了。使用if .. else
比给定代码更有效。
但是,从逻辑上讲,它可能与您给定的代码具有相同的效果。
根据逻辑,else if
不是必需的。
如下所述,您将获得比较操作数量的差异。
当前代码:
'a'
,它将执行4次比较(||
和&&
被短路。)在if-else
代码中,将执行最多3次比较。
这种差异并不那么显着。并且只有在代码运行数十亿次时才能注意到。
if else
具有维护的额外优势。在OP中的上述代码中,如果if
部分中有任何更改,则应将其反映在{{1}中部分也是。
因此,对我来说,仅使用else if
代替if else
似乎是有益的。