嵌入式程序员手撕代码

目录

1、将字符串反转

2、数字翻转和回文判断

3、大小端问题

(1)判断大小端

(2)大小端转换

4、实现函数memcpy(), strcpy(), strcmp(), strcat()

 5、实现最简单的hello world字符设备驱动

6、设计函数 int atoi(char *s),void itoa(int n, char s[])

7、链表操作(单链表的插入、删除节点、遍历、反转)

8、排序算法

9、二分查找

10、 字符串转换数字

 11、求一个数中1的位数

12、判断一个数是否为2的幂

13、实现atoi

滑动窗口

 24. 两两交换链表中的节点

3. 无重复字符的最长子串

86. 分隔链表 

141. 环形链表 ​编辑

19. 删除链表的倒数第 N 个结点

 61. 旋转链表

438. 找到字符串中所有字母异位词(滑动窗口)

5. 最长回文子串

2487. 从链表中移除节点

剑指 Offer 45. 把数组排成最小的数 

1、将字符串反转

// 实现字符串反转的两个函数
// 第一个函数,参数为字符数组
void reserverString(char str[])
{
    char tmp; // 定义一个临时变量
    int i, j; // 定义两个整型变量
    // 循环遍历字符数组,i从0开始,j从字符串长度减1开始,i小于j时循环
    for (i = 0, j = strlen(str) - 1; i < j; i++, j--)
    {
        tmp = str[i]; // 将str[i]的值赋给tmp
        str[i] = str[j]; // 将str[j]的值赋给str[i]
        str[j] = tmp; // 将tmp的值赋给str[j]
    }
}
// 第二个函数,参数为字符指针
char* reserverString1(char* str)
{
    char* start = str; // 定义一个字符指针start,指向字符串的首地址
    char* end = str + strlen(str) - 1; // 定义一个字符指针end,指向字符串的末尾地址
    char tmp; // 定义一个临时变量
    // 如果传入的字符串不为空
    if (NULL != str)
    {
        // do-while循环,先执行一次循环体,再判断条件是否成立
        do
        {
            tmp = *start; // 将start指向的字符赋给tmp
            *start++ = *end; // 将end指向的字符赋给start指向的字符,然后start指针向后移动一位
            *end-- = tmp; // 将tmp的值赋给end指向的字符,然后end指针向前移动一位
        } while (start<end); // 当start指针小于end指针时继续循环
    }
    return str; // 返回反转后的字符串
}

2、数字翻转和回文判断

数字翻转

int reverse(int num) {
    int reversed = 0;
    while (num != 0) {
        reversed = reversed * 10 + num % 10;
        num /= 10;
    }
    return reversed;
}
#include <stdio.h>
int main() {
    int num, reversed_num = 0, remainder, original_num; // 定义整型变量num、reversed_num、remainder和original_num

    printf("Enter an integer: "); // 输出提示信息,要求用户输入一个整数
    scanf("%d", &num); // 读取用户输入的整数,并存储到变量num中

    original_num = num; // 将变量num的值赋给变量original_num

    while (num != 0) { // 当变量num不等于0时,执行循环体内的语句
        remainder = num % 10; // 取变量num除以10的余数,存储到变量remainder中
        reversed_num = reversed_num * 10 + remainder; // 将变量reversed_num乘以10再加上变量remainder的值,存储到变量reversed_num中
        num /= 10; // 将变量num除以10的结果,存储到变量num中
    }

    if (original_num == reversed_num) { // 如果变量original_num等于变量reversed_num,执行if语句块内的语句
        printf("%d is a palindrome.\n", original_num); // 输出变量original_num是回文数的信息
    } else { // 否则,执行else语句块内的语句
        printf("%d is not a palindrome.\n", original_num); // 输出变量original_num不是回文数的信息
    }

    return 0; // 返回0,表示程序正常结束
}

3、大小端问题

(1)判断大小端

方法一:输入一个字符变量,若数据的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处,则是大端存储方式;若数据的低位字节存储在内存的低地址处,高位字节存储在内存的高地址处,则是小端存储方式。

