C 语言第 10 天学习笔记:字符串基础操作与相关函数

发布于:2025-07-28 ⋅ 阅读:(12) ⋅ 点赞:(0)

C语言学习笔记:数组与字符串及综合案例

内容提要

  • 数组
    • 字符串基础操作
    • 字符串相关函数
  • 综合案例:学生成绩管理系统v1.0

数组与字符串基础操作

在用格式化说明符%s进行输入输出时,其输入输出项均为数组名。输入时,相邻字符串需用空格分隔,系统会自动在字符串后加\0;输出时,遇到\0则结束输出。字符串操作需使用系统提供的API函数。

字符串输入

scanf

  • 语法scanf("%s", 数组名);
  • 说明:数组需为char类型,输入后默认追加\0
  • 注意:输入字符串不能包含空格,否则遇空格结束。
  • 案例
#include <stdio.h>

int main(int argc, char *argv[]) {
    char name[20]; // 存储姓名的字符数组
    printf("请输入您的名字:\n");
    scanf("%s", name); // 接收输入的字符串
    printf("您的姓名是%s\n", name);
    return 0;
}

fgets

  • 语法fgets(数组名, 数组容量, stdin);
  • 功能:从键盘录入字符串到字符数组,返回数组首地址(12位16进制数)。
  • 说明:可接收含空格或换行的字符串,需手动处理可能包含的\n
  • 案例
#include <stdio.h>

int main(int argc, char *argv[]) {
    char name[20]; // 需指定容量
    int len = sizeof(name) / sizeof(name[0]); // 计算数组容量
    printf("请输入您的姓名:\n");
    fgets(name, len, stdin); 
    printf("您的姓名是%s\n", name);
    return 0;
}
  • 注意
    • 无空格/换行的字符串可使用scanffgets
    • 含空格/换行的字符串只能用fgets

gets(危险,C11移出)

  • 语法gets(数组名);
  • 功能:从键盘录入字符串到字符数组,返回数组首地址。
  • 说明:可接收含空格/换行的字符串,但存在缓冲区溢出风险,已被C11标准移除。

字符串输出

printf

  • 语法printf("%s", 数组名);
  • 说明%s支持字符串常量、字符数组,均以字符串形式输出,遇\0结束。
  • 案例:同fgets案例中的输出部分。

fputs

  • 语法fputs(数组名, stdout);
  • 功能:输出字符串,支持包含转义字符(以\开头)。
  • 案例
#include <stdio.h>

int main(int argc, char *argv[]) {
    char arr[] = "hi yifanjiao\neat!\n";
    // 两种输出方式
    printf("%s", arr);
    fputs(arr, stdout);
    return 0;
}

puts(危险,C11移出)

  • 语法puts(数组名称);
  • 功能:输出字符串,支持转义字符,但存在安全风险,已被C11移除。

字符串相关函数

需引入头文件#include <string.h>

字符串拼接(strcat)

  • 语法strcat(字符数组, 需要拼接的字符串/字符数组/字符指针);
  • 说明
    • 参数1必须是字符数组,且剩余空间需足够容纳参数2;
    • 拼接时会删除除最后一个\0以外的所有\0
  • 案例
#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); // 拼接并输出
    printf("\n");
    return 0;
}

字符串拷贝(strcpy)

  • 语法strcpy(数组名, 字符串);
  • 功能:类似将字符串赋值给字符数组(数组不可直接赋值,需用此函数)。
  • 区别strcat是追加(如"a"+“b"→"ab”),strcpy是覆盖(如"a"+“b"→"b”)。
  • 案例
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    char name[50] = "hello";
    printf("初始化后: %s\n", name);
    strcpy(name, "my"); // 覆盖原有内容
    printf("赋值后: %s\n", name);
    return 0;
}

字符串比较(strcmp)

  • 语法strcmp(字符串1, 字符串2);
  • 返回值
    • 相等返回0;
    • 字符串1>字符串2返回正数;
    • 字符串1<字符串2返回负数。
  • 说明:逐字符比较ASCII值,不可用==直接比较字符串。
  • 案例
#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)

  • 语法strlen(字符串);
  • 功能:返回字符串实际字符数(遇\0结束,不含\0;无\0则返回数组长度)。
  • 案例
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    char s4[] = "hello";
    printf("数组长度: %lu\n字符串长度: %lu\n", 
           sizeof(s4)/sizeof(s4[0]), strlen(s4)); // 数组长度6,字符串长度5
    return 0;
}

综合案例:学生成绩管理系统v1.0

需求

  1. 存储最多50名学生信息(无结构体);
  2. 每个学生包含:学号(字符数组)、姓名(字符数组)、3门课程成绩(一维数组);
  3. 功能:添加学生信息、显示所有信息、计算平均分、查找最高分科目、退出系统。

代码实现

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

/* 系统常量定义 */
#define MAX_STU 50        // 最大学生数量
#define NAME_LEN 20       // 姓名最大长度(含\0)
#define ID_LEN 8          // 学号最大长度(含\0)
#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;                     // 实际学生数量

/* 课程名称 */
char COURSE_NAMES[COURSE_NUM][NAME_LEN] = {"语文", "数学", "英语"};

/**
 * 查找最高分科目及对应学生
 */
