嵌软八股大全1 - C & C++ 手撕真题

1、OJ在线编程常见输入输出练习

1.1、A+B(7)

题目:已知满足 1 <= n <= 100,输入若干行形如 1 2 3... 的由空格隔开的 n 个数据(n 不固定),要求输出每一行数据求和后的结果

示例输入

1 2 3
4 5
0 0 0 0 0

示例输出

6
9
0

注意:

  1. 可以利用 getchar() == '\n' 判断是否一行结束

解答:

#include <stdio.h>

int main() {
    int n,m=0;
    
    while(scanf("%d", &n) != EOF) {
        m += n;
        if(getchar() == '\n'){
            printf("%d\n", m);
            m = 0;
        }
    }
    
    return 0;
}

1.2、字符串排序(1)

题目:已知输入为两行,第一行为数字 n,第二行是形如 a b c..的由空格隔开的 n 个字符串,要求输出一行排序后的字符串,空格隔开,无结尾空格

示例输入

5
c d a bb e

示例输出

a bb c d e

注意:

  1. 每个元素都是一个字符串
  2. 使用 C 库函数 qsort 快速排序

解答:

#include <stdio.h>

int compare(const void *a,const void*b)
{
    return strcmp((const char *)a, (const char *)b);
}

int main() {
    int n,i;
    scanf("%d", &n);
    char arr[n][100];
    
    for(i=0;i<n;i++){
        scanf("%s", &arr[i]);
    }
    
   qsort(arr, n, sizeof(arr[0]), compare);
    
    for(i=0;i<n;i++){
        if(i == (n-1)) printf("%s", &arr[i]);
        else printf("%s ", &arr[i]);
    }
    
    return 0;
}

1.3、字符串排序(3)

题目:已知满足 n < 100,输入形如 xxx,xxx,xxx... 的由逗号隔开的 n 个字符串,输出一行排序后的字符串,用 , 隔开,无结尾空格

示例输入

a,c,bb
f,dddd
nowcoder

示例输出

a,bb,c
dddd,f
nowcoder

注意:

  1. 现在每一行都是一个不能分割的字符串
  2. 使用 char *fgets(char *str, int n, FILE *stream) 获取每一行输入
  3. 使用 size_t strcspn(const char *str1, const char *str2) 快速找到字符串 str1 中匹配字符串 str2 的位置
  4. 使用 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符

解答:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_LINE_LENGTH 100

// 比较函数,用于qsort排序
int compare(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}

// 主函数
int main() {
    char line[MAX_LINE_LENGTH];
    
    while (fgets(line, sizeof(line), stdin)) {
        // 去掉换行符
        line[strcspn(line, "\n")] = 0;
        
        // 拆分字符串
        char *tokens[MAX_LINE_LENGTH];
        int n = 0;
        char *token = strtok(line, ",");
        
        while (token != NULL) {
            tokens[n++] = token;
            token = strtok(NULL, ",");
        }
        
        // 排序
        qsort(tokens, n, sizeof(char *), compare);
        
        // 输出结果
        for (int i = 0; i < n; i++) {
            printf("%s", tokens[i]);
            if (i < n - 1) {
                printf(",");
            }
        }
        printf("\n");
    }
    
    return 0;
}

1.4、“看不见的错误”

题目:

已知整数 a,b 满足 0 < 𝑎, 𝑏 < 2×10^10 ,按照形如 1 1 的格式输入多组测试用例,两个整数间用空格隔开,要求输出两个整数的和

示例输入:

1 1

示例输出:

2

注意:

  1. 此题潜在的风险在于输入的两个数 a,b 最大值为 2×10^10,所以编程时要注意输入的值的类型,如果为 int ,数太大则会溢出

解答:

#include <stdio.h>

int main() {
    long m,n;
    
    while(scanf("%ld %ld", &m, &n) != EOF){
        if(getchar() == '\n'){
            printf("%ld\n", m+n);
        }
    }
    
    return 0;
}

1.5、总结

