收集飞花令碎片——C语言字符串(纯干货)

收集飞花令碎片——C语言字符串(纯干货)

前言

在走进的代码世界之前,先领略一下小桥流水美景的诗意世界吧

完了就直接进入正题

一、C语言字符串的手动内存管理

1、C语言无字符串

"hello bit.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。

2、'\0’的重要性

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
    char arr1[] = "Hello";
    char arr2[] = { 'H', 'e', 'l', 'l', 'o' };
    char arr3[] = { 'H', 'e', 'l', 'l', 'o', '\0'};
    printf("%s\n", arr1);
    printf("%s\n", arr2);
    printf("%s\n", arr3);
    return 0;
}


在上面的代码运行结果可以看到,我们在输出arr2时出现了乱码形式

思考:为什么会出现这种情况呢?
因为在arr2中并不包含字符串的结束标志即’\0’,所以会出现上面的乱码!


字符串与\0的深度解析

  1. 当我们用printf()函数以字符串形式进行输出时,只有遇到’\0’才会停止输出


    这时候肯定会有码友会问:为什么输出arr1就不会产生乱码?

  2. 因为在 “” 里面的字符串中就已经自动包含了字符串的结束标志即’\0’,所以当我们输出arr1自然就不会产生乱码

  3. 当我们在使用 {} 字符串的定义的方式时,一定要记得加上字符串的结束标志,否则就会出现乱码现象

小编提醒:一个合格的程序员必备的素养,是对代码的每一处细节严格把控,虽然我们有时候用不到,但这却是我们必须要做的

3、字符串的初始化