void find_max() {
    if (stu_count == 0) {
        printf("系统提示:当前没有学生信息!\n");
        return;
    }
    int max_score = -1;
    int max_stu_idx = -1, max_course_idx = -1;
    // 遍历所有学生和科目
    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];
                max_stu_idx = i;
                max_course_idx = j;
            }
        }
    }
    // 输出结果
    printf("系统最高分:\n");
    printf("学生:%s\n", stu_name[max_stu_idx]);
    printf("学号:%s\n", stu_id[max_stu_idx]);
    printf("科目:%s\n", COURSE_NAMES[max_course_idx]);
    printf("分数:%d\n\n", max_score);
}

/**
 * 计算指定学生平均分
 */
void calc_avg() {
    if (stu_count == 0) {
        printf("系统提示:当前没有学生信息!\n");
        return;
    }
    char target_id[ID_LEN];
    printf("请输入要查询的学生学号:");
    scanf("%7s", target_id);
    while (getchar() != '\n'); // 清空缓冲区
    // 查找学生
    for (int i = 0; i < stu_count; i++) {
        if (strcmp(stu_id[i], target_id) == 0) {
            float sum = 0;
            for (int j = 0; j < COURSE_NUM; j++) sum += scores[i][j];
            printf("学生 %s(学号:%s)的平均分:%.2f\n\n", 
                   stu_name[i], stu_id[i], sum / COURSE_NUM);
            return;
        }
    }
    printf("系统提示:未找到学号为 %s 的学生!\n\n", target_id);
}

/**
 * 显示所有学生信息
 */
void show_all() {
    if (stu_count == 0) {
        printf("系统提示:当前没有学生信息!\n");
        return;
    }
    printf("\n=== 当前所有学生信息 ===\n");
    // 表头
    printf("%-10s%-20s", "学号", "姓名");
    for (int i = 0; i < COURSE_NUM; i++) printf("%-10s", COURSE_NAMES[i]);
    printf("\n");
    // 内容
    for (int i = 0; i < stu_count; i++) {
        printf("%-10s%-20s", stu_id[i], stu_name[i]);
        for (int j = 0; j < COURSE_NUM; j++) printf("%-10d", scores[i][j]);
        printf("\n");
    }
    printf("\n系统统计:共%d名学生\n\n", stu_count);
}

/**
 * 获取有效成绩(0~100)
 */
int get_valid_score(const char* course) {
    int score;
    do {
        printf("请输入%s成绩(0~100):", course);
        scanf("%d", &score);
        while (getchar() != '\n'); // 清理缓存
        if (score < 0 || score > 100) {
            printf("输入错误:成绩必须在0~100之间!\n");
        }
    } while (score < 0 || score > 100);
    return score;
}

/**
 * 添加学生信息
 */
void add_student() {
    if (stu_count >= MAX_STU) {
        printf("系统提示:学生数量已达上限%d人!\n", MAX_STU);
        return;
    }
    printf("\n=== 正在添加第%d个学生 ===\n", stu_count + 1);
    // 输入学号
    printf("请输入学号(最多%d位数字):", ID_LEN - 1);
    scanf("%7s", stu_id[stu_count]);
    while (getchar() != '\n'); // 清理缓冲区
    // 输入姓名
    printf("请输入姓名(最多%d位字符):", NAME_LEN - 1);
    fgets(stu_name[stu_count], NAME_LEN, stdin);
    // 去除换行符
    stu_name[stu_count][strcspn(stu_name[stu_count], "\n")] = '\0';
    // 输入成绩
    printf("请依次输入各科成绩:\n");
    for (int i = 0; i < COURSE_NUM; i++) {
        scores[stu_count][i] = get_valid_score(COURSE_NAMES[i]);
    }
    stu_count++;
    printf("成功添加学生:%s(学号:%s)\n", 
           stu_name[stu_count - 1], stu_id[stu_count - 1]);
}

/**
 * 显示主菜单
 */
void show_menu() {
    printf("\n======== 主菜单 ========\n");
    printf("1. 添加学生信息\n");
    printf("2. 显示所有学生信息\n");
    printf("3. 查询学生平均分\n");
    printf("4. 查询最高分科目\n");
    printf("5. 退出系统\n");
}

/**
 * 入口函数
 */
int main(int argc, char *argv[]) {
    int choice;
    printf("= 学生成绩管理系统 V1.0 =\n");
    // 主循环
    while (1) {
        show_menu();
        // 获取用户选择
        if (scanf("%d", &choice) != 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;
            default:
                printf("输入错误:请输入1~5的有效选项!\n");
        }
    }
    return 0;
}

章节作业

一维数组练习题

  1. 键盘录入数列,用冒泡排序从大到小排序;
  2. 输入年、月、日,计算该日是当年第几天;
  3. 录入数列,求最大数、最小数、均值;
  4. 判断数列是否为回文(如12321、abba);
  5. 存储10个整数,输入一个数,找出其下标;
  6. 录入10个学员成绩:
    • 输出不及格成绩及下标;
    • 求最高分、最低分的下标;
    • 求总成绩及平均分。

二维数组练习题

  1. 二维数组中查找用户输入的数,返回行列位置;
  2. 求二维整型数组所有元素平均值、每行最大值、每列最小值;
  3. 计算行列相等数组的主对角线元素和;
  4. 计算矩阵下三角元素的和;
  5. 电影院某排某列有礼包(行和列的平方和为512),找出位置(20排,每排25座)。

字符数组练习题

  1. 读取字符串并反转输出;
  2. 判断字符串是否为回文。

思考题(选做)

  1. 求出矩阵的鞍点(行上最大且列上最大的元素)。

网站公告

今日签到

点亮在社区的每一天
去签到