大家好,我是深鱼~
【前言】:本部分是C语言初阶学完阶段性测试题,最后一道编程题有一定的难度,需要多去揣摩,代码敲多了,自然就感觉不难了,加油,铁汁们!!!
一、选择题
1.下面程序执行后,输出的结果为()
1. #include<stdio.h> 2. int cnt = 0; 3. int fib(int n) 4. { 5. cnt++; 6. if (n == 0) 7. return 1; 8. else if (n == 1) 9. return 2; 10. else 11. return fib(n - 1) + fib(n - 2); 12. } 13. void main() 14. { 15. fib(8); 16. printf("%d", cnt); 17. }
【解答】:67
函数递归的问题:进入一次fib函数,cnt++,要算cnt的值也就是算进入了多少次fib函数,那就列树状图:直到列到1和0就不会再进入fib函数为止,然后列出来的每一个数都会进入函数使cnt++,算一共列有多少数,对于的也就是cnt的值:1+2+4+8+16+22+12+2=67
2.以下程序k的最终值是()
1. int i = 10; 2. int j = 20; 3. int k = 3; 4. k *= i + j;
【解答】:90
本题考察的是操作符优先级的问题
赋值操作符(*=,/=,+=,-=)的优先级很低,所以肯定是i+j先算,然后再*k,也就是k*=30,也就是90
3.判断正误:C语言本身没有输入输出语句
【解答】:正确
C语言是给定了语法,输入输出是库函数提供的
C语言约定了一些函数,规定了函数的名字,功能,参数,返回类型
这些规定的函数是由编译器的厂商实现的,msvc,gcc,clang的厂商在实现编译器的时候提供实现的,这些函数是放在标准库中,称为库函数
4.若有定义语句int year=1009,*p=&year,以下不能使变量year中的值增至1010的语句是()
A.*p+=1 B.(*p)++ C.++(*p) D.*p++
【解答】:D
其实上面的代码就相当于int year=1009;int *p=&year
A.*(解引用操作符)的优先级高于+=(赋值操作符),p解引用指向year,然后year++
B.有括号先算*p,然后year++
C.也有括号,只要对(*p)也就是year++就可以
D.*p++,++优先级高于*,++先执行,p++后置++,值先为p,然后p++,这里就是地址++,而不是地址指向的元素++
5.char a;int b;float c;double d;
则表达式a*b+d-c值的类型为
【解答】:double类型
首先a*b(char*int),char类型整形提升变成int类型,int *int类型结果是int类型
然后int+double类型,这个时候int类型就算术转化为double类型,double+double类型结果是double类型
最后double-float类型,这个时候float类型就算术转化为double类型,double-double类型结果是double类型
【注意】:这个过程发生了整形提升和算术转化,是先变类型再进行运算
二、编程题
1.求最小公倍数
【题目】:
【题解1】:常规做法
最小公倍数一定是大于等于输入的两个数的,所以可以从两个数的较大数开始加,看加到哪个数可以同时将两个数整除
1. #include <stdio.h> 2. int main() 3. { 4. int a=0; 5. int b=0; 6. //输入 7. scanf("%d %d",&a,&b); 8. //求较大值 9. int m=a>b?a:b; 10. //从较大者开始求最小公倍数 11. while(1) 12. { 13. if(m%a==0&&m%b==0) 14. break; 15. m++; 16. } 17. //输出 18. printf("%d\n",m); 19. return 0; 20. }
【题解2】:最小公倍数=输入的两个数的积 / 最大公约数(辗转相除法)
1. #include <stdio.h> 2. int main() 3. { 4. int a=0; 5. int b=0; 6. int c=0; 7. //输入 8. scanf("%d %d",&a,&b); 9. int n=a*b; 10. //求最大公约数 11. while(c=a%b) 12. { 13. a=b; 14. b=c; 15. } 16. //输出 17. printf("%d\n",n/b); 18. return 0; 19. }
【题解3】:效率最高
假设m是a和b的最小公倍数,那么m既能被a整除,又能被b整除,m/a=i,m/b=j,那么我们就看a*i能否将b整除,eg:求3和5的最小公倍数,首先看3*1能否整除5,再看3*2是否能整除5,以此类推,直到找到3*i可以整除5,那么这时3*i就是最小公倍数
1. #include <stdio.h> 2. int main() 3. { 4. int a=0; 5. int b=0; 6. //输入 7. scanf("%d %d",&a,&b); 8. int i=1; 9. while(a*i%b) 10. { 11. i++; 12. } 13. //输出 14. printf("%d\n",a*i); 15. return 0; 16. }
【注意】:我们最好把int类型都写成long long类型,因为a和b最大可以到达100000,他们相乘是很大的,long long类型的输入输出都是%lld
2.字符串的倒置
【题目】:
【题解】:
思路:逆序整个字符串,再逆序每个单词(或者先逆序每个单词,再逆序整个字符串)
1. #include <stdio.h> 2. #include<string.h> 3. void reverse(char* left, char* right) 4. { 5. while (left < right) 6. { 7. char tmp = *left; 8. *left = *right; 9. *right = tmp; 10. left++; 11. right--; 12. } 13. } 14. int main() 15. { 16. char arr[101] = {0}; 17. gets(arr); 18. int len=strlen(arr); 19. //1.逆序整个字符串 20. reverse(arr,arr+len-1); 21. //2.逆序每个单词 22. char*cur=arr; 23. while(*cur!='\0') 24. { 25. char*start=cur; 26. while(*cur!=' '&&*cur!='\0') 27. { 28. cur++; 29. } 30. char*end=cur-1; 31. reverse(start,end); 32. if(*cur==' ') 33. cur++; 34. } 35. printf("%s\n",arr); 36. return 0; 37. }
【注意事项】:
(1)输入字符串:不能正常用scanf函数输入,因为它一遇到空格就停止读取了,gets(arr)
要用也得这样写scanf("%[^\n]s",arr);意思就是scanf函数直到读到\n才停止
也可以用getchar:
int ch=0;
int i=0;
while( (ch=getchar( ) )!='\n')
{
arr[i++]=ch;
}
(2)逆序整个字符串:思路是将左右字符一个一个交换,直到 left>right停止交换
还有就是reverse自定义函数传参的时候最后字符的地址怎么传:首字符地址+字符串的长度-1
(3)逆序输出:首先定义一个cur指针指向字符串的最前面,然后开始遍历,以一个单词为一个循环,当指针指向的不是空格或者\0时cur继续向下遍历,直到遇到了,就倒置这个单词,我们就用start和end指针分别来指向一个单词的首尾,然后单词也可以当字符串倒置
当一个单词结束,就需要进入下一个单词,这个时候就要将cur++,但是如果这是最后一个单词,就不需要cur++,因为再++就会造成数组越界
这次内容就到此啦,有什么问题欢迎评论区或者私信交流,觉得笔者写的还可以,或者自己有些许收获的,麻烦铁汁们动动小手,给俺来个一键三连,万分感谢 !