深入解析:(十)嵌入式面试题收集: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. 问题 1 的 C 语言实现通过命令行交互,使用结构体数组存储信息,支持所有要求的功能,操作后自动刷新界面。
  2. 问题 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的反转函数
}
posted @ 2025-12-12 11:04  gccbuaa  阅读(19)  评论(0)    收藏  举报