1.下面代码的结果是:( )
#include <stdio.h> int main() { int i = 1; int ret = (++i) + (++i) + (++i); printf("ret = %d\n", ret); return 0; }
A.10
B.12
C.9
D.程序错误
答案解析:
答案是:D
如果你在VS上运行了这段代码,运行结果是12,你就选择了B,但是这样就错了,在不同的编译器它可能有着不同的运行结果。因为这个表达式的求值顺序是不确定的,第一个+和第三个++的不知谁先谁后,不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。
知识点:
1.表达式求值
表达式求值的顺序是由操作符的优先级和结合性决定的,但注意,有些表达式的操作数再求值的过程中可能需要转换为其他类型。
1.1 类型转换
低于int型的char,short为整形提升,等于或大于int型的为算术转换(从低到高)。
1.2 操作符的属性
①首先确定优先级,相邻操作符按照操作符优先级高级计算(相邻操作符才讨论优先级)
②优先级相同的情况下,结合性才起作用。
③注意操作符是否控制求值顺序(只有四个:&& || (?:) ,)
1.3 总结
我们写出的表达式如果不能通过操作符的属性确定唯一的计算途径,那这个表达式就是存在问题的。
1.4 补充:
(1)操作符的优先级:
()(聚组>函数调用) > [](下标引用)> 访问结构体成员操作符(. ->)> 后缀++ --
> 单目操作符(! ~ + - ++ -- * & sizeof (类型) )> 算术操作符(* / % + -)>移位操作符(<< >>) > 关系操作符(> >= < <= == !=)> 位操作符(& | ^)> 逻辑操作符(&& ||)> 条件操作符 > 赋值操作符 > 逗号操作符
(2)操作符的结合性
单目操作符和赋值操作符是自右向左结合,其余一般都是自左向右。
2.下面代码的结果是:
#include <stdio.h> int i; int main() { i--; if (i > sizeof(i)) { printf(">\n"); } else { printf("<\n"); } return 0; }
A.>
B.<
C.不输出
D.程序有问题
答案解析:
答案是:A
详细图解:
3.关于表达式求值说法不正确的是:( )
A.表达式求值先看是否存在整形提升或算术转换,再进行计算
B.表达式真正计算的时候先看相邻操作符的优先级决定先算谁
C.相邻操作符的优先级相同的情况下,看操作符的结合性决定计算顺序
D.只要有了优先级和结合性,表达式就能求出唯一值
答案解析:
答案是:D
如例题1,有了操作符的优先级和结合性,但是还是不能确定表达式的唯一计算途径。
4.点击下方链接
代码1:
分析:使用数组存放矩阵元素,同时统计大于0的元素。
#include <stdio.h> int main() { //行 int n=0; //列 int m=0; int arr[10][10]={0}; int sum=0; //输入行和列,且<=10 scanf("%d %d",&n,&m); //行循环变量 int i=0; for(i=0;i<n;i++) { //列循环变量 int j=0; for(j=0;j<m;j++) { //输入矩阵元素 scanf("%d",&arr[i][j]); //输入数据的同时,统计大于0的元素之和 if(arr[i][j]>0) { sum+=arr[i][j]; } } } //输出 printf("%d\n",sum); return 0; }
代码2:
分析:其实题目只是统计矩阵大于0的元素,所以没必要把数组元素存储起来,使用变量tmp接收并判断即可。
//没必要把数组元素存起来,使用变量tmp接收数组元素即可 #include<stdio.h> int main() { int n = 0; int m = 0; scanf("%d %d", &n, &m); int i = 0; int j = 0; int tmp = 0; int sum = 0; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%d", &tmp); if (tmp > 0) { sum += tmp; } } } printf("%d\n", sum); return 0; }
代码3:
分析:牛客网支持变长数组的特性,所以也可使用变长数组来存储矩阵的元素。
知识点:
①牛客可以使用变长数组;
②使用变长数组,注意不能初始化。
#include<stdio.h> int main() { int n = 0; int m = 0; scanf("%d %d", &n, &m); //变长数组,因为牛客网的oj是支持C99标准的,所以可以使用 int arr[n][m]; int i = 0; int j = 0; int sum = 0; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%d", &arr[i][j]); if (arr[i][j] > 0) { sum += arr[i][j]; } } } printf("%d\n", sum); return 0; }
5.点击链接做题
代码1:数组存放
分析:进制转化整数部分——取余倒排序法
//正序打印——数组存放 #include<stdio.h> int main() { int n = 0; //输入n scanf("%d", &n); //计算得到n表示六进制的逆序结果——数组存放 int arr[20] = { 0 }; int i = 1; while (n) { arr[i] = n % 6; n /= 6; i++; } //打印n六进制的结果 while (--i) { printf("%d", arr[i]); } printf("\n"); return 0; }
代码2:递归
//递归 #include <stdio.h> void print(int n) { if (n > 5) { print(n / 6); } printf("%d", n % 6); } int main() { unsigned int n = 0; while ((scanf("%d", &n)) != EOF) { print(n); printf("\n"); } return 0; }
6.点击链接做题
//矩阵转置——只是打印的方式不同 #include <stdio.h> int main() { int n = 0; int m = 0; scanf("%d %d", &n, &m); int arr[n][m]; int i = 0; int j = 0; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf("%d ", &arr[i][j]); } } for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { printf("%d ", arr[j][i]); } printf("\n"); } return 0; }
7.点击链接做题
代码1:投机取巧1
分析:投机取巧1——并没有真正删除,只是将要删除的数改成0,不打印0。
//投机取巧1——并不真正删除 #include <stdio.h> int main() { int n = 0; scanf("%d", &n); int arr[n]; int i = 0; for (i = 0; i < n; i++) { scanf("%d", &arr[i]); } //输入要删除的数 int del = 0; scanf("%d", &del); for (i = 0; i < n; i++) { if (arr[i] == del) { arr[i] = 0; } } //输出 for (i = 0; i < n; i++) { if (arr[i] != 0) { printf("%d ", arr[i]); } } return 0; }
代码2:投机取巧2
分析:既然代码1可以,那我们直接在打印时判断,不等于删除的数才打印。
//投机取巧2 #include<stdio.h> int main() { int n = 0; scanf("%d", &n); int arr[n]; int i = 0; for (i = 0; i < n; i++) { scanf("%d", &arr[i]); } //输入删除的数,直接判断不相等就输出 int del = 0; scanf("%d", &del); for (i = 0; i < n; i++) { if (del != arr[i]) { printf("%d ", arr[i]); } } return 0; }
代码3:真正的删除
分析:删除——>数组要实现删除的话,使用后面的元素将其覆盖即可。
图解
//真正将数组中要删除的数据删除掉 #include<stdio.h> int main() { int n=0; scanf("%d",&n); int arr[n]; int i=0; for(i=0;i<n;i++) { scanf("%d",&arr[i]); } //输入想要删除的数 int del=0; scanf("%d",&del); //删除 int j=0;//作为下标锁定的位置就是用来存放不删除的数据的 for(i=0;i<n;i++) { if(arr[i]!=del) { arr[j++]=arr[i]; } } //输出删除后的数组 for(i=0;i<j;i++) { printf("%d ",arr[i]); } return 0; }