1.题1
int main()
{
int count = 0;
int x = -1;
while (x)
{
count++;
x = x >> 1;
}
printf("%d", count);
return 0;
}
上述代码的运行结果是什么呢?
我们来分析一下:我们知道在vs中右移操作符的规则是,右边抛弃,左边由符号位相同的字符补齐。不太熟练地可以看一下之前的作品 。这里的while循环条件是x,如果x=x>>1,不能使x变为0,那么该程序就会陷入死循环。我们发现x总是等于-1,这是因为补齐的是1,舍弃的也是1,这样的话,补码始终不变,所以该程序会陷入死循环。
2.题2
int func(int x)
{
int count = 0;
while (x)
{
count++;
x = x & (x - 1);//与运算:只要有0就是0,同时为1才为1
}
return count;
}
如果传给func函数-1,则运行结果会是什么呢?
我们来分析一下:while循环条件为x当x不为0时就会陷入死循环,其实这道题的难点就是判断x=x&(x-1),这个表达式能在循环的作品用下使x为0。&是与运算操作符,它的运算规则是只要为0就是0,同时为1才为1。不够了解可以看之前的作品。在这里我们发现第一次循环时-1&-2,补码最右端少了一个1,我们继续观察两次发现,每循环一次x的补码最右端就会少一个1,这样的话在64位机器中,int类型的大小是32位bit,所以这里应该会循环32次,故count也会变为32.
我们运行看看:
3.题3
int main()
{
int w = 1, x = 2, y = 3, z = 4;
int ret=(w < x ? w : y < z ? y : z);
printf("%d", ret);
return 0;
}
上述代码的运行结果是什么呢?
我们来分析一下:这里考查的是条件操作符的使用,大家可能会觉得好长一条代码呀,看上去就好复杂,其实不然,我们首先来看w<x是否成立,这里很明显成立,所以计算w的值,所以结果为1。就是这么简单,没那么可怕的,大家只要慢慢去分析就好了。那么到底对不对呢?
我们运行看看:
4.题4
int main()
{
int a = 1, b = 2, m = 0, n = 0, k;
k=(n = b < a) && (m = a);
printf("%d,%d\n", k, m);
return 0;
}
上述代码的运行结果是什么呢?
我们来分析一下:这里考查的是运算符的优先级运算,我们观察发现这里的()优先级最大,所以先算n=b<a,得出n=0;又由于&&前表达式为假就不会计算后表达式,所以m=0,最后得出k=0;所以输出结果应该为0 0,我们运行看看:
5.题5
编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0~127 ,包括 0 和 127 ),换行 表示结束符,不算在字符里。不在范围内的不作统计。
多个相同的字符只计算一次 例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。
数据范围: 0 <= n <= 500 输入描述:一行没有空格的字符串。 输出描述: 输入字符串 中范围在(0~127,包括0和127)字符的种数。
#include <stdio.h>
int main()
{
char tmp[501] = { 0 };//最大输入量
while (~scanf("%s", tmp)) //对scanf的返回值按位取反。
{
char table[128] = { 0 };
char* ptr = tmp;
int count = 0;
while (*ptr)
{
if (table[*ptr] != 1) {//判断字符ascii值作为下标的位置是否被标记过,是否是重复字符
count++; //当前字符的位置没有被标记过表示没有出现过,则计数+1
}
table[*ptr++] = 1;//将字符ascii值作为下标的位置进行标记置1
}
printf("%d\n", count);
}
}
这里使用的是一种叫做查表法的方法: "aca" ,首先把a字符( ascii 值为 97 )作为下标,将标记数组的第 97 位置 1 ,下次如果还有 a 字符出现,到下标 'a' 或者 97 的位置一看是1就表示a已经统计过了。大家可能会疑惑这个while的循环条件怎么是~scanf啥的,这是啥意思呢?其实~就是我们之前学过的按位取反,操作是就是scanf的返回值,这样做的作用就是如果没有输入,也就是-1 ,取反就是0,就退出循环了。即使不适用do while循环,也可以达到类似的效果。(可以连续的输入并得出值)
