内容提要
-
数组
-
字符数组
-
-
综合案例:学生成绩管理系统
数组
字符数组
字符串拼接
语法:
strcat(字符串1,需要拼接的字符串2); char name[] = "张三";
解释:
①这里的字符串,可以是字符串常量,也可以是字符数组或者字符指针。
②这里需要将字符串2拼接到字符串1中,所以需要字符串1有足够大的空间去容纳字符串2
引入:
#include <string.h>
案例:
-
需求:将两个字符串拼接为一个字符串
-
代码:
/*************************************************************************> File Name: demo01.c> Author: > Description: > Created Time: 2025年03月13日 星期四 09时47分53秒************************************************************************/#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){//创建一个数组,用来接收字符串常量,控制台输入char name[20];printf("请输入您的名字:\n");//通过键盘录入fgets(name,sizeof(name) / sizeof(name[0]),stdin);//通过显示器输出fputs(strcat(name,"你好"),stdout);//带""的字符串时,内存加一个\0printf("\n");return 0;}注意:
①
字符串1必须是字符数组,长度必须是够大,以便于能够容纳被链接的字符串。②连接后系统将自动取消
字符串1后面的结束符\0③
字符串2可以是字符数组名,也可以是字符串常量,如:strcat(s1"def");srrcat(s1s2);
字符串拷贝
语法:
strcpy(数组名,字符串);
解释:简单来说,类似于将一个字符串赋值给一个字符数组
引入:
#include <string.h>
说明:这个函数适合给字符串赋值
char str[20] = "张三"; //正确char str[20]; str = "张三"; //错误char str[20]; strcpy(str,"张三"); //正确
案例:
-
需求:录入名字,赋值给一个字符数组
-
代码:
/*************************************************************************> File Name: demo02.c> Author: > Description: > Created Time: 2025年03月13日 星期四 10时26分54秒************************************************************************/#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){char name[20];printf("请输入名字\n");fgets(name,sizeof(name) / sizeof(name[0]),stdin);//重新赋值strcpy(name,"谢谢回顾");printf("同学的名字是%s\n",name);return 0;}
字符串比较
语法:
strcmp(字符串1,字符串2);
字符串:字符串常量、字符数组、字符指针
引入:
#include <string.h>
功能:如果是英文,比较两个字符串对应位置字符ASCII的大小(字典顺序比较)
返回值:
-
若字符串1等于字符串2,返回0
-
若字符串1大于字符串2,返回正数(>0)
-
若字符串1小于字符串2,返回负数(<0)
说明:
①执行这个函数时,自左到右逐个比较对应字符的ASCII的值,直到发现了不同字符或者字符串结束符\0为止
②对字符串不能用数值型比较符,比如:“abc” = "abc" ,比较是错误的
③字符串1和字符串2可以是字符数组,也可以是字符指针或者字符串常量
案例:
-
需求:通过控制台输入用户名和密码,并进行校验
-
代码:
/*************************************************************************> File Name: demo03.c> Author: > Description: > Created Time: 2025年03月13日 星期四 11时15分44秒************************************************************************/#include <stdio.h> #include <string.h>int main(int argc,char *argv[]) {//用户登录案例//创建两个字符数组,用来接收控制台输入的用户名和密码char username[20],password[8];printf("--------------用户登录-------------\n");printf("请输入您的用户名:\n");scanf("%s",username);printf("请输入您的密码:\n");scanf("%s",password);//校验if(!strcmp(username,"admin") && !strcmp(password,"123456")){printf("登录成功!\n");}else{printf("用户名或者密码错误!\n");}return 0; }
字符串长度
语法:
strlen(字符串);
引用:
#include <string.h>
注意:返回字符串中包含字符的实际个数,不含\0
案例:
-
需求:字符串长度案例
-
代码:
/*************************************************************************> File Name: demo04.c> Author: > Description: > Created Time: 2025年03月13日 星期四 11时30分56秒************************************************************************/#include <stdio.h> #include <string.h>int main(int argc,char *argv[]) {//测试数据1char s1[] = {'h','i','\0','h','i','\0'};printf("数组长度:%lu,字符串长度:%lu\n",sizeof(s1)/sizeof(s1[0]),strlen(s1));//测试数据2char s2[] = "hi\0hi\0";printf("数组长度:%lu,字符串长度:%lu\n",sizeof(s2)/sizeof(s2[0]),strlen(s2));//测试数据3char s3[] = {'h','e','l','l','o'};printf("数组长度:%lu,字符串长度:%lu\n",sizeof(s3)/sizeof(s3[0]),strlen(s3));//测试数据4char s4[] = "hello";printf("数组长度:%lu,字符串长度:%lu\n",sizeof(s4)/sizeof(s4[0]),strlen(s4));return 0; } -
代码:
/*************************************************************************> File Name: demo05.c> Author: > Description: > Created Time: 2025年03月13日 星期四 14时27分46秒************************************************************************/#include <stdio.h> #include <ctype.h>int main(int argc,char *argv[]) {//创建一个数组char string[100];//创建两个变量;用来标记遍历输出字符是否为空格,默认是,0-是,1-不是,num记录单词个数int world = 0;int num = 0;//创建一个变量char c;//通过控制台输入fgets(string,sizeof(string)/sizeof(string[0]),stdin);//遍历for (int i = 0; (c = string[i])!= '\0'; i++){//如果取出的字符是空格,就设置word为0if (isspace(c))//字符是空格{//标记word = 0world = 0;}else//字符{//如果上一个字符是空格,就需要统计if(world == 0){//更改word = 1world = 1;//统计num++;}}}printf("%s中有%d个单词\n",string,num);return 0; }运行结果:
综合案例:学生成绩管理系统
需求:
-
存储最多50名学生的信息(不使用结构体)
-
每个学生包含:
-
学号(字符数组)
-
姓名(字符数组)
-
3门课程成绩(一维数组)
-
-
实现功能菜单:
-
添加学生信息
-
显示所有学生信息
-
计算学生平均分
-
查找最高分科目
-
退出系统
-
代码:
/*************************************************************************> File Name: scores_mg.c> Author: > Description: 综合案例:学生成绩管理系统> Created Time: 2025年03月13日 星期四 15时13分43秒************************************************************************/#include <stdio.h>
#include <string.h>// 定义符号常量
#define MAX_STU 50 // 学生数量
#define NAME_LEN 20 // 学生名字最大长度
#define ID_LEN 8 // 学生学号最大长度
#define COURSE_NUM 3 // 学生课程数量// 全局数组实现数据存储
char stu_id[MAX_STU][ID_LEN]; //学号
char stu_name[MAX_STU][NAME_LEN]; //姓名 //二维数组
int scores[MAX_STU][COURSE_NUM]; //成绩
int stu_count = 0; //当前实际学生数/*** 成绩录入* */
int get_valid_score(const char* course) //这里可以理解为一个不能改变值的字符串
{//用来接收控制台输入的成绩int score;while(1){printf("请输入%s成绩(0-100):",course);//对成绩校验if(scanf("%d",&score) == 1 && score >=0 && score <= 100){return score;}//校验不通过//清理缓冲while(getchar() != '\n');printf("成绩输入有误!\n");}
}/*** 添加学生*/
void add_student()
{//添加前,需要校验数组是否已满if (stu_count >= MAX_STU){printf("添加学生的人数已经达到最大值!\n");return; //跳出函数,后续代码不会再执行}printf("\n--- 添加第%d个学生 ---\n",stu_count +1);//输入学号printf("请输入学号:\n");scanf("%s",stu_id[stu_count]);// 需要清除缓冲while(getchar() != '\n');//输入姓名printf("请输入姓名:\n");scanf("%[^\n]",stu_name[stu_count]);// 匹配除了\n以外的输入// 输入成绩scores[stu_count][0] = get_valid_score("语文");scores[stu_count][1] = get_valid_score("数学");scores[stu_count][2] = get_valid_score("英语");stu_count++;}/*** 显示所有学生信息*/
void show_all()
{// 非空校验if (stu_count == 0){printf("暂无学生信息!\n");return;}// 格式化输出数据printf("\n%s\t%s\t%s\t%s\t%s\t\n","学号","姓名","语文","数学","英语") ;//表格数据for (int i = 0; i < stu_count; i++){// 获取学号和姓名printf("%s\t%s\t",stu_id[i],stu_name[i]);// 获取成绩for (int j = 0; j < COURSE_NUM; j++){printf("%d\t",scores[i][j]);}printf("\n");}printf("\n");
}/*** 计算平均分*/
void calc_avg()
{//非空校验if (stu_count == 0){printf("暂无学生信息!\n");return;}//创建一个数组,用来接收控制台输入的学号char target_id[ID_LEN];printf("请输入要查询的学号:\n");scanf("%s",target_id);// 遍历数组,通过学号在stu_id数组中找到对应下标for (int i = 0; i < stu_count; i++){//字符判断strcmpif (!strcmp(stu_id[i],target_id))//匹配学号{float sum = 0; //计算总分//通过下标在stu_scores数组中匹配对应成绩for(int j = 0; j < COURSE_NUM; j++){sum += scores[i][j];//计算总分}printf("学生%s的平均分%.2f\n",stu_name[i],sum/COURSE_NUM);return;}}//数据匹配不上printf("未找到该学生!\n");}/*** 查看最高分*/
void find_max()
{//创建一个变量,记录最高分int max_score = -1;// 创建一个变量,记录最高分课程char max_course[NAME_LEN];//创建一个变量,记录学生姓名char max_stu[NAME_LEN];//遍历数组for (int i = 0; i < stu_count; i++) // 遍历学生{for(int j = 0; j < COURSE_NUM; j++) //遍历学生对应课程{if(scores[i][j] > max_score) // 求最高成绩{max_score = scores[i][j];//最高分对应的学生名字strcpy(max_stu,stu_name[i]);//最高分对应课程名称switch(j){case 0: strcpy(max_course,"语文");break;case 1: strcpy(max_course,"数学");break;case 2: strcpy(max_course,"英语");break;}}}}//输出if(max_score != -1) printf("最高分记录:%s的%s获得%d分\n",max_stu,max_course,max_score);elseprintf("没有匹配!\n");
}/***入口*/
int main(int argc,char *argv[])
{// 定义一个变量,用来接收用户输入的选项int choice;while(1){//设计头printf("==============================\n");printf("= 学生成绩管理系统 v1.0 =\n");printf("==============================\n");printf("1.添加学生信息\n");printf("2.显示所有学生信息\n");printf("3.查看平均分\n");printf("4.查看最高分\n");printf("5.退出系统\n");printf("请选择操作:");//过滤非法输入int result = scanf("%d",&choice);if(result != 1){//清空缓冲while(getchar()!='\n');printf("请输入1-5的数字!\n");continue;}//校验输入switch(choice){case 1:// 添加学生信息add_student();break;case 2:// 显示所有学生信息show_all();break;case 3:// 查看平均分calc_avg();break;case 4:// 查看最高分find_max();break;case 5:printf("系统已经退出!\n");return 0; // 退出main函数,其实就是进程结束default:printf("无效输入\n");}}return 0;
}
中文字符在内存中存储?
在C语言中,中文字符通常使用多字节编码(如UTE-8或GBK)进行存储。由于中文字符的编码长度通常大于1个字节,因此它们在内存中的存储方式与单字节字符(如ASCII字符)有所不同。以下是中文字符在内存中存储的详细说明:
字符编码
中文字符的编码方式决定了它们在内存中的存储形式。常见的编码方式包括:
-
UTE-8:变长编码,每个中文字符通常占用3个字节。
-
GBK:周定长度编码,每个中文字符占用2个字节。
内存存储
在C语言中,中文字符是以字节序列的形式存储在内存中的。例如:
-
使用UTE-8编码时,中文字符“你”的编码是
BxE4 0xBD 0xAB,占用3个字节。 -
使用GBK编码时,中文字符"你"的编码是
Bxc4 BxE3,占用2个字节。在内存中,这些字节按照编码顺序连续存储
