1. 计算递归了几次:
#include <stdio.h> int cnt = 0; int fib(int n) { cnt++; if (n == 0) { return 1; } else if (n == 1) { return 2; } else { return fib(n - 1) + fib(n - 2); } } void main() { fib(8); printf("%d", cnt); }
2. 判断 do while 循环执行了几次:
//在上下文和头文件均正常的情况下,以下程序的输出结果是() #include <stdio.h> int main() { int x = 1; do { printf("%d\n", x++); } while (x--); return 0; }
3. 求输入的两个数的最小公倍数
思路一:
假设 a 和 b 的较大值是最小公倍数,
如果较大值能同时整除两个数,说明较大值是两值的最小公倍数,跳出循环,
不能整除则 较大值++,直到能同时整除两个值跳出循环
//求输入两个整数的最小公倍数 #include <stdio.h> //最小公倍数 肯定会 大于等于 较大值 //所以可以试试用 较大值 同时 整除两个数 ,能整除 最小公倍数就是 较大值 //不能整除就把 较大值++ ,直到能整除两个数 int main() { //输入两个值 long long a = 0; long long b = 0; scanf("%lld %lld", &a, &b); //假设 a 和 b 的较大值是最小公倍数 //使用三目表达式,把 较大值 取出 long long m = a > b ? a : b; // while (1)//死循环 { if (m % a == 0 && m % b == 0) { break; //如果较大值能同时整除两个数,说明是两值的最小公倍数,跳出循环 } //不能整除则 较大值++,直到能同时整除两个值跳出循环 m++; //效率较低 } printf("%lld\n", m); return 0; }
思路二:
假设有 a 和 b ,两值的最小公倍数是 k ,i = 1
让 a * i % b 看能不能整除掉(余数等于0)
能整除最小公倍数是 k = a * i
不能则 i++,
直到能整除为止,此时最小公倍数 k = a * i
//求输入两个整数的最小公倍数 #include <stdio.h> //思路二: //假设有 a 和 b ,两值的最小公倍数是 k ,i = 1 //让 a * i % b 看能不能整除掉(结果等于0) //不能则 i++, //直到能整除为止,此时最小公倍数 k = a * i int main() { //输入两个值 long long a = 0; long long b = 0; scanf("%lld %lld", &a, &b); //求最小公倍数 int i = 1; while (a*i % b != 0)//这里 !=0 可以省略 // a*i 不能整除 b 则改变 i ,直到可以整除退出循环 { i++; } //直到能整除为止,此时最小公倍数 k = a * i printf("%lld\n", a*i); return 0; }
4. 将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I
补充知识点一:gets()
读取一个 字符串 ,即使中间有空格
gets(arr); -- 把读取到的字符串 放进 字符串数组arr中
(编译器可能会觉得该函数不安全而报警告,因为读取的字符串放进数组后可能会导致数组越界,可能会报错爆红,但还是可以用的)
补充知识点二:fgets()
可以使用 fgets()函数 替代 gets()函数
fgets(arr, 100, stdin);
函数参数:
arr:把读取的字符串放进字符数组arr中
100:获取字符串最大字符数,这里设置为100
stdin:输入方式,stdin 为 键盘输入
(因为指定了获取的字符个数,所以不用担心数组越界,也就不会报警告)
思路:(可以把两步顺序调换)
第一步: 把 整个字符串 逆序
(知道 整个字符串 的首尾地址后,一对一对向整个字符串中间靠拢交换)
第二步:再逆序每个单词
(知道 每个单词 的首尾地址后,一对一对向单词中间靠拢交换)
逆序的方法是一样的,可以写一个相应的自定义函数
实现代码:
//将一句话的单词进行倒置,标点不倒置。 //比如 I like beijing. 经过函数后变为:beijing. like I //每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100 #include <stdio.h> #include <string.h> //逆序 整个字符串 或 单词 void reverse(char* left, char* right) { while (left < right) //左小于右,中间还有值且没有同时指向一个字符,继续逆序 { char tmp = *left; *left = *right; *right = tmp; //调整指针 left++; right--; } } int main() { char arr[101];//数组长度不超过100,那就设置为101 //之后要重新赋值数组的话,这里就不初始化了? //这里不能使用 scanf()函数 获取字符串, //因为当读到单词间的空格时,scanf()函数 就不再往后读了 //这里可以使用 gets()函数 , //读取一个 字符串 ,即使中间有空格 gets(arr); //把读取到的字符串 放进 字符串数组arr中 //但系统可能会觉得不安全,报警告 //也可以写成:scanf("%[^\n]s",arr) //可以是 fgets()函数 再进行替代 //fgets(arr, 100, stdin); //函数参数: //arr:把读取的值放进字符数组arr中 //100:获取字符串最大字符数,这里设置为100 //stdin:输入方式,stdin 为 键盘输入 //求字符串长度: int len = strlen(arr);//strlen 不会把 \0 计算进去,找到 \0 就停了 //逆序整个字符串: reverse(arr, arr + len - 1); //自定义一个逆序函数方法 //方法参数:数组首地址(左指针) 、 最后一个字符的地址(右指针) //arr+len-1 :首地址 + 数组长度 - 1 ---》 最后一个字符的地址 //逆序每个单词: char* start = arr;//单词起始位置 char* cur = arr;//单词尾部位置 //逆序每个单词: while (*cur != '\0')//整个字符串还没结束,继续找单词 { //逆序一个单词: while (*cur != ' ' && *cur != '\0') //单词尾部未找到空格且还没到结束符就继续找下一位 { cur++; }//直到找到单词 //找到单词后进行单词逆序 reverse(start, cur - 1); //因为单词尾部,cur 此时是 空格位置,所以要在空格(或\0)位置前-1 //找下一个单词: start = cur + 1; //cur+1,空格后的下一个位置就是下一个单词的首地址 if (*cur == ' ') //只有是空格时才能跳过,\0不能再跳过了,不然就跳不出循环了 { cur++; //尾部跳过空格 } } printf("%s", arr); return 0; }
自定义逆序函数方法:
主函数:
补充:
1. 赋值运算符 优先级是很低的 (例如:*= , /=……);
2. 全局变量 和 局部变量同名的情况下,调用时优先调用 局部变量;
3. C语言规定,在一个源程序中,main函数的位置 可以是 任意的;
4. 注释会被编译器替换成空格,所以不要随便把注释夹在代码中间;
5. C语言早期是没有库函数的,所以可以说C语言本身是没有输入输出语句的,后来C语言的标准约定了一些函数,规定了一些函数名,功能,参数,返回类型,这些约定(规定)由编译器的厂商来提供标准库,标准库提供库函数,VS提供VS的,gcc提供gcc的,不是C语言提供的;
6. = 是赋值,== 是等于(啊啊啊啊啊);
针变量 *p,有:*p++,++ 的优先级是比 * 要高的,但这里是 后置++ ,是只作用于 p 的,而不是 *p,因为后置所以先执行 *p ,执行后再执行 p++ (是地址++)。如果要先 p++ ,再 *p ,可以写成 (*p)++ ;
8. 整型提升 是把 char 和 short 转化为 整型。算术转换 是把 小的类型 转换为 大的类型;
(奇奇怪怪的彩蛋:选择题全是坑啊啊啊啊啊,大题好难啊啊啊啊啊,我好笨啊啊啊啊啊)