字符和字符串全网最详解

字符和字符串全网最详解

字符是一个单个的字母、数字、标点符号或者其他可打印的符号。

字符使用单引号 ' ' 表示,例如:'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;如果 s1s2 则返回大于 0。

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");

相关推荐

打电话多用什么电话卡合适?
365平台靠谱吗

打电话多用什么电话卡合适?

📅 09-12 👁️ 8793
体育直播导航 - NBA直播
365beat网页怎么打不开

体育直播导航 - NBA直播

📅 10-04 👁️ 3108
中国神书《山海经》中的十个美丽传说,您听过几个?