方式 示例 说明
直接赋值 char s[] = "abc"; 自动计算长度并补 '\0'(长度=4)
指定大小 char s[5] = "abc"; 剩余空间填充 '\0'(实际存储 a b c \0 \0
逐个字符 char s[4] = {'a','b','c','\0'}; 必须显式添加 '\0',否则不是合法字符串
指针 char *s = "abc"; 指向只读的字符串常量(不可修改内容)


4、与字符串相关的格式说明符

在 C 语言中,与字符串相关的格式说明符主要用于输入/输出函数

(1)%s

用途:输入/输出 字符串(以 ‘\0’ 结尾的 char 数组或指针)。

代码示例:

char str[] = "Hello";
printf("%s\n", str);  // 输出字符串
scanf("%s", str);     // 输入字符串(遇空格停止)
  • 注意:
    scanf(“%s”, str) 不安全(可能缓冲区溢出),推荐:
scanf("%19s", str);  // 限制最大长度(数组大小-1)


  • 或使用 fgets:
fgets(str, sizeof(str), stdin);  // 更安全(读取一行)


(2)%c

用途:输入/输出 单个字符(char 类型)。

代码示例:

char ch = 'A';
printf("%c\n", ch);  // 输出字符 'A'
scanf("%c", &ch);    // 输入单个字符(包括空格/换行)

注意:

若需跳过空白字符,加空格:

scanf(" %c", &ch);  // 忽略前面的空格/换行


(3)%p

用途:输出 指针的地址(十六进制格式)。

代码示例:

char *ptr = "Hello";
printf("%p\n", (void *)ptr);  // 输出指针地址(如 0x55a1b2c3d4e5)

后面我们讲到指针的时候会深度解析



拓展:fgets

fgets 是 C 语言标准库中用于安全读取字符串的重要函数,相比 gets 和 scanf 的 %s,它提供了更好的安全性和控制能力。

最简单的 fgets 使用模板
#include <stdio.h>

int main() {
    char buffer[100]; // 定义一个足够大的字符数组
    
    printf("请输入内容: ");
    fgets(buffer, sizeof(buffer), stdin); // 读取输入
    
    printf("你输入的是: %s", buffer);
    
    return 0;
}z


关键要点

三个必要参数:
buffer:存储输入的字符数组
sizeof(buffer):最大读取长度(自动计算数组大小)
stdin:表示从标准输入(键盘)读取

自动添加结束符:
fgets 会自动在字符串末尾添加 \0
所以实际读取的字符数 = 指定长度 - 1


拓展:使用fgets的时候,如何去掉换行符



如果用户按了回车,换行符 \n 会被包含在字符串中
示例:输入 “hello” 后按回车,buffer 内容为 “hello\n\0”



这时候我们可以用到头文件<string.h>来去除换行符
头文件<string.h>的讲解篇章在下面

#include <stdio.h>
#include <string.h> // 需要用到 strcspn

int main() {
    char buffer[100];
    
    printf("请输入: ");
    fgets(buffer, sizeof(buffer), stdin);
    
    // 去除换行符
    buffer[strcspn(buffer, "\n")] = '\0';
    
    printf("处理后的输入: %s", buffer);
    return 0;
}




(4)其它相关的格式说明符

下面这些说明符虽然功能强大,但是很少被使用,这里我们只是作简单的讲解,感兴趣的朋友可以去了解一下

1. %[…](扫描集)

用途:自定义 scanf 的输入规则。

  • 代码示例:
char str[50];
scanf("%[^\n]", str);  // 读取一行(直到换行符)
scanf("%[a-z]", str);  // 只读取小写字母
  • 常见用法:

%[^\n]:读取一行(含空格)。
%[^,]:读取直到逗号。

2. %n

用途:记录已输出的字符数(不消耗参数)。

  • 代码示例:
int count;
printf("Hello%nWorld\n", &count);  // count = 5("Hello"的长度)
3. %*s(抑制赋值)

用途:跳过输入的字符串。

  • 代码示例:
char str[10];
scanf("%*s %s", str);  // 跳过第一个单词,读取第二个


二、C语言字符串的库函数

<string.h> 是C语言中处理字符串和内存操作的重要头文件,下面介绍其中最常用的函数,适合初学者掌握核心功能。


由于<string.h>包含很多英文,为了方便大家的记忆,我会将每个英文前置并在后面附上其作用,方便大家的记忆

1、字符串基本操作

(1) strlen(长度计算)

size_t len = strlen(str); // 不计算'\0'


(2) strcpy(复制)

strcpy(char dest[] , const char arc[]);  // 可能溢出
  • 功能:将src字符串复制到dest字符串
(2.1)strncpy(复制):
strncpy(dest, src, n); // 最多复制n个字符
  • 功能:strncpy可以指定最大复制字符数


(3) strcat(连接)

strcat(dest, src); // 可能溢出
(3.1)strncat(连接)
strncat(dest, src, n); // 最多连接n个字符


(4) strcmp(比较)

int strcmp(const char str1[], const char str2[]);
  • 功能:比较两个字符串
(4.1)strncmp(比较)
int strncmp(const char str1[], const char str2[], size_t n);
  • 功能:指定几个字符进行比较

返回值:

  • 0:相等
  • 负数:str1小于str2
  • 正数:str1大于str2


代码示例:

if(strcmp("apple", "banana") < 0) {
    printf("apple在banana前面");
}


2、内存操作函数

(1)memset(内存设置)

void memset(char arr[], int value, size_t num);
  • 功能:将arr数组的前num个字节设置为value,常用于初始化数组

代码示例:

char buffer[50];
memset(buffer, 0, 50); // 将buffer全部初始化为0


(2)memcpy(内存复制)

void memcpy(char dest[], const char src[], size_t num);
  • 功能:从src数组复制num个字节到dest数组

代码示例:

int src[5] = {1,2,3,4,5};
int dest[5];
memcpy(dest, src, sizeof(src)); // 复制整个数组


3、内存查找函数

(1) strchr(查找字符位置)

int strchr(const char str[], int c);
  • 功能:查找字符c在str中第一次出现的位置,返回字符的索引位置,找不到返回-1

代码示例:

int pos = strchr("Hello", 'l'); // pos现在是2


(2) strstr(查找子串位置)

int strstr(const char haystack[], const char needle[]);
  • 功能:在haystack中查找needle,返回子串开始的位置索引,找不到返回-1

代码示例:

int pos = strstr("Hello world", "wor"); // pos现在是6

注意事项
使用这些函数时要确保目标数组足够大
字符串必须以’\0’结尾
数组索引从0开始计算
记得包含头文件 #include <string.h>


三、小编附言

为了方便大家的理解,本期的字符串没有附带指针的内容,后续讲指针的时候,会与字符串联系在一起讲

看到这里麻烦给个三连吧

转载请说明出处内容投诉
CSS教程网 » 收集飞花令碎片——C语言字符串(纯干货)

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买