五道选择题:
1、如果 x=2014 ,下面函数的返回值是( )
int fun(unsigned int x) { int n = 0; while(x + 1) { n++; x = x | (x + 1); } return n; }
A、20 B、21 C、23 D、25
解析:观察代码,发现代码的主要构成是一个循环,且每进行一次循环,n+1,最后返回的值为n的大小,那么我们的目标就是计算循环的次数。循环内部是x和x+1进行|(或)运算,|运算的规则是位上只要有一个为真便为真,两个同时为假才为假。
而和比自己大1的数进行|运算就会稳定地使x上的位为0的变为位为1的,直到全部都变为1,再进一次循环就为0。2014,可写作0000.......0111 1101 1110,总计有9个1,23个0,那么当循环23次之后,也就是n为23时,x为1111.......1111,32位均是1,想要再次循环,但x+1为0,不满足循环条件,故结束循环,返回23。因此答案选C
2、如下函数 fun 计算 prod=1*2*3*…*n ,并返回计算结果值。但当 n>12 时,返回值不正确。要找出该程序的错误,正确的调试方法是( )
int fun(int n) { int prod = 1 , i = 0; for(i = 1;i <= n;i++) { prod *= i; } return prod; }
A、监视变量prod的值,在prod *= i;行处设置断点,然后单步运行,直到发现错误原因
B、监视变量prod的值,在return prod;行处设置断点,程序中断后,即可发现错误原因
C、在prod=1;处设置断点,然后在函数调用堆栈中即可发现错误原因
D、监视变量i的值,在for (i=1; i<=n; i++)行处设置断点,然后单步运行,直到发现错误原因
解析:依题目已知情况,当n<=12时结果是正确的,说明是随着参数的变大计算过程中哪里出了问题,故而要在prod *= i;处设断点,查看原因。错误原因是数据过大时整型溢出,故答案选A
3、请问下列代码的输出结果有可能是哪些【多选】( )
#include <stdio.h> typedef union { int a; struct { short b; short c; }; }X; int main() { X x; x.a = 0x20150810; printf("%x,%x\n", x.b, x.c); return 0; }
A、2015,810 B、50810,201 C、810,2015 D、20150,810
解析:对于0x20150810
如果按照大端模式存储:
从低地址到高地址:20 15 08 10 输出从低地址到高地址:20 15 08 10
如果按照小端模式存储:
从低地址到高地址:10 08 15 20 输出从高地址到低地址:08 10 20 15
此数以int类型赋值给联合体x.a,而以结构成员b和c分开访问,分别拿到低地址的2个字节和高地址的2个字节,大端下是2015和810,小端下是810和2015,故答案选AC
4、运行以下程序后,如果从键盘上输入 65 14<回车> ,则输出结果为( )
#include<stdio.h int main() { int m, n; printf("Enter m,n\n"); scanf("%d %d", &m,&n); while (m!=n) //1 { while(m>n) m=m-n; //2 while(n>m) n=n-m; //3 } printf("m=%d\n",m); return 0; }
A、3 B、2 C、1 D、0
解析:观察代码发现它主要实现了一个功能就是,将输入进来的两个数互相减来减去,直到它们两个相等,中止循环,数据不大,可以直接代入进去,65-14=51,51-14=37,37-14=23,23-14=9,14-9=5,9-5=4,5-4=1,4-1=3,3-1=1,2-1=1,1==1中止循环,打印1,故答案选C。当数据不大的时候我们可以直接代入得结果,但当数据大到一定程度的时候还是需要通过分析两个数据之间的联系,具体情况具体分析。
5、若运行以下程序时,从键盘输入ADescriptor<回车> ,则下面程序的运行结果是( )
#include <stdio.h> int main() { char c; int v0 = 0, v1 = 0, v2 = 0; do { switch (c = getchar()) { case'a':case'A': case'e':case'E': case'i':case'I': case'o':case'O': case'u':case'U':v1 += 1; default: v0 += 1; v2 += 1; } } while (c != '\n'); printf("v0=%d,v1=%d,v2=%d\n", v0, v1, v2); return 0; }
A、v0=7,v1=4,v2=7 B、v0=8,v1=4,V2=8 C、v0=11,v1=4,v2=11 D、v0=12,v1=4,v2=12
解析:观察代码发现,主要构成就是一个循环包着一个switch,它的switch语句从我们输入的字符中读取,并通过读取的字符进行一系列的计算。但要注意的一点便是,它的switch中没有break,也就是说,它一旦执行了上面的,它就会一直往下走,直到走完,再通过循环判断。 ADescriptor<回车>。一共11个字符,a,e,i,o,u大小写,加起来有4个,令v1=v0=v2=4,剩下7个字符令v0+7,v2+7,所以最后v1=4,v0=v2=11,看上去好像就是这样,但需要注意的一点就是,它是dowhile循环,也就是先执行循环内容再判断,也就是说'\n'这个回车它也要执行1次,最后令v1=4,v0=v2=12,选D
编程题1:
思路:通过取模的计算将后一位剥离出来,在通过/10不断地寻找下一位的同时,对储存颠倒过来的数不断*10使其恢复位数,最后比对即可。需要注意的一点就是负数不可能是回文数。
bool isPalindrome(int x) { if (x < 0) //当x为-1时,倒过来为1-,可看出,负数不可能为回文数 { return false; } long long int sum = 0; long long int x1 = x; while (x1) { sum = sum * 10 + x1 % 10; x1 /= 10; } if (sum == x) { return true; } else return false; }
编程题2:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:通过我们手中的5美元和10美元钞票的数量进行判断,需要注意的便是,一开始我们是没有钱的,只能收5美元,别的遇到便找不开了。
bool lemonadeChange(int* bills, int billsSize) { //一开始我们是穷光蛋,一块钱都找不出 if (bills[0] != 5) return false; int five = 0; int ten = 0; //只需要计算5块钱和10块钱的数目即可,因为找钱不可能拿20找 int i = 0; for (i = 0; i < billsSize; i++) { if (bills[i] == 5) //给我们5美元的时候,直接收就行 { five += 1; } if (bills[i] == 10) //10美元就一种情况,找5美元,收10美元 { five -= 1; if (five < 0) { return false; } ten += 1; } if (bills[i] == 20) //两种情况,找3张5或1张10和1张5 { if (five >= 3 && ten < 1) //确实没有办法了,就找3张5出去,可以找的时候找1张5和1张10 //因为5相比10适用范围更大 { five -= 3; } else { five -= 1; ten -= 1; } if (five < 0 || ten < 0) { return false; } } } return true; }
好了,今天的练习到这里就结束了,感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O