嵌入式C语言学习笔记 - 指针、字符串、结构体

函数指针

作用:利用函数指针,可以动态的调用函数;

格式:返回类型 (*指针名)(形参列表)

void function()
{
    printf("run the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);//日志打印
}

int function2(int num1,int num2)
{
    printf("run the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);//日志打印 函数名、文件、所在行编号
    return num1+num2;//返回入参中两个数值和
}


int main()
{
    //函数指针
    int (*p_fun)(int,int) = function2;
    void (*p1_fun)(void) = function;
    int sum = p_fun(5,10);
    p1_fun();
}
int add(int a,int b)
{
    return a+b;
}
int sub(int a,int b)
{
    return a-b;
}
int mul(int a,int b)
{
    return a*b;
}
int div(int a,int b)
{
    return a/b;
}

int main()
{
    int (*p_calc[4])(int,int) = {add,sub,mul,div};//函数指针数组
    printf("请输入两个数字参与计算:\n");
    int a = 0;
    int b = 0;
    scanf("%d %d",&a,&b);
    printf("请输入你要进行的操作:\n");
    printf("0:加法 1:减法 2:乘法 3:除法\n");
    int op = 0;
    scanf("%d",&op);
    if (op < 0 || op > 3)
    {
        printf("输入错误,请重新输入\n");
        return -1;
    }
    int res = p_calc[op](a,b);
    printf("the result is %d\n",res);

}

字符串

在C语言中,处理字符串通常涉及到使用字符数组(char 数组),字符串:定义可以使用双引号引起来的;字符串结束标志'\0';

字符串使用依赖标准库(头文件)<string.h>

常见字符串命令(比较、替换、截取、查找、切割、检索、加密、打乱内容、大小写转换):

strcpystrcatstrlenstrcmp 等

字符串定义方式:

char str[4+1] = “abcd”; //数组:内容长度+结束符’\0’
char *str = “abcd”;       //指针,存放在只读区内,不可以修改

void stringTest()
{
    //字符串的定义 利用字符数组+双引号的方式定义字符串
    char str[4+1] = "abcd";//4个字符(字符串长度小于等于4)+1个结束符;字符串长度等于数组长度的时候可能存储不完全
    //字符串的定义 利用字符指针+双引号的方式定义字符串
    char* str1 = "abcd";//会把字符数组放在只读区,不能修改;里面定义的字符串是可以复用的
    char* str2 = "abcd";//在创建abcd字符串的时候,str1和str2指向同一块内存区域
    //在创建ABCD的时候,会检查只读区是否有相同的字符串,如果有就直接指向同一块内存区域,如果没有就创建一块新的内存区域
    printf("the string is %s\n",str);
    printf("the string is %s\n",str1);
    printf("%p\n",str1);
    printf("%p\n",str2);
}

字符输入

int stringScanf()
{
    char str[20] = {0};
    printf("请输入一个字符串:\n");
    scanf("%s",str);
    if (strlen(str) > (sizeof(str)-1)) //判断输入字符串长度是否大于字符串数组允许输入的最大值
    {
        printf("输入的字符串长度超过20个字符,请重新输入\n");
        return -1;
    }
    printf("the string is %s\n",str);
    return 0;
}

字符串输入及使用指针遍历

void stringScanf1()
{
    char str[20] = {0};
    printf("请输入一个字符串:\n");
    scanf("%s",str);//scanf函数会自动添加结束符'\0',所以不需要手动添加
    if (strlen(str) > (sizeof(str)-1))//判断字符串长度是否超过20个字符
    {
        printf("输入的字符串长度超过20个字符,请重新输入\n");
        return;
    }
    char* p = str;  
    //利用指针遍历字符串
    printf("the string is :");
    while(1)
    {
        if (*p == '\0') //字符串结束标志
        {
            break;
        }
        printf("%c",*p);
        p++;
    }
    printf("\n");
}

字符串数组

void stringarr()
{
    char arrstr[5][20] = {"hello","world","nihao","zhongguo","shijie"};
    for(int i = 0;i < 5;i++)
    {
        printf("the string is %s\n",arrstr[i]);//利用数组下标遍历二维数组
    }
    char* p = arrstr[0];
    for(int i = 0;i < 5;i++)
    {
        printf("the string is %s\n",p);
        p += 20;//每次移动20个字节,二维数组中的每个字符串长度为20,利用指针加法遍历二维数组
    }
    for(int i = 0;i < 5;i++)
    {
        p = arrstr[i];//利用指针遍历二维数组,指针每次获取二维数组中的一个字符串
        printf("the string is %s\n",p);
    }
    //把五个字符串的指针放到一个数组中,指针数组
    char* p_arr[5] = {"hello","world","nihao","zhongguo","shijie"};
    for(int i = 0;i < 5;i++)
    {
        printf("the string is %s\n",p_arr[i]);
    }
}

字符串常见函数

常见string函数strlen(长度)、strcpy(复制)、strcat(拼接)、strcmp(比较)

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

void stringFunction()
{
	//常见string函数strlen(长度)、strcpy(复制)、strcat(拼接)、strcmp(比较)、strchr、strstr、strlwr(转小写)、strupr(转大写)
	char* str = "hello world";//字符串常量,存放在只读区
	char str1[20] = "abcd";   //字符串数组,存放在栈区
	char str2[20] = "hello";

	printf("the string length is %lu\n",strlen(str));
	printf("the string length is %lu\n",strlen(str1));
	printf("the string length is %lu\n",strlen(str2));

	/*strcat把第二字符串的全部的内容,拷贝到第一个字符串的末尾
	1.第一个字符串是需要可以修改的(可写的)
	2.第一个字符串中的剩余空间可以容纳拼接的字符串*/
	strcat(str1,str2);//拼接字符串
	printf("the string is %s\n",str1);
	printf("the string is %s\n",str2);

	/*strcpy:把第二个字符串中的全部内容,拷贝到第一个字符串中,把第一个字符串里面的原始内容给覆盖了
	1.第一个字符串是需要可以修改的(可写的)
	2.第一个字符串中的剩余空间可以第二个的字符串全部内容*/
	strcpy(str1,str2);//复制字符串
	printf("the string is %s\n",str1);
	printf("the string is %s\n",str2);

	/*strcmp:比较两个字符串;在比较的时候要求顺序和内容一致,才能返回0
	1.如果第一个字符串大于第二个字符串,返回正数
	2.如果第一个字符串小于第二个字符串,返回负数
	3.如果两个字符串相等,返回0*/
	int res = strcmp(str1,str2);
	if (res > 0)
	{
		printf("the string %s is greater than %s\n",str1,str2);
	}
	else if (res < 0)
	{
		printf("the string %s is less than %s\n",str1,str2);
	}
	else
	{
		printf("the string %s is equal to %s\n",str1,str2);
	}

	/*strlwr*/
	//strlwr(str1);//把字符串转换成小写
	//printf("the string is %s\n",str1);

	/*strupr*/
	//strupr(str1);//把字符串转换成大写
	//printf("the string is %s\n",str1);

}

使用 strlen 函数获取字符串的长度(不包括结尾的空字符)。

#include <stdio.h>
#include <string.h> // 包含strlen的声明
 
int main() 
{
    char str[] = "Hello, world!";
    int length = strlen(str); // 获取字符串长度
 
    printf("Length of '%s' is %d.\n", str, length);
    return 0;
}

使用strcpy复制字符串内容

#include <stdio.h>
#include <string.h>
 
int main() 
{
    char str1[] = "Hello, world!"; // 初始化字符串
    char str2[50]; // 定义一个足够大的字符数组来存储字符串
 
    // 使用strcpy复制字符串
    strcpy(str2, str1); // 将str1的内容复制到str2
 
    printf("str1: %s\n", str1);
    printf("str2: %s\n", str2);
 
    return 0;
}

使用 strcat 函数可以将两个字符串连接起来。

#include <stdio.h>
#include <string.h> // 包含strcat的声明
 
int main() 
{
    char str1[50] = "Hello, ";
    char str2[] = "world!";
    char str3[100]; // 确保有足够的空间存储结果
 
    // 使用strcat连接字符串
    strcat(str1, str2); // 将str2连接到str1的末尾
    strcpy(str3, str1); // 可以选择复制回str3以保留原始str1内容
 
    printf("Combined string: %s\n", str1);
    return 0;
}

使用 strcmp 函数比较两个字符串。这个函数返回0如果两个字符串相等,返回负值如果第一个字符串在字典序上小于第二个,返回正值如果第一个字符串在字典序上大于第二个;

#include <stdio.h>
#include <string.h> // 包含strcmp的声明
 
int main() 
{
    char str1[] = "Hello";
    char str2[] = "World";
    char str3[] = "Hello";
    int result;
 
    result = strcmp(str1, str2); // 比较str1和str2
    if (result == 0) {
        printf("str1 and str2 are equal.\n");
    } else if (result < 0) {
        printf("str1 is less than str2.\n");
    } else {
        printf("str1 is greater than str2.\n");
    }
 
    result = strcmp(str1, str3); // 比较str1和str3,两者相等,应返回0
    if (result == 0) {
        printf("str1 and str3 are equal.\n"); // 应输出此行信息
    } else {
        printf("str1 is not equal to str3.\n"); // 不应输出此行信息,除非有错误或特殊情况发生。正常情况下不会执行到这里。
    }
    return 0;
}

利用字符实现用户、密码登录功能(demo)

实际上用户相关信息在数据库中都需要加密存储(用户安全隐私合规),用户相关信息不能进行明文存储;

使用到C语言相关知识:函数、指针、结构体(结构体起别名、结构体初始化、使用指针实现结构体访问)、字符串(只读、输入、字符串长度、字符串比较)、字符数组、for、if break、continue等


typedef struct user
{
	char username[20];
	char password[20];
}user_t;

void userLogin(user_t* p_user)
{
	char *username = "zhangtao";
	char *password = "Cxm940521";
	for(int i = 0;i < 5;i++)
	{
		printf("请输入用户名,长度20字符以内:\n");
		scanf("%s",p_user->username);
		if (strlen(p_user->username) > 20)
		{
			printf("用户名长度超过20个字符,请重新输入\n");
			continue;
		}
		printf("请输入密码(长度20字符以内,大写,小写,数字)\n");
		scanf("%s",p_user->password);
		if (strlen(p_user->username) > 20 || strlen(p_user->password) > 20)
		{
			printf("用户名或密码长度超过20个字符,请重新输入\n");
			continue;
		}
		if (strcmp(username,p_user->username) == 0 && strcmp(password,p_user->password) == 0)
		{
			printf("登录成功\n");
			break;
		}
		else
		{
			printf("登录失败,剩余 次%d\n",5-i);
			continue;
		}
	}
}

结构体

结构体(Structures)是一种复合数据类型,允许将多个不同类型的数据项组合成一个单一的类型;

结构体可以理解为自定义的数据类型 ,由一批数据组合而成的结构型数据,里面的每一个数据都是结构体的成员;

 结构体的定义方式

struct human//定义结构体
{
	char name[20];
	int age;
	float height;
	float weight;
};

void printHuman()
{
	struct human h1; //定义human结构体h1
    //初始化结构体h1内容
	h1.age = 10;
	h1.height = 1.75f;
	h1.weight = 60.0f;
	strcpy(h1.name,"zhangsan");//字符串(数组)初始化使用strcpy
    
    //打印结构体结构体内容
	printf("the name is %s\n",h1.name);
	printf("the age is %d\n",h1.age);
	printf("the height is %f\n",h1.height);
	printf("the weight is %f\n",h1.weight);
}
typedef struct //上面的名称可以有,也可以省略
{
	char name[20];
	int age;
}student_t;    //结构体别名,后缀_t


void changeStudent(student_t* p_student)//定义结构体指针p_student
{
    //使用结构体指针访问结构体,
	strcpy(p_student->name,"lisi");
	p_student->age = 20;

    //结构体信息打印
	printf("the name is %s\n",p_student->name);
	printf("the age is %d\n",p_student->age);
}

结构体在嵌入式中注意事项(内存相关)

内存分布:

确定变量位置:只能放在自己类型数据整数倍的内存地址上;

最后一个补位:结构体的总大小,是最大类型的数据的整数倍;

常见定义方式:先定义占用内存空间少的成员,在定义占用内存空间多的成员;

typedef struct number
{
	double a;//0-7
	char b;//8
	int c;//12-15
	char d;//16  补位对齐值23;总长度24字节,起始字节为0
}number_t;


typedef struct
{
	double a;//0-7
	char b;//8
    char d;//9
	int c;//12-15
}number1_t;


int main()
{
	number_t num;
    number1_t num1;
	printf("the size of number_t is %lu\n",sizeof(num));//占用24字节
    printf("the size of number_t is %lu\n",sizeof(num1));//占用16字节
}
/*思考一下为什么*/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值