字符是一个单个的字母、数字、标点符号或者其他可打印的符号。
字符使用单引号 ' ' 表示,例如:'a'、'1'、'!' 等。
字符串是字符数组或指针,表示一个或多个字符组成的一串。
字符串使用双引号 " " 表示,例如:“hello”、“world” 等。
字符串的最后一个字符是 ‘\0’,表示字符串的结尾。
字符串数组的长度是字符个数再加上一个‘\0’.
比如:char str[] = "hello world";那么字符个数就是{ 'h','e','l','l','o',' ','w','o','r','l','d','\0' },共12个字符(注意里面还有一个空格)加1个\0。
字符
定义字符
char a = 'H'; //定义一个字符变量a并赋值为'H'
char b = '3';
char c = '!';
打印字符
printf("%c\n", a); //打印字符a
//打印字符使用的就是 %c 格式化符
//字符串使用 %s
同时使用的格式化符不同也会有不同效果
char a = 'h';
printf("%c\n", a); //输出 h
printf("%d\n", a); //输出 h的ASCII码 104
//如果变量a的值是字母,%d会打印出字母的ASCII码, %c直接打出字母
//如果变量a的值是数字,%d会打印出数字的ASCII码, %c直接打出数字
char可以当int使用,而且比int省空间(通常为1字节)。
其范围取决于系统定义:
带符号char:-128 到 127(共256个值)
无符号char:0 到 255(共256个值)
输入字符
scanf
char a;
scanf("%c", &a); // 注意格式化符是 %c
printf("%c\n", a);
getchar
char a;
a=getchar();
printf("%c\n", a);
字符串
定义字符串
char a[] = "hello world";// 使用数组定义字符串。
打印字符串
char a[20] = "hello world";
printf("%s\n", a); // 格式化符是 %s
输入字符串
scanf
char a[20];
scanf("%19s", a); // 限制输入长度为19,留1字节给'\0'
printf("%s\n", a);
限制和潜在的问题:
scanf() 在遇到空格、制表符或换行符时会停止读取,这意味着它无法读取包含空格的完整句子。
scanf() 不会检查输入的字符串长度是否超过数组的大小,可能导致缓冲区溢出的安全问题。
如果用户输入的字符串超过了数组的大小,多余的字符会留在输入缓冲区中,可能影响后续的输入操作。
gets
char a[20];
gets(a);
printf("%s\n", a);
gets() 函数存在严重的安全隐患:
gets() 不会检查输入的字符串长度是否超过数组的大小,很容易导致缓冲区溢出。
由于安全问题,gets() 函数在 C11 标准中已经被废弃,许多现代编译器会发出警告或错误。
fgets
char a[20];
fgets(a, 20, stdin);
printf("%s\n", a);
fgets() 函数有三个参数:存储字符串的数组、最大读取的字符数(包括空字符)和输入流(这里使用 stdin 表示标准输入)。
fgets() 的优点包括:
可以安全地读取指定长度的字符串,避免缓冲区溢出。
可以读取包含空格的完整行。
如果输入的字符串过长,fgets() 会自动截断,而不会造成安全问题。
需要注意的是,fgets() 会保留输入中的换行符。我们使用 strcspn () 函数来去除末尾的换行符。 a[strcspn(a, "\n")] = '\0'; // 去除换行符
多个字符串
二维数组
每个字符串都存储在一个固定大小的字符数组中,整个数组是二维的。
#include
int main() {
char words[][10] = {"shift", "fuck", "wc"};
int count = sizeof(words) / sizeof(words[0]);
for (int i = 0; i < count; i++) {
printf("%s\n", words[i]);
}
return 0;
}
说明:
10 是每个字符串的最大长度(包括 \0),可根据实际需要调整。
每个字符串是独立的字符数组,可以修改其内容(如 words[0][0] = 'S'; 是合法的)。
优点:
可修改字符串内容。
更适合需要对字符串内容进行操作的场景。
注意:
需要提前指定每个字符串的最大长度。
内存固定分配,不够灵活。
指针
这是最常见、最灵活的方式。将每个字符串的地址(指针)存入一个 char * 类型的数组中。
c
深色版本
#include
int main() {
char *words[] = {"shift", "fuck", "wc"};
int count = sizeof(words) / sizeof(words[0]);
for (int i = 0; i < count; i++) {
printf("%s\n", words[i]);
}
return 0;
}
优点:
语法简洁,易于初始化。
字符串内容不可修改(常量字符串),适用于只读场景。
每个字符串占用的内存由系统自动分配。
注意:
不可对字符串内容进行修改(如 words[0][0] = 'S'; 会导致未定义行为)。
适合存储固定数量的字符串。
动态分配(malloc)
适用于运行时动态生成或读取字符串的情况。
#include
#include
#include
int main() {
char **words = (char **)malloc(3 * sizeof(char *));
int i;
words[0] = strdup("shift");
words[1] = strdup("fuck");
words[2] = strdup("wc");
for (i = 0; i < 3; i++) {
printf("%s\n", words[i]);
free(words[i]); // 释放每个字符串
}
free(words); // 释放指针数组
return 0;
}
优点:
灵活,适合动态生成或读取字符串。
可自由控制内存大小。
注意:
使用完后必须手动释放内存,防止内存泄漏。
strdup 是非标准函数(但广泛支持),功能是复制字符串并分配内存。
📌 总结对比
方法
是否可修改
内存管理
适用场景
字符指针数组
❌ 不可修改
自动管理
只读字符串,简单快速
二维字符数组
✅ 可修改
固定分配
需要修改字符串内容
动态分配(malloc)
✅ 可修改
手动管理
动态生成或读取字符串
✅ 推荐使用方式
简单使用:推荐使用 字符指针数组,语法简洁,适合大多数情况。
需要修改内容:使用 二维字符数组,确保每个字符串有足够空间。
动态生成字符串:使用 动态分配,但需注意内存释放。
常用函数
注意 :下面这些函数全部需要头文件string.h
要写 #include
1
strcpy(s1, s2); 复制字符串 s2 到字符串 s1。
2
strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。
3
strlen(s1); 返回字符串 s1 的长度。
4
strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1
5
strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
6
strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
strcpy
char a[20] = "Hello World!";
char c[20];
strcpy(c, a); //将a的值复制到c中
printf("%s\n", c);
strcat
char a[20] = "Hello World!";
char b[20] = "shit fuck";
strcat(a,b);//将b连接到a后面去
printf("%s\n", a);
strlen
char a[20] = "Hello World!";
len = strlen(a); // 这里计算的是实际有几个字符,不是数组定义的长度
printf("%d\n", len);
strcmp
char s1[] = "apple";
char s2[] = "banana";
int result = strcmp(s1, s2); // 比较 s1 和 s2
if (result == 0)
printf("字串相等 \n");
else if (result < 0)
printf("s1 小于 s2.\n");
else
printf("s1 大于 s2.\n");
strchr
char str[] = "Hello, world!";
char ch = 'w';
char *ptr = strchr(str, ch); // 查找字符 'w' 的首次出现位置
if (ptr != NULL)
printf("字符 '%c' 找到位置在: %s\n", ch, ptr);
else
printf("字符 '%c' 没找到.\n", ch);
//运行结果:
//字符 'w' 找到位置在: world!
strstr
查找 子字符串 "world" 在 str 中的首次出现位置,返回指向该位置的指针。
char str[] = "Hello, world!";
char sub[] = "world";
char *ptr = strstr(str, sub); // 查找子字符串 "world" 的首次出现位置
if (ptr != NULL)
printf("子字符串发现位置: %s\n", ptr);
else
printf("没发现子字符串.\n");