#include <stdio.h>
#include <stdlib.h>
 
int check_sys()
{
    int a = 1;
    return *(char*)&a;//返回1表示小端,返回0表示大端
}
 
int main()
{
    if (check_sys() == 1)
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
    system("pause");
    return 0;
}

方法二:用联合体

(2)大小端转换

//对于16位数据,定义一个宏BIG2LITTLE,用于将大端字节序转换为小端字节序
#define BIG2LITTLE(A)   ((((A)&0xff00)>>8) | (((A)&0x00ff)<<8))  

//对于32位数据,定义一个宏BIG2LITTLE,用于将大端字节序转换为小端字节序
#define BIG2LITTLE(A)  (((A)&0xff000000)>>24) | (((A)&0x000000ff)<<24) | (((A)&0x0000ff00)<<8) | (((A)&0x00ff00)>>8))

//1. 宏定义:#define 宏名(参数) 宏体

//2. & 位运算符:按位与,将两个数的二进制位进行与运算,只有两个数对应位都为1时,结果才为1,否则为0

//3. | 位运算符:按位或,将两个数的二进制位进行或运算,只要两个数对应位有一个为1,结果就为1,否则为0

//4. >> 位运算符:右移运算符,将一个数的二进制位向右移动指定的位数,移动后高位补0

//5. << 位运算符:左移运算符,将一个数的二进制位向左移动指定的位数,移动后低位补0

//6. &0xff00:将A的高8位清零,低8位保留

//7. &0x00ff:将A的低8位清零,高8位保留

//8. ((((A)&0xff00)>>8) | (((A)&0x00ff)<<8)):将A的高8位和低8位交换位置,得到小端字节序

//9. &0xff000000:将A的高8位清零,低24位保留

//10. &0x000000ff:将A的低24位清零,高8位保留

//11. &0x0000ff00:将A的低16位和高8位清零,中间的8位保留

//12. ((((A)&0xff000000)>>24) | (((A)&0x000000ff)<<24) | ((A)&0x0000ff00)<<8) | (((A)&0x00ff00)>>8)):将A的高24位和低8位交换位置,将A的次高8位和次低8位交换位置,得到小端字节序。

4、实现函数memcpy(), strcpy(), strcmp(), strcat()

(1)函数原型 :void *memcpy(void *dest, const void *src, size_t n);

功能:从源src所指的内存地址的起始位置开始,拷贝n个字节到目标dest所指的内存地址的起始位置中,函数返回dest的值。

(2)函数原型 :void strcpy (char *dest,const char*src);

功能:将src拷贝到dest中

char* strcpy(char* dest, const char* src) {
    char* p = dest;
    while (*src != '\0') {
        *p++ = *src++;
    }
    *p = '\0';
    return dest;
}

(3)函数原型 :int strcmp(const char *s,const char * t);
功能:比较字符串s和t,并且根据s按照字典顺序小于,等于或大于t的结果分别返回负整数,0,正整数。

int strcmp(const char *s, const char * t)
{
	for (; *s == *t; s++, t++)//注意for循环,能循环下去的条件的两者元素对应相等,一旦不相等立即退出
		if (*s == '\0')
			return 0;//表示相等
	return *s - *t;
}

(4)函数原型 :char *strcat(char *dest,char *src);
功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0',返回指向dest的指针

char *strcat(char *dst, const char *src) {
    // 找到目标字符串的末尾
    char *p = dst + strlen(dst);
    // 逐个字符追加源字符串,直到遇到 null 字符
    while (*src != '\0') {
        *p++ = *src++;
    }
    // 添加 null 字符
    *p = '\0';
    return dst;
}

(5)函数原型 :void *memmove(void *dest, const void *src, size_t n);
功能:将src指向的内存块中的n个字节拷贝到dest指向的内存块中。与memcpy()函数不同的是,memmove()函数可以处理源内存块和目标内存块重叠的情况,保证拷贝的正确性。因此,memmove()函数更加安全,但是相对于memcpy()函数来说,它

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值