前言:
两件事情A和B发生,只有四种情况:
1)A发生,同时B发生;
2)A发生,同时B不发生;
3)A不发生,同时B发生;
4)A不发生,同时B不发生。
第一种情况是 A&&B
后三种情况是 !(A&&B) 即 !A||!B
第一种情况与后三种情况互补;
第四种情况是!A&&!B
前三种情况是 !(!A&&!B) 即 A||B
第四种情况与前三种情况互补;
其实,因为只有四种情况,所以,任意一种情况都与其他三种情况互补。
即:第二种情况是 A&&!B ,其他三种情况是:!(A&&!B) 即 !A ||B
即:第三种情况是!A&&B,其他三种情况是:!(!A&& B) 即: A||!B
a&&b 和 !a || !b
c语言中的逻辑通过以下运算符和结构实现
逻辑运算符:
1、与
与:二者同时发生;
非--->二者至少有一个没发生。
1) if(a&&b)
条件a和条件b同时成立才会向下执行;
等价于 即:if中的与运算等价于两个if的叠加,两个if的叠加,可以合并为与运算。
if(a)
{
if(b){}
}
等价于//利用while 和 break 配合使用是,实现a&&b功能。
while(1)
{
if(!a)
break;
if(b)
{
//do sth
break;
}
break;
}
思想:
while中的 if(!a) 的 等价于 if(a&&b)中的 条件a不成立就不执行;
其实,if(a&&b) ,就是 先判断a,成立,再判断b
2) 参考本文
for(;p<=temp->list+length-1&&*p!=value;p++) ;//不满足循环条件,退出
if(p<=temp->list+length-1) //是*p==value的情况
{
ret = *(p-1);
return true;
}
return false; //是p>temp->list+length-1的情况
上例中,条件不满足,其实就是与运算 的 非。
2、或
或:二者至少有一个发生
非--->二者至都没发生。
if(!a||!b)
条件!a或者条件!b有一个成立,向下执行;
意为以下三种情况。(简单理解,一件事情发生了,要么是a,要么是b)
!a 且 !b
!a且 b
a且!b
以上三种情况 与 a且b 互斥且互补。
小结:且的情况只有1种,但 或的情况有3种,
要能从或推出3种情况,也要能从3种情况中,推出或:
3种情况推出或的 方法如下:
!a 且 !b
!a且 b
a且!b
左边,找!a出现了2次,即!a的情况已经全部列出了,右边找!b,出现了2次, a 、b 的位置是等同的,即!b的情况已经全部列出了,
推断出:三种情况 为 !a||!b
或者这样想:
左边 !a 且 !b 和 !a且 b 两种情况将!a的情况已经列全了,最后一种是 !a不发生, 另一边发生,而另一边是 !b
所以,这样也可以推断出:三种情况 为 !a||!b
*******************************************
以上分析了 a&&b 和 !a||!b 是互补的关系;
我们再分析一下 a&&b 和 a||b 的关系:
结论: a||b 分为 a&&b,a&&!b ,!a&&b 三种情况,故a||b包含 a&&b
3、非
if(!a)
if(a) 可以翻译成条件a成立
if(!a)翻译成条件!a成立。
一般应用于 函数出错判断的情况
4、条件结构
if -else及其嵌套
if和else地位是完全等价的,但并不意味着if 和 else 中的内容形式上也必须得一致。。。。
if-else 中的内容,互不影响,没有任何交集 ,单纯的并列关系。
if(a>10) //if和else完全等价,if中判断的是>10的情况,
{
}else{ //else中判断<=10的情况
}
//只不过程序执行顺序是先if 后else
if(a>90) //a>90的情况
{
}else if(a>60){ //a>60 且 a<90 的情况 //else中 嵌套了if-else
}else if(a>0){ //a>0 且 a<60 的情况 //else中 嵌套了if
}
if-else中内容形式相似的情况: if 和else 产生了交集,给对方的变量值 赋0;
int a=1,i=j=0;
while(true)
{
if( a == 1) //此处if和else中内容形式上是一致的。
{
j = 0;
i++;
if(i>=100)
{
i=100;
printf("---1");
}
}else{
i = 0;
j++;
if(j>=100)
{
j=100;
printf("-----2");
}
}
}
if-else中形式不同的情况,参考该文。 主要算法在if中,而else的情况我们不关注,但是,if 需要else 为其变量重新赋值.
例如:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度
int lengthOfLongestSubstring(char * s){
int strLen = strlen(s);
int maxLen = 1;
int count ;
char *str = s;
int i,j;
int k = 0;
if(strLen == 0)//字符串为空串
{
return 0;
}
for(i=1;i<strLen;i++)//strLen是指字符串的长度,同时也是字符数组的最后一个字符的下一位。
{
count = 1; //字符串每次比较,count重新计数
for(j=0;j<i-k;j++)//i-k是新串的长度,同时也是新的字符数组的最后一个字符的下一位。
{
if(s[i]==str[j])
{
str = str+j+1;//重复的话,str指向重复字符的下一个字符
k = k+j+1;//k记录str共向后移动的字符数//向后移动的个数==去掉的字符个数
break; //str成为一个新串,重新开始比较
}else
{
count++; //不重复的情况时,计数值++
}
}
maxLen = maxLen>count?maxLen:count;//求最大字符长度//跳出for循环就意味着串比较结束
}
return maxLen;
}
总结:if-else 并列且互斥,结论性的语句既不能放在if中,也不能放在else中。
循环中套if-else,主要算法在if中时,往往需要else为if中的变量重新赋值;
上例中,maxLen = maxLen>count?maxLen:count; 不能放在if中的原因:可能存在所有字符都不相等的情况,根本就没有进入到if中,count = 1,也不能放在if中也是这个原因。
5、循环结构
while
for
do-while
及与break,continue,if-else的嵌套
while循环中,隐含着continue,即条件成立继续循环,相当于此处有个continue;
while循环中,不满足循环条件,则退出循环,可以利用这个特性,找到某值,就不用使用break了。
循环结构是多次if的判断,当循环条件中嵌套if ,即两个if叠加,根据两个if叠加等价于与运算,故此时if条件也可以 与循环条件 合并为与运算。
常规思路:循环中,找某个值,找到之后,就break退出。
for(;p<=temp->list+length-1;p++)
{
if(*p==value)
break;
}
两个if叠加,合并为与运算。
for(;p<=temp->list+length-1&&*p!=value;p++) ;//不满足循环条件,退出
if(p<=temp->list+length-1) //是*p==value的情况
{
ret = *(p-1);
return true;
}
return false; //是p>temp->list+length-1的情况