深入解析:(十)嵌入式面试题收集:15道
问题 1(信息管理界面设计,C 语言实现)
以下是基于 C 语言的信息管理系统,使用结构体存储信息,支持命令行交互实现增删改查功能,以学号、姓名、班级为例:
#include
#include
#include
#define MAX 100 // 最大记录数
#define LEN 20 // 字符串长度
// 信息结构体
typedef struct {
char id[LEN]; // 学号
char name[LEN]; // 姓名
char cls[LEN]; // 班级
} Info;
Info infos[MAX]; // 存储信息数组
int count = 0; // 当前记录数
// 刷新并显示所有信息
void refresh() {
system("cls"); // 清屏(Windows系统,Linux用"clear")
printf("=== 当前信息列表 ===\n");
printf("学号\t姓名\t班级\n");
for (int i = 0; i < count; i++) {
printf("%s\t%s\t%s\n", infos[i].id, infos[i].name, infos[i].cls);
}
printf("=====================\n");
}
// 添加信息
void add() {
if (count >= MAX) {
printf("信息已满,无法添加!\n");
return;
}
Info newInfo;
printf("请输入学号:");
scanf("%s", newInfo.id);
printf("请输入姓名:");
scanf("%s", newInfo.name);
printf("请输入班级:");
scanf("%s", newInfo.cls);
// 检查学号是否重复
for (int i = 0; i < count; i++) {
if (strcmp(infos[i].id, newInfo.id) == 0) {
printf("学号已存在!\n");
return;
}
}
infos[count++] = newInfo;
refresh();
printf("添加成功!\n");
}
// 按学号查找(返回索引,-1表示不存在)
int findById(char *id) {
for (int i = 0; i < count; i++) {
if (strcmp(infos[i].id, id) == 0) {
return i;
}
}
return -1;
}
// 显示全部信息
void showAll() {
refresh();
if (count == 0) {
printf("暂无信息!\n");
}
}
// 按条件查找
void search() {
int choice;
char key[LEN];
printf("请选择查找条件:1-学号 2-姓名 3-班级:");
scanf("%d", &choice);
printf("请输入查找内容:");
scanf("%s", key);
refresh();
printf("=== 查找结果 ===\n");
int found = 0;
for (int i = 0; i < count; i++) {
if ((choice == 1 && strcmp(infos[i].id, key) == 0) ||
(choice == 2 && strcmp(infos[i].name, key) == 0) ||
(choice == 3 && strcmp(infos[i].cls, key) == 0)) {
printf("%s\t%s\t%s\n", infos[i].id, infos[i].name, infos[i].cls);
found = 1;
}
}
if (!found) {
printf("未找到匹配信息!\n");
}
}
// 修改信息
void modify() {
char id[LEN];
printf("请输入要修改的学号:");
scanf("%s", id);
int index = findById(id);
if (index == -1) {
refresh();
printf("未找到该学号信息!\n");
return;
}
// 显示当前信息
printf("当前信息:学号=%s 姓名=%s 班级=%s\n",
infos[index].id, infos[index].name, infos[index].cls);
printf("是否修改?(1-是 0-否):");
int confirm;
scanf("%d", &confirm);
if (confirm != 1) {
refresh();
return;
}
// 修改信息
printf("请输入新姓名(不修改按回车):");
char name[LEN];
getchar(); // 清空缓冲区
fgets(name, LEN, stdin);
name[strcspn(name, "\n")] = '\0'; // 去除换行符
if (strlen(name) > 0) {
strcpy(infos[index].name, name);
}
printf("请输入新班级(不修改按回车):");
char cls[LEN];
fgets(cls, LEN, stdin);
cls[strcspn(cls, "\n")] = '\0';
if (strlen(cls) > 0) {
strcpy(infos[index].cls, cls);
}
refresh();
printf("修改成功!\n");
}
// 删除信息
void delete() {
char id[LEN];
printf("请输入要删除的学号:");
scanf("%s", id);
int index = findById(id);
if (index == -1) {
refresh();
printf("未找到该学号信息!\n");
return;
}
// 移位删除
for (int i = index; i < count - 1; i++) {
infos[i] = infos[i + 1];
}
count--;
refresh();
printf("删除成功!\n");
}
// 删除全部信息
void deleteAll() {
printf("确定要删除全部信息吗?(1-是 0-否):");
int confirm;
scanf("%d", &confirm);
if (confirm == 1) {
count = 0;
refresh();
printf("全部信息已删除!\n");
} else {
refresh();
}
}
// 显示菜单
void menu() {
printf("\n===== 信息管理系统 =====\n");
printf("1. 添加信息\n");
printf("2. 显示全部\n");
printf("3. 查找信息\n");
printf("4. 修改信息\n");
printf("5. 删除信息\n");
printf("6. 删除全部\n");
printf("0. 退出系统\n");
printf("请选择操作:");
}
int main() {
int choice;
while (1) {
refresh();
menu();
scanf("%d", &choice);
switch (choice) {
case 1: add(); break;
case 2: showAll(); break;
case 3: search(); break;
case 4: modify(); break;
case 5: delete(); break;
case 6: deleteAll(); break;
case 0: printf("谢谢使用,再见!\n"); return 0;
default: printf("无效操作,请重新选择!\n");
}
printf("按任意键继续...");
getchar(); // 等待输入
getchar();
}
}
问题 2(棋子交换问题,C 语言实现)
以下是解决 2N+1 格棋子交换问题的 C 语言代码,支持通用 N 值:
#include
#include
#include
// 打印当前棋盘状态
void printBoard(char *board, int size) {
for (int i = 0; i < size; i++) {
printf("%c ", board[i]);
}
printf("\n");
}
// 移动棋子(src:源位置,dest:目标位置)
void move(char *board, int src, int dest) {
board[dest] = board[src];
board[src] = ' ';
printf("移动:%d -> %d,当前状态:", src, dest);
printBoard(board, 2 * (src > dest ? src : dest) + 1); // 打印当前状态
}
// 解决棋子交换问题(n:每种棋子数量,总格子数=2n+1)
void solveChessSwap(int n) {
int size = 2 * n + 1;
char *board = (char *)malloc(size * sizeof(char));
if (!board) {
printf("内存分配失败!\n");
return;
}
// 初始化棋盘:n个'A' + 空格 + n个'B'
for (int i = 0; i < n; i++) {
board[i] = 'A';
}
board[n] = ' '; // 中间是空格
for (int i = n + 1; i < size; i++) {
board[i] = 'B';
}
printf("初始状态:");
printBoard(board, size);
// 通用解法逻辑
for (int i = 0; i < n; i++) {
// B向左移动或跳跃(从n+1+i到n-i)
move(board, n + 1 + i, n - i);
// A向右移动或跳跃(从n-2-i到n+2+i,i=0时n-2-i可能为负,需特殊处理)
if (n - 2 - i >= 0) {
move(board, n - 2 - i, n + 2 + i);
}
}
// 补充步骤(确保最终状态正确)
if (n > 1) {
move(board, n + 1, n - 1);
if (n - 2 >= 0) {
move(board, n - 2, n + 2);
}
}
printf("最终状态:");
printBoard(board, size);
free(board);
}
int main() {
int n;
printf("请输入棋子数量n(总格子数为2n+1):");
scanf("%d", &n);
solveChessSwap(n);
return 0;
}
说明:
- 问题 1 的 C 语言实现通过命令行交互,使用结构体数组存储信息,支持所有要求的功能,操作后自动刷新界面。
- 问题 2 的 C 语言实现通过模拟棋子移动过程,支持任意 N 值的 2N+1 格情形,遵循移动规则(可移动一格或跳过对方一个棋子,A 只能右移,B 只能左移)。运行时输入 n 值(如题目中的 n=3)即可看到完整移动过程。
问题 1:关键字 const 有什么含义?
const 是 C/C++ 中的关键字,用于声明常量,表示其修饰的变量或对象的值在定义后不能被修改。主要作用包括:
- 定义常量:如
const int MAX = 100;,MAX的值不可更改。 - 修饰指针:
const int *p(或int const *p):指针指向的内容不可修改,但指针本身可以指向其他地址。int *const p:指针本身不可修改(即指向的地址固定),但指向的内容可以修改。const int *const p:指针本身和指向的内容都不可修改。
- 修饰函数参数:表示函数内部不会修改该参数的值,增强代码可读性和健壮性。
- 修饰函数返回值:表示函数返回的是常量,调用者不能修改该返回值。
问题 2:检查下面的程序有没有问题
void test1()
{
char string[10];
char* str1="0123456789";
strcpy(string, str1);
}
存在问题。
str1指向的字符串"0123456789"长度为 10(包含末尾的\0终止符),共 11 个字符。- 而
string数组仅分配了 10 个字符的空间,strcpy会将str1的所有字符(包括\0)复制到string中,导致数组越界(缓冲区溢出),可能引发程序崩溃或未定义行为。
问题 3:已知一个数组 table,用一个宏定义,求出数据的元素个数
可以通过数组总字节数除以单个元素字节数来计算元素个数,宏定义如下:
#define ARRAY_SIZE(table) (sizeof(table) / sizeof(table[0]))
- 例如,对于
int table[5];,sizeof(table)是5 * sizeof(int),sizeof(table[0])是sizeof(int),相除结果为5,即元素个数。
问题 4:写一个 “标准” 宏 MIN,这个宏输入两个参数并返回较小的一个
需要考虑参数副作用(如参数是表达式时的重复计算问题),“标准” 宏实现如下:
#define MIN(a, b) ((a) < (b) ? (a) : (b))
- 括号的作用是确保宏在复杂表达式中能正确运算,避免优先级错误。
问题 5:do……while 和 while 有什么区别?
| 特性 | while 循环 | do……while 循环 |
|---|---|---|
| 执行顺序 | 先判断条件,条件为真时执行循环体 | 先执行循环体,再判断条件 |
| 最少执行次数 | 0 次(条件初始为假时,循环体不执行) | 1 次(无论条件是否为真,循环体至少执行一次) |
| 语法格式 | while(条件) { 循环体; } | do { 循环体; } while(条件); |
问题 6:一个 32 位的机器,该机器的 16 位无符号的数据指针是多少位?
32 位。
- 指针的位数由机器的地址总线宽度决定,与指针指向的数据类型无关。在 32 位机器中,地址总线是 32 位的,因此无论数据指针是指向 16 位、32 位还是其他类型的数据,指针本身的位数都是 32 位。
问题 7:12 位 ADC 的输入电压计算
已知 12 位 ADC 的量程为\(0 \sim 4095\)(\(2^{12}-1\)),若 ADC 参考电压为\(V_{ref}\),输入电压经电阻\(R_1\)和\(R_2\)分压后接入 ADC(分压关系为\(V_{adc} = \frac{R_2}{R_1+R_2}V_{in}\)),则输入电压\(V_{in}\)的计算公式为:
\(V_{in} = \frac{adc\_value \times V_{ref} \times (R_1 + R_2)}{4095 \times R_2}\)
其中,\(adc\_value\)为 ADC 的采样值。
问题 8:计算 0 到 1000 的整数和
C 语言实现:
// 方法1:循环累加
int sum_0_to_1000_loop() {
int sum = 0;
for (int i = 0; i <= 1000; i++) {
sum += i;
}
return sum;
}
// 方法2:等差数列求和公式(更高效)
int sum_0_to_1000_formula() {
// 公式:S = n*(a1 + an)/2,其中n=1001(项数),a1=0,an=1000
return 1000 * 1001 / 2; // 结果为500500
}
问题 9:滑动滤波算法实现
滑动滤波通过维护固定长度的缓冲区,每次更新数据后计算平均值,适用于平滑高频噪声。
C 语言实现(窗口长度为 5):
#define FILTER_WINDOW 5 // 滑动窗口大小
static int adc_buffer[FILTER_WINDOW] = {0}; // 存储历史采样值
static int buffer_index = 0; // 当前缓冲区索引
static int total_sum = 0; // 缓冲区总和
// 输入新的ADC采样值,返回滤波后的值
int sliding_filter(int new_adc) {
// 减去缓冲区中最旧的值
total_sum -= adc_buffer[buffer_index];
// 存入新值并累加
adc_buffer[buffer_index] = new_adc;
total_sum += new_adc;
// 更新索引(循环覆盖)
buffer_index = (buffer_index + 1) % FILTER_WINDOW;
// 返回平均值(滤波结果)
return total_sum / FILTER_WINDOW;
}
说明:
- 静态变量确保缓冲区状态在多次调用中保持。
- 每次更新仅需加减操作,时间复杂度为\(O(1)\),效率高。
问题 1:用 C 语言实现一个函数,判断一个整数是否为素数
答案 1:
#include
#include
// 判断n是否为素数(素数:大于1的自然数,除了1和自身外无其他因数)
bool is_prime(int n) {
if (n <= 1) {
return false; // 1和负数不是素数
}
if (n == 2) {
return true; // 2是素数
}
if (n % 2 == 0) {
return false; // 偶数不是素数(除2外)
}
// 检查到sqrt(n)即可,因为因数成对出现
for (int i = 3; i <= sqrt(n); i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
问题 2:编写 C 语言代码,将一个字符串反转(如 "hello" 反转后为 "olleh")
答案 2:
#include
void reverse_string(char *str) {
if (str == NULL) {
return; // 空指针处理
}
int len = strlen(str);
int left = 0;
int right = len - 1;
// 左右指针交换字符,直到相遇
while (left < right) {
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++;
right--;
}
}
问题 3:用 C 语言实现冒泡排序算法,对整数数组进行升序排序
答案 3:
// 冒泡排序(升序):每次比较相邻元素,将大的元素"浮"到末尾
void bubble_sort(int arr[], int n) {
if (n <= 1) {
return; // 数组长度<=1无需排序
}
for (int i = 0; i < n - 1; i++) {
int flag = 0; // 标记本轮是否有交换,优化无交换时提前退出
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换相邻元素
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if (flag == 0) {
break; // 无交换,数组已有序
}
}
}
问题 4:编写 C 语言函数,计算两个整数的最大公约数(GCD)
答案 4:
// 方法1:辗转相除法(欧几里得算法)
int gcd(int a, int b) {
// 保证a >= b,若a < b则交换
if (a < b) {
int temp = a;
a = b;
b = temp;
}
// 当余数为0时,除数即为最大公约数
while (b != 0) {
int remainder = a % b;
a = b;
b = remainder;
}
return a;
}
// 方法2:递归实现辗转相除法
int gcd_recursive(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd_recursive(b, a % b);
}
}
问题 5:用 C 语言实现一个函数,将十进制整数转换为二进制字符串(如 10 转换为 "1010")
答案 5:
#include
// 将十进制整数n转换为二进制字符串,存储到buf中(需保证buf足够大)
void decimal_to_binary(int n, char *buf) {
if (buf == NULL) {
return;
}
if (n == 0) {
strcpy(buf, "0");
return;
}
int is_negative = 0;
// 处理负数(简单表示为符号+绝对值的二进制,非补码)
if (n < 0) {
is_negative = 1;
n = -n;
}
int index = 0;
// 提取二进制位(从低位到高位)
while (n > 0) {
buf[index++] = (n % 2) ? '1' : '0';
n /= 2;
}
// 添加负号(如果是负数)
if (is_negative) {
buf[index++] = '-';
}
buf[index] = '\0'; // 字符串结束符
// 反转字符串(因为上面是从低位开始存储的)
reverse_string(buf); // 复用问题2的反转函数
}

浙公网安备 33010602011771号