总结如下

  1. ACM 模式下使用 scanf() / cin() 作为试题输入
  2. 使用 printf() / cout() 作为试题输出
  3. 使用 getchar() == '\n' 来判断一行的输出是否结束
  4. 使用 qsort 库函数快速排序

常用标准库函数

#include <stdio.h>

char *fgets(char *str, int n, FILE *stream)


常用字符串库函数

#include <string.h>

size_t strcspn(const char *str1, const char *str2)

char *strtok(char *str, const char *delim)

2、笔试真题

2.1、求斐波那契第 n 项的值?

// 递归
int fibonacci_recursive(int n) {  
    if (n <= 0) {  
        return 0;  
    } else if (n == 1) {  
        return 1;  
    } else {  
        return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);  
    }  
}

// 迭代
int fibonacci_iterative(int n) {  
    if (n <= 0) {  
        return 0;  
    } else if (n == 1) {  
        return 1;  
    }  
  
    int prev1 = 1, prev2 = 0;  
    int result = 0;  
  
    for (int i = 2; i <= n; ++i) {  
        result = prev1 + prev2;  
        prev2 = prev1;  
        prev1 = result;  
    }  
  
    return result;  
}

变形:已知一个数列的前3个数为3,4,5,以后每个数为前3个数的和,编程序求此数列的第N项。

int fibonacci_recursive(int n) {  
    if (n <= 0) {  
        return 3;  
    } else if (n == 1) {  
        return 4;  
    } else if (n == 1) {  
	    return 5;
	} else {
        return fibonacci_recursive(n - 1) 
	        + fibonacci_recursive(n - 2) 
	        + fibonacci_recursive(n - 3);  
    }  
}

2.2、排列组合?

有 1、2、3、4 四个数字,用 C 语言编程计算能组合出多少个不重复的三位数?

#include <stdio.h>

int main() {
    int count = 0;
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++) {
            if (j == i) continue;
            for (int k = 1; k <= 4; k++) {
                if (k == i || k == j) continue;
                printf("%d%d%d\n", i, j, k);
                count++;
            }
        }
    }
    printf("All Situations: %d\n", count);
    return 0;
}

2.3、矩阵相乘?

// 需要满足 colsA == rowsB 才可以进行矩阵相乘
void multiplyMatrices(int rowsA, int colsA, int matrixA[rowsA][colsA],  
                      int rowsB, int colsB, int matrixB[rowsB][colsB],  
                      int result[rowsA][colsB]) {  
    // 无法相乘  
    if(colsA != rowsB)  
        return;  
  
    // 初始化结果矩阵  
    for (int i = 0; i < rowsA; i++) {  
        for (int j = 0; j < colsB; j++) {  
            result[i][j] = 0;  
        }  
    }  
  
    // 进行矩阵乘法运算  
    for (int i = 0; i < rowsA; i++) {  
        for (int j = 0; j < colsB; j++) {  
            for (int k = 0; k < colsA; k++) {  
                result[i][j] += matrixA[i][k] * matrixB[k][j];  
            }  
        }  
    }  
}

2.4、手撕 memcpy()

// 自定义 memcpy 函数  
void my_memcpy(void *dest, const void *src, size_t n) 
{  
    char *d = (char *)dest;  
    const char *s = (char *)src;  
  
    // 循环复制每个字节  
    while (n--) {  
        *d++ = *s++;  
    }  
}

2.5、手撕 memcpy_s()

// 函数原型
// errno_t memcpy_s(void *dest, size_t destSize, const void *src, size_t count);

#include <stdio.h>
#include <errno.h>

errno_t memcpy_s(void* dest, size_t dest_size, const void* src, size_t count) {
    // 检查空指针
    if (dest == nullptr || src == nullptr) {
        return EINVAL; // 参数无效
    }

    // 检查目标缓冲区大小是否足够
    if (count > dest_size) {
        // 若目标缓冲区不够大,则不执行复制,返回错误码
        return ERANGE; // 超出范围
    }

    // 执行内存复制
    unsigned char* d = (unsigned char*)dest;
    const unsigned char* s = (const unsigned char*)src;

    for (size_t i = 0; i < count; i++) {
        d[i] = s[i];
    }

    return 0; // 成功
}

