一、位运算操作实践
描述:
编写一个C语言程序,该程序通过位运算操作来修改一个8位无符号整数(uint8_t
)的特定位。具体任务如下:
- 将变量
a
的第6位设置为1,其他位保持不变。 - 将变量
b
的第5位设置为0,其他位保持不变。 - 将变量
c
的第6位取反(如果为1则变为0,如果为0则变为1),其他位保持不变。 - 将变量
d
的第3位和第5位取反,其他位保持不变。
程序应该输出每个变量修改后的十六进制表示。
提示:
- 使用位运算操作符
|
(按位或)、&
(按位与)、~
(按位取反)和^
(按位异或)。 - 使用左移操作符
<<
来将1移动到目标位的位置。 - 使用十六进制字面量(例如
0xa9
)来表示变量初始值可以使代码更易读。
输出示例(根据程序实现):
a = 0xe9
b = 0x89
c = 0xe9
d = 0x81
注意:在C语言中,二进制字面量(如 0b10101001
)并不是标准的,你需要将其转换为十进制或十六进制字面量,或者如果你的编译器支持二进制字面量,那么可以直接使用。
代码实现:
#include <stdio.h>
#include <stdint.h>
// 1. 位运算
int main()
{
// 将变量a的第六位设置为1,其他位不变
uint8_t a = 0b10101001; // 0xa9
// 0b10101001
// 0b01000000
// 0b11101001 0xe9
printf("a = %#0x\n", a | (1 << 6));
// 将变量b的第5位设置为0,其他位不变
uint8_t b = 0b10101001;
// 0b10101001
// 0b11011111 0xbf
// 0b10001001 0x89
printf("b = %#0x\n", b & (~(1 << 5)));
// 将变量c的第6位取反,其他位不变
uint8_t c = 0b10101001;
// 0b10101001
// 0b11101001 0xe9
printf("c = %#0x\n", c ^ (1 << 6));
// 将变量d第3位和第5位取反
uint8_t d = 0b10101001;
// 0b10101001
// 0b10000001 0x81
printf("d = %#0x\n", d ^ (1 << 3) ^ (1 << 5));
return 0;
}
运行结果:
二、计算所有能被7和9整除的整数的和
描述:
编写一个C语言程序,该程序通过for
循环遍历从1到用户输入的整数n,并计算这个范围内所有能被7和9同时整除的整数的和。最后,程序应输出这个和。
要求:
- 提示用户输入一个整数n。
- 使用
for
循环遍历从1到n的所有整数。 - 对于每个整数,检查它是否同时能被7和9整除。
- 如果一个整数同时满足上述条件,则将其累加到变量
sum
中。 - 在循环结束后,输出变量
sum
的值,即所有满足条件的整数的和。
提示:
- 使用
%
运算符来检查一个数是否能被另一个数整除。 - 使用
scanf
函数读取用户输入的整数。 - 使用
printf
函数输出最终的和。
输出示例:
请输入n: 100
和为63
代码实现:
#include <stdio.h>
int main()
{
// 编写一个程序,使用for循环计算1到n之间所有能被7和9整除的整数的和,并输出结果。
// 1. 定义变量接收n
int n;
// 2. 定义变量接收和
int sum = 0;
// 3. 输入
printf("请输入n:\n");
scanf("%d", &n);
// 4. 循环计算
for (int i = 1; i <= n; i++)
{
// 计算所有能被7和9整除的整数的和
if (i % 7 == 0 && i % 9 == 0)
{
sum += i;
}
}
printf("和为%d\n", sum);
return 0;
}
运行结果:
三、员工信息打印程序
描述:
编写一个C语言程序,该程序定义了一个结构体Employee
,用于存储员工的姓名、工号和工资信息。程序中包含一个函数print_employee
,该函数接收一个指向Employee
结构体的指针,并打印出该员工的信息。
要求:
-
定义一个结构体
Employee
,包含以下三个成员变量:name
:一个字符数组,用于存储员工的姓名。id
:一个字符数组,用于存储员工的工号。salary
:一个浮点数,用于存储员工的工资。
-
编写一个函数
print_employee
,该函数接收一个指向Employee
结构体的指针作为参数,并打印出该员工的姓名、工号和工资。 -
在
main
函数中,创建一个Employee
结构体变量employee
,并初始化其成员变量的值。 -
调用
print_employee
函数,将employee
的地址作为参数传递,以打印出员工的信息。
注意:
- 在打印工资时,使用
%f
格式化字符串,并确保在输出时工资值保留两位小数。
输出示例:
姓名 = jack
工号 = e001
工资 = 7000.00
代码实现:
#include <stdio.h>
// 4. 定义一个结构体,包含姓名、工号和工资三个成员变量。
struct Employee
{
char name[50]; // 姓名
char id[50]; // 工号
float salary; // 工资
};
void print_employee(struct Employee *employee)
{
printf("姓名 = %s\n", employee->name);
printf("工号 = %s\n", employee->id);
printf("工资 = %2f\n", employee->salary);
}
int main()
{
struct Employee employee = {"jack", "e001", 7000};
// 定义一个函数接收指向结构体的指针,打印结构体的内容
print_employee(&employee);
return 0;
}
输出结果:
四、年龄递推计算
描述:
有5个人坐在一起,按照年龄从小到大的顺序依次排列。第5个人说他的年龄比第4个人大2岁,第4个人说他的年龄比第3个人大2岁,以此类推,直到第2个人说他的年龄比第1个人大2岁。已知第1个人的年龄是10岁。请通过递归的方式编写一个程序来计算第5个人的年龄。
要求:
- 编写一个递归函数
calculateAge
,该函数接收一个整数age
作为参数,表示当前询问的是第几个人的年龄。 - 递归函数的结束条件是当
age
等于1时,返回第1个人的年龄(已知为10岁)。 - 在递归函数中,每次递归调用
calculateAge(age - 1)
,并将结果加上2,以表示当前人的年龄比前一个人大2岁。 - 在
main
函数中,调用calculateAge
函数,并将结果(第5个人的年龄)输出到屏幕上。
提示:
- 递归函数是一种自我调用的函数,它通过不断地缩小问题的规模,直到达到一个已知的结果,然后将这些结果逐步返回,从而解决整个问题。
- 在本题中,递归函数
calculateAge
通过不断地减小age
的值,直到age
等于1时返回已知的第1个人的年龄,然后逐步加上2,最终得到第5个人的年龄。
输出示例:
第5个人:18岁
代码实现:
#include <stdio.h>
// 有5个人坐在一起,问第5个多少岁,他说比第4个人大2岁, 第4个人说比第3个人大2岁,依次类推得到第2个人比第1个人大2岁,求第5个人多大, 递归实现
int calculateAge(int age)
{
// 递归结束条件
if (age == 1)
{
return 10;
}
// 递归调用
return calculateAge(age - 1) + 2;
}
int main()
{
printf("第5个人:%d岁\n", calculateAge(5));
return 0;
}
运行结果:
五、二分查找目标值的下标
描述:
给定一个有序整数数组arr
和一个目标值target
,请编写一个函数find_index
,使用二分查找算法在数组中查找目标值的下标。如果找到目标值,则返回其下标;否则返回-1。
要求:
arr
是一个有序整数数组,保证不会出现重复的元素。- 函数
find_index
的参数应为数组arr
和数组的长度len
。 - 在
find_index
函数中,使用二分查找算法来查找目标值target
。 - 如果找到目标值,则返回其下标;否则返回-1。
- 在
main
函数中,定义一个有序整数数组arr
,并初始化其值。 - 调用
find_index
函数,并将结果存储在变量result
中。 - 输出目标值的下标,格式为:"目标值的下标为: %d\n"。
提示:
- 二分查找算法的基本思想是,通过每次与数组中间元素进行比较,将搜索范围缩小一半,直到找到目标值或搜索范围为空。
- 在计算中间值
mid
时,为了避免整数溢出,可以使用mid = left + (right - left) / 2
的方式。
输出示例:
目标值的下标为: 7
代码实现:
#include <stdio.h>
// 查询目标值的下标
int find_index(int *arr, int len)
{
// 目标值
int target = 93;
// 查找范围的左边界
int left = 0;
// 查找范围的右边界
int right = len - 1;
// 计算中间值的初始位置
int mid = left + (right - left) / 2;
// 当左边界小于等于右边界时,继续查找
while (left <= right)
{
// 重新计算中间值,防止溢出
mid = left + (right - left) / 2;
// 如果中间值等于目标值,返回其下标
if (arr[mid] == target)
{
return mid;
}
// 如果中间值大于目标值,更新右边界
else if (arr[mid] > target)
{
right = mid - 1;
}
// 如果中间值小于目标值,更新左边界
else
{
left = mid + 1;
}
}
// 如果循环结束仍未找到目标值,返回-1
return -1;
}
int main()
{
// 定义有序的数组
int arr[9] = {1, 3, 6, 12, 45, 67, 89, 93, 96};
// 计算数组长度
int len = sizeof(arr) / sizeof(arr[0]);
// 调用find_index函数查找目标值的下标
int result = find_index(arr, len);
// 输出目标值的下标
printf("目标值的下标为: %d\n", result);
return 0;
}
运行结果:
六、使用冒泡排序算法对整数数组进行升序排序
问题描述:
给定一个包含9个整数的数组,要求使用冒泡排序算法对该数组进行升序排序,并输出排序后的结果。
要求:
- 编写一个C语言程序,实现上述功能。
- 在程序中定义一个整型数组,并初始化9个整数。
- 计算数组的长度,并使用冒泡排序算法对数组进行升序排序。
- 排序完成后,使用循环输出排序后的数组。
注意:
- 冒泡排序算法的基本思想是通过相邻元素之间的比较和交换,使得每一轮排序后,最大的元素能够“浮”到数组的末尾。
- 冒泡排序的时间复杂度为O(n^2),其中n为数组的长度。在实际应用中,如果数组较大,冒泡排序可能不是最高效的排序算法,可以考虑使用其他更高效的排序算法。
示例输出:
排序后的数组为: 3 6 12 45 67 89 93 93 96
代码实现:
#include <stdio.h>
int main()
{
// 排序
// 定义一个包含9个整数的数组
int arr[9] = {3, 93, 67, 96, 45, 6, 89, 93, 12};
// 计算数组的长度
int len = sizeof(arr) / sizeof(arr[0]);
// 外层循环控制排序的轮数
for (int i = 0; i < len; i++)
{
// 内层循环用于每轮比较和交换元素
for (int j = 0; j < len - i - 1; j++)
{
// 如果当前元素大于下一个元素,则交换它们的位置
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
// 输出排序后的数组
printf("排序后的数组为: ");
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n"); // 输出换行符,使输出更整洁
return 0;
}
运行结果: