单项选择题 用户标识符 1、以下不能定义为用户标识符的是( )
A)scanf
scanf
答案错误!
scanf
不属于 C 语言关键字的任意一个。他是 <stdio.h>
头文件中的其中一个函数名。用户可以自定义一个 scanf
函数名去 替换 掉原有的 scanf
函数。
B)Void
Void
答案错误!
要知道,C 语言是严格区分大小写的,所以 Void
不等于 关键字 中的 Void
C)_3com
_3com
答案错误!
C 语言的变量名可以用 字母或下划线开头
D)int
int
正确,int
属于 C 语言中 32 个关键字 中的其中一个,故不能成为用户标识符。
查看解释 本题重点是:关键字,变量命名规则
C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z
或 a-z
或下划线 _
开始,后跟零个或多个字母、下划线和数字(0-9
)。
C 标识符内 不允许 出现标点字符,比如 @
、$
和 %
。C 是区分大小写的编程语言。因此,在 C 中,Manpower
和 manpower
是两个不同的标识符。
下表列出了 C 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。
关键字
说明
auto
声明自动变量
break
跳出当前循环
case
开关语句分支
char
声明字符型变量或函数返回值类型
const
定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue
结束当前循环,开始下一轮循环
default
开关语句中的”其它”分支
do
循环语句的循环体
double
声明双精度浮点型变量或函数返回值类型
else
条件语句否定分支(与 if 连用)
enum
声明枚举类型
extern
声明变量或函数是在其它文件或本文件的其他位置定义
float
声明浮点型变量或函数返回值类型
for
一种循环语句
goto
无条件跳转语句
if
条件语句
int
声明整型变量或函数
long
声明长整型变量或函数返回值类型
register
声明寄存器变量
return
子程序返回语句(可以带参数,也可不带参数)
short
声明短整型变量或函数
signed
声明有符号类型变量或函数
sizeof
计算数据类型或变量长度(即所占字节数)
static
声明静态变量
struct
声明结构体类型
switch
用于开关语句
typedef
用以给数据类型取别名
unsigned
声明无符号类型变量或函数
union
声明共用体类型
void
声明函数无返回值或无参数,声明无类型指针
volatile
说明变量在程序执行中可被隐含地改变
while
循环语句的循环条件
表达式与数据类型 设有定义:float a = 2, b = 4, h = 3;
以下 C 语言表达式中与代数式 的计算结果不相符的是( )
查看算出来的值
B)(1 / 2) * (a + b) * h
(1 / 2) * (a + b) * h
哎呀!这不是和上面的代数式一模一样嘛?怎么和计算结果不相符呢?别急,看下面解释。
查看解释
这要是用数学的思维计算,好家伙,全是 9,那不没答案嘛。你正想要去找老师抬杠呢,信心满满的打开 Visual Studio,往里面一输入:
#include <stdio.h> int main () { float a = 2 , b = 4 , h = 3 ; printf ("%f\n" , (a + b) * h / 2 ); printf ("%f\n" , (1 / 2 ) * (a + b) * h); printf ("%f\n" , (a + b) * h * 1 / 2 ); printf ("%f\n" , h / 2 * (a + b)); return 0 ; }
结果一看输出:
9.000000 0.000000 9.000000 9.000000
好家伙,我计算机出问题了?这怎么算出个 0 呢?仔细一看。。。奥!原来问题就出在 (1 / 2)
这个坑里。
在 C 语言中,整数相除,会舍弃掉小数点后面的值,甚至没有四舍五入。所以 (1 / 2) = 0;
而 (1.0 / 2.0) = 0.5
脑子过程序 1 有以下程序:
#include <stdio.h> void main () { int i = 1 , j = 1 , k = 2 ; if ((j++ || k++) && i++) printf ("%d, %d, %d\n" , i, j, k); }
执行后的输出结果是( )
1, 1, 2
2, 2, 1
2, 2, 2
2, 2, 3
查看解释 #include <stdio.h> void main () { int i = 1 , j = 1 , k = 2 ; if ((j++ || k++) && i++) printf ("%d, %d, %d\n" , i, j, k); }
这是程序员最烦最烦的题目。但是总喜欢出这种没营养的题目,是为了训练学生的 C 语言基础,所以还是得忍痛学习。这题主要有以下几点:
C 逻辑中,非零为 真 True
if 语句有短路
自增
非零为真 其实不是本题关键,因为 i j k 都是非 0 值。重点在 自增和短路 !
首先,i = 1, j = 1, k = 2;
到 if 语句时,执行两个判断,首先是 (j++ || k++)
,才到 ((j++ || k++) && i++)
当执行 (j++ || k++)
会触发一种机制,短路。因为 j++
后,j = 2
,非 0,所以或语句并没有执行 k++
,直接返回 true
接下来执行 (true && i++)
,这时候需要执行 i++
,所以 i = 2
。
所以 i = 2, j = 2, k = 2;
衍生说逻辑判断中的短路:
短路的意思是不会执行逻辑判断中后续的语句
逻辑与 &&
:如果或中间的其中一个值为 0 假 false
,则发生短路
逻辑或 ||
:如果与中间的其中一个值为 1 真 true
,则发生短路
脑子过程序 2 有以下程序:
#include <stdio.h> void main () { int i, s = 0 ; for (i = 1 ; i < 10 ; i += 2 ) s += i + 1 ; printf ("%d\n" , s); }
执行后的输出结果是( )
查看解释
注意看 for 循环变量增值操作(第三个表达式)是 i += 2
,所以要么奇数要么偶数。
可以两种观点:
for 循环的循环变量赋值操作(第一个表达式)是 i = 1
,所以只能是 1 3 5 7 9
奇数。
for 循环中的循环条件(第二个表达式)为 i < 10
,所以不可能会是 1 - 10
脑子过程序 3 有以下函数定义:
void fun (int n, double x) { ... ... }
若以下选项中的变量都已经正确定义并赋值,则对函数fun的正确调用语句是( )
fun(int y, double m);
A)
fun(int y, double m);
答错了!这不知道是什么奇怪的写法。。。
k = fun(10, 12.5);
B)
k = fun(10, 12.5);
答错了!咋一看很像是对的是吧,可是这个函数的返回值是 void
。所以他还是错了。
fun(x, n);
void fun(n, x);
D)
void fun(n, x);
答错了!这是 声明函数 的语句
阅读程序 填空 有一个 3 * 4 矩阵,求其中的最大元素。
#include <stdio.h> int max_value (int array [][4 ] ) { int i, j, max; max = array [0 ][0 ]; for (i = 0 ; i < 3 ; i++) for (j = 0 ; j < 4 ; j++) if (array [i][j] > max) max = array [i][j]; return max; } int main () { int a[3 ][4 ], i, j; for (i = 0 ; i < 3 ; i++) for (j = 0 ; j < 4 ; j++) a[i][j] = i * j; printf ("max value is % d\n" , max_value(a)); return 0 ; }
查看解释
第一个空是函数行禅定义,我们通过下边的代码观察到 array
变量未在函数中被定义,所以推断形参就是 array
。下方 main
函数中对 max_value(a)
的调用也能验证参数只有一个。且是二维数组。而二维数组的定义,第一个方括号可以留空,但是第二个不行 [][4]
。同理,一维数组中的方括号不能留空 []
。
第二个空是赋值,说实话,这个空在这里好奇怪,因为我想不到还能填什么值,索性就以 i * j
的结果赋值给矩阵中。访问二维矩阵的方式为 数组名[行下标][列下标]
。
输入 x、y 两个整数,按先大后小的顺序输出 x、y。
#include <stdio.h> int main () { int x, y, * px, * py, * p; scanf ("%d%d" , &x, &y); px = &x; py = &y; if (x < y) { p = px; px = py; py = p; } printf ("x = %d, y = %d\n" , x, y); printf ("MAX = %d, MIN = %d\n" , *px, *py); return 0 ; }
查看解释
这题主要看它的交换操作那块,那是对地址 进行操作,所以我们需要初始化地址指向 x
和 y
的指针。
注意,我们需要用 &
取地址符,来获取 x 和 y 变量的地址。
用选择排序法对任意10个整数按照由大到小排序。
#include <stdio.h> int main () { int a[11 ], i, j, k, t; printf ("Please input 10 numbers:\n" ); for (i = 1 ; i < 11 ; i++) scanf_s("%d" , &a[i]); printf ("\n" ); for (i = 1 ; i <= 9 ; i++) { k = i; for (j = i + 1 ; j <= 10 ; j++) if (a[j] > a[k]) k = j; if (k != i) { t = a[k]; a[k] = a[i]; a[i] = t; } } printf ("The sorted numbers:\n" ); for (i = 1 ; i < 11 ; i++) printf ("%d " , a[i]); }
查看解释
填空 5: 在选择排序中,变量 k
用于记录当前轮次中最大元素的索引。在每轮开始时,应将 k
初始化为当前轮次的起始位置 i
。
填空 6: 修改循环条件,使其循环到数组的最后一个元素。
选择排序的解释
选择排序是一种简单直观的排序算法,其基本思想是每一次从待排序的数据元素中选择最小(或最大)的一个元素,放到序列的起始位置,然后再从剩余未排序的元素中选择最小(或最大)的元素,放到已排序序列的末尾。依此类推,直到所有元素均排序完毕。
具体步骤如下:
初始状态: 假设待排序的序列有n个元素,将序列分为已排序和未排序两部分。初始时,已排序部分为空,未排序部分包含所有n个元素。
选择最小元素: 在未排序部分中选择最小的元素,记其下标为k。
交换位置: 将未排序部分中的第一个元素与第2步中选择的最小元素交换位置。此时,已排序部分增加一个元素,未排序部分减少一个元素。
重复步骤2-3: 重复执行步骤2和步骤3,直到未排序部分变为空。这样,每一次循环都会找到未排序部分的最小元素,并将其加入已排序部分。
结束: 当未排序部分为空时,排序完成。
选择排序的时间复杂度为O(n^2),其中n是待排序序列的长度。虽然选择排序相对简单,但对于大型数据集来说,性能较差,因此在实际应用中更常使用其他更高效的排序算法,如快速排序或归并排序。
基础程序设计题 第 9 题 编写一个程序。实现输入一个小写字母,程序输出它对应的大写字母。 (提示:小写字母的ASCII码值比大些字母大32。)
第 9 题思路
接收用户输入
将小写转换成大写
输出结果
第 9 题题解 #include <stdio.h> int main () { int ch; scanf_s("%c" , &ch); printf ("%c\n" , ch - 32 ); }
第 9 题思路(字符串版本)
接收用户输入
循环字符串
判断是否为小写字母
转换成大写
输出结果
第 9 题题解(字符串版本) #include <stdio.h> #define SIZE 100 int main () { char str[SIZE]; int i; gets(str); for (i = 0 ; i < SIZE; i++) { if (str[i] >= 'a' && str[i] <= 'z' ) { str[i] -= 32 ; } } puts (str); return 0 ; }
我在原版的基础上,加上了:
使用 sizeof
,动态计算数组长度
增加用户输入提示
检测字符串结尾,提前退出循环
#include <stdio.h> int main () { char str[100 ]; int i; int len; printf ("请输入一段字符串:" ); gets(str); len = sizeof (str) / sizeof (*str); for (i = 0 ; i < len; i++) { if (str[i] == '\0' ) break ; if (str[i] >= 'a' && str[i] <= 'z' ) { str[i] -= 32 ; } } puts (str); return 0 ; }
第 10 题 编写一个程序,计算 100 + 101 + 102 + ⋯ + 300 的值。
第 10 题思路
定义总和变量
从 100 循环到 300
加总和
输出结果
第 10 题题解 #include <stdio.h> int main () { int sum = 0 , i; for (i = 100 ; i <= 300 ; i++) { sum += i; } printf ("%d" , sum); return 0 ; }
第 11 题 已知学生成绩(100 分为满分)与等级的对应关系为:
成绩(grade)
等级
90 <= grade <= 100
A
80 <= grade < 90
B
70 <= grade < 80
C
60 <= grade < 70
D
grade < 60
E
请你编写一个程序,要求:输入学生成绩,输出学生成绩对应的等级。(提示:使用 switch⋯.case语句)
第 11 题思路与题解 switch...case 版本 if...else 版本 switch…case 版本
接收用户输入
因为是每个档次以 10 分为分水岭,所以直接将分数除 10,得到它的十进制。
用 switch...case
判断 10 进制
输出结果
#include <stdio.h> int main () { int grade; printf ("请输入学生成绩(0-100):" ); scanf_s("%d" , &grade); switch (grade / 10 ) { case 10 : case 9 : printf ("等级:A\n" ); break ; case 8 : printf ("等级:B\n" ); break ; case 7 : printf ("等级:C\n" ); break ; case 6 : printf ("等级:D\n" ); break ; default : if (grade >= 0 && grade <= 100 ) { printf ("等级:E\n" ); } else { printf ("输入无效的成绩\n" ); } } return 0 ; }
if…else 版本
接收用户输入
既然它的条件都已经写给你了,何不用 if…else?
将他的条件拆分成:if (上限 <= grade && grade < 下限) { ... } eise if ( ... ) { ... } else { ... }
完美解决
输出结果
#include <stdio.h> int main () { int grade; printf ("请输入学生成绩(0-100):" ); scanf ("%d" , &grade); if (grade >= 90 && grade <= 100 ) { printf ("等级:A\n" ); } else if (grade >= 80 && grade < 90 ) { printf ("等级:B\n" ); } else if (grade >= 70 && grade < 80 ) { printf ("等级:C\n" ); } else if (grade >= 60 && grade < 70 ) { printf ("等级:D\n" ); } else if (grade >= 0 && grade < 60 ) { printf ("等级:E\n" ); } else { printf ("输入无效的成绩\n" ); } return 0 ; }
综合程序设计题 第 12 题 输入一个圆半径 r
,当 r >= 0
时,计算并输出圆的面积和周长,否则,输出提示信息。
第 12 题思路
获取用户输入
判断输入是否合法
计算面积
输出结果
第 12 题题解 #include <stdio.h> #define PI 3.1415926 int main () { double r; printf ("请输入圆的半径:" ); scanf ("%lf" , &r); if (r >= 0 ) { double area = PI * r * r; printf ("圆的面积为:%lf\n" , area); } else { printf ("半径不能为负数\n" ); } return 0 ; }
第 13 题 从键盘输入 10 个整数,统计其中正数、负数和零的个数,并在屏幕上输出。
第 13 题思路
定义一个整型数组
获取用户输入
遍历数组
判断整数类型
统计
输出结果
第 13 题题解 #include <stdio.h> int main () { int numbers[10 ]; int positiveCount = 0 , negativeCount = 0 , zeroCount = 0 ; printf ("请输入10个整数:\n" ); for (int i = 0 ; i < 10 ; i++) { scanf_s("%d" , &numbers[i]); } for (int i = 0 ; i < 10 ; i++) { if (numbers[i] > 0 ) { positiveCount++; } else if (numbers[i] < 0 ) { negativeCount++; } else { zeroCount++; } } printf ("正数个数:%d\n" , positiveCount); printf ("负数个数:%d\n" , negativeCount); printf ("零的个数:%d\n" , zeroCount); return 0 ; }
第 14 题 编写程序,其中自定义一函数用来判断数组 a[8] = {1,3,4,7,8,9,10,12}
中的每个数组元素是否为素数,输出是否为素数。子函数声明格式为:int prime(int *p)
。
第 14 题思路
int prime(int *p)
函数
如果 prime 等于 1 则返回 0(1 不是素数)
暴力尝试是否能被自身以外的值整除
主函数
定义数组
遍历数组中的值
调用 prime
函数,判断是否为素数
输出结果
第 14 题题解 #include <stdio.h> int prime (int * p) { if (*p <= 1 ) { return 0 ; } for (int i = 2 ; i * i <= *p; i++) { if (*p % i == 0 ) { return 0 ; } } return 1 ; } int main () { int a[8 ] = { 1 , 3 , 4 , 7 , 8 , 9 , 10 , 12 }; printf ("判断数组中的素数:\n" ); for (int i = 0 ; i < 8 ; i++) { if (prime(&a[i])) { printf ("%d 是素数\n" , a[i]); } else { printf ("%d 不是素数\n" , a[i]); } } return 0 ; }
在这个程序中,prime
函数接受一个整数指针作为参数,判断该整数是否为素数。然后,在 main
函数中,对数组中的每个元素调用 prime
函数,并输出结果。
在这个程序中,指针起到的作用是允许函数prime
直接修改传递给它的数组元素的值。以下是对指针的作用的解释:
传递数组元素的地址: 函数 prime
的参数是一个整数指针 int *p
,它接受一个整数的地址作为输入。这样,当在 main
函数中调用 prime(&a[i])
时,实际上是将数组元素 a[i]
的地址传递给了 prime
函数。
通过指针修改数组元素: 在 prime
函数中,使用解引用操作符 *p
来访问传递进来的整数的值。这允许 prime
函数直接修改 main
函数中数组元素的值。在这个程序中,虽然 prime
函数没有对数组元素的值进行修改,但是通过指针,它具有修改的能力。
避免数组元素的复制: 通过传递指针,而不是整数的副本,可以避免在函数调用中进行数组元素的复制。这在处理大型数组时可以提高程序的效率。
第 15 题 一个学生具有学号、姓名、3 门课程成绩共 5 个信息。定义结构体变量,调用函数求 3 门课程的平均分。
第 15 题思路
定义学生结构体,包含学号、姓名和3门课程成绩
声明一个函数用于计算三门课程的平均分
在主函数中定义学生结构体变量,接收用户输入的学生信息和三门课程成绩
调用函数计算平均分
输出计算结果
第 15 题题解 #include <stdio.h> struct Student { int studentId; char name[50 ]; double grades[3 ]; }; double calculateAverage (struct Student student) ;int main () { struct Student student1 ; printf ("请输入学生信息:\n" ); printf ("学号:" ); scanf ("%d" , &student1.studentId); printf ("姓名:" ); scanf ("%s" , student1.name); printf ("输入三门课程的成绩:\n" ); for (int i = 0 ; i < 3 ; i++) { printf ("课程%d成绩:" , i + 1 ); scanf ("%lf" , &student1.grades[i]); } double average = calculateAverage(student1); printf ("%s的三门课程平均分为:%lf\n" , student1.name, average); return 0 ; } double calculateAverage (struct Student student) { double sum = 0 ; for (int i = 0 ; i < 3 ; i++) { sum += student.grades[i]; } double average = sum / 3 ; return average; }
观众姥爷赏口饭吃 教材准备不易,可否打个赏?