2.6、手撕 strcpy()

// 原型:char* strcpy(char* _Dest, const char* _Source);
// 字符串赋值函数
char* my_strcpy(char* dest, const char* src)  
{  
    char *temp = dest;  
    // 将 src 的每个字符复制到 dest,直到遇到空字符  
    while((*temp++ = *src++) != '\0'){}  
    return temp;  
}

2.7、手撕 strcat()

// 原型:char* strcat(char* _Dest, const char* _Source);
// 字符串拼接函数
char* my_strcat(char* dest, const char* src)  
{  
    char *temp = dest;  
    // 移动到 dest 的末尾  
    while (*dest) {  
        dest++;  
    }  
    // 追加 src 到 dest 的末尾  
    while ((*dest++ = *src++) != '\0'){}  
    return temp;  
}

2.8、手撕 strlen()

// 原型:size_t __cdecl strlen(const char *_Str);
// 计算字符串长度函数
size_t my_strlen(const char* str)  
{  
    size_t length = 0;  
  
    // 遍历字符串直到遇到空字符  
    while (*str++) {  
        length++;  
    }  
    // 返回字符串的长度  
    return length;  
}

2.9、大端与小端相互转化?

// val = 0x12345678;
int swap_endian(int val) {  
	// 0x00000012 | 0x00003400 | 0x00560000 | 0x78000000 = 0x78563412
	return ((val >> 24) & 0x000000FF) |  
		 ((val >> 8) & 0x0000FF00) |  
		 ((val << 8) & 0x00FF0000) |  
		 ((val << 24) & 0xFF000000);  
}

2.10、实现一个 mutex 互斥锁?

关键使用 TestAndSet函数,该函数可以原子的测试并修改给定内存位置的值

int TestAndSet(int *ptr, int new) 
{
    int old = *ptr;
    *ptr = new;
    return old;
}

自己实现一个简单的锁

//锁结构体数据
typedef struct __lock_t { int flag; } lock_t;  

//初始化锁
void init(lock_t *mutex)  
{  
    // 0: lock is available  
    // 1: lock is held 
    mutex->flag = 0;  
}  
//上锁
void lock(lock_t *mutex)  
{  
    while (TestAndSet(&mutex->flag, 1) == 1) {;}  
}
//解锁
void unlock(lock_t *mutex)  
{  
    mutex->flag = 0;  
}

2.11、实现字符串反转?

“abcdefg“ -> ”gfedcba”

辅助数组方式

void reverseString(char *str) {  
    int n = strlen(str);  
    char temp[n + 1];  
  
    for (int i = 0; i < n; i++) {  
        temp[i] = str[n - 1 - i];  
    }  
  
    temp[n] = '\0';  
    strcpy(str, temp);  
}

双指针交换方式

void reverseString(char *str) {  
    int n = strlen(str);  
    char temp;  
    int left = 0;  
    int right = n - 1;  
  
    while (left < right) {  
        temp = str[left];  
        str[left] = str[right];  
        str[right] = temp;  
        left++;  
        right--;  
    }  
}

2.12、求素数?

使用 C/C++ 实现求 100 以内的素/质数

素数:除了 1 和它自身之外,不能被其他自然数整除的数

#include <stdio.h>

#define MAX 100

// 埃拉托斯特尼筛法
void sieve_of_eratosthenes(bool prime[]) {  
	// 初始化所有都为 true
	for (int i = 0; i <= MAX; i++) {  
		prime[i] = true;  
	}  
	// 0 

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

欢迎来到我的专栏,在这里,我将整理并分享2024年各大企业的真实笔试/面试真题,同时还整理了嵌入式软件相关的八股知识。专栏内容涵盖C/C++基础、嵌软常见通信协议、ARM、FreeRTOS、Linux OS相关问题汇总,希望能帮助求职者了解考试趋势和嵌入式常见考点。无论你是准备面试,还是希望提升自己的专业知识,这里都能为你提供宝贵的参考和学习资源。

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务