在学习字符和字符串函数之前,我们先认识一下ASCLL码,ASCII 编码是字符处理的基础,了解其规则对编程非常重要!
ASCII是一种字符编码标准,用于表示英文字符。每个字符用7位二进制表示,共可表示 128 个字符。
ASCII 不仅包括可以打印字符还包括控制字符,用于文本处理和硬件控。
示例:
\n(换行):用于文本换行。 \t(水平制表符):用于文本对齐。 \b(退格):用于删除之前的字符。 DEL(删除):删除字符。
ASCII 字符表(0 ~ 127)分为以下几类:
范围 | 类型 | 示例 |
---|---|---|
0 ~ 31 | 控制字符(不可打印) | \n、\t、\r 等 |
32 | 空格 | ' ' |
33 ~ 47 | 标点符号 | !, @, #, ? |
48 ~ 57 | 数字 | '0' ~ '9' |
58 ~ 64 | 标点符号 | :, ;, = |
65 ~ 90 | 大写字母 | 'A' ~ 'Z' |
91 ~ 96 | 标点符号 | [, \, ], ^ |
97 ~ 122 | 小写字母 | 'a' ~ 'z' |
123 ~ 126 | 标点符号 | {, }, ~ |
127 | 删除字符(DEL) |
完整 ASCII 表:
完整的 ASCII 码表 包括 控制字符(0-31)、可打印字符(32-126) 和 删除字符(127)。以下是完整的 ASCII 码表,包括 十进制、十六进制、字符 和 描述。
十进制 | 十六进制 | 字符 | 描述 |
---|---|---|---|
0 | 0x00 | NUL | 空字符 |
1 | 0x01 | SOH | 标题开始 |
2 | 0x02 | STX | 正文开始 |
3 | 0x03 | ETX | 正文结束 |
4 | 0x04 | EOT | 传输结束 |
5 | 0x05 | ENQ | 询问 |
6 | 0x06 | ACK | 确认应答 |
7 | 0x07 | BEL | 响铃(警报) |
8 | 0x08 | BS | 退格 |
9 | 0x09 | HT | 水平制表符 |
10 | 0x0A | LF | 换行 |
11 | 0x0B | VT | 垂直制表符 |
12 | 0x0C | FF | 换页 |
13 | 0x0D | CR | 回车 |
14 | 0x0E | SO | 不用切换 |
15 | 0x0F | SI | 启用切换 |
16 | 0x10 | DLE | 数据链路转义 |
17 | 0x11 | DC1 | 设备控制1 |
18 | 0x12 | DC2 | 设备控制2 |
19 | 0x13 | DC3 | 设备控制3 |
20 | 0x14 | DC4 | 设备控制4 |
21 | 0x15 | NAK | 拒绝应答 |
22 | 0x16 | SYN | 同步空闲 |
23 | 0x17 | ETB | 传输块结束 |
24 | 0x18 | CAN | 取消 |
25 | 0x19 | EM | 结束媒介 |
26 | 0x1A | SUB | 替换 |
27 | 0x1B | ESC | 转义 |
28 | 0x1C | FS | 文件分隔符 |
29 | 0x1D | GS | 组分隔符 |
30 | 0x1E | RS | 记录分隔符 |
31 | 0x1F | US | 单元分隔符 |
十进制 | 十六进制 | 字符 | 描述 |
---|---|---|---|
32 | 0x20 | (空格) | 空格 |
33 | 0x21 | ! | 感叹号 |
34 | 0x22 | " | 双引号 |
35 | 0x23 | # | 井号 |
36 | 0x24 | $ | 美元符号 |
37 | 0x25 | % | 百分号 |
38 | 0x26 | & | 和号 |
39 | 0x27 | ' | 单引号 |
40 | 0x28 | ( | 左括号 |
41 | 0x29 | ) | 右括号 |
42 | 0x2A | * | 星号 |
43 | 0x2B | + | 加号 |
44 | 0x2C | , | 逗号 |
45 | 0x2D | - | 减号 |
46 | 0x2E | . | 句号 |
47 | 0x2F | / | 斜杠 |
48 | 0x30 | 0 | 数字 0 |
49 | 0x31 | 1 | 数字 1 |
50 | 0x32 | 2 | 数字 2 |
51 | 0x33 | 3 | 数字 3 |
52 | 0x34 | 4 | 数字 4 |
53 | 0x35 | 5 | 数字 5 |
54 | 0x36 | 6 | 数字 6 |
55 | 0x37 | 7 | 数字 7 |
56 | 0x38 | 8 | 数字 8 |
57 | 0x39 | 9 | 数字 9 |
58 | 0x3A | : | 冒号 |
59 | 0x3B | ; | 分号 |
60 | 0x3C | < | 小于号 |
61 | 0x3D | = | 等于号 |
62 | 0x3E | > | 大于号 |
63 | 0x3F | ? | 问号 |
64 | 0x40 | @ | at 符号 |
65 | 0x41 | A | 大写字母 A |
66 | 0x42 | B | 大写字母 B |
67 | 0x43 | C | 大写字母 C |
68 | 0x44 | D | 大写字母 D |
69 | 0x45 | E | 大写字母 E |
70 | 0x46 | F | 大写字母 F |
71 | 0x47 | G | 大写字母 G |
72 | 0x48 | H | 大写字母 H |
73 | 0x49 | I | 大写字母 I |
74 | 0x4A | J | 大写字母 J |
75 | 0x4B | K | 大写字母 K |
76 | 0x4C | L | 大写字母 L |
77 | 0x4D | M | 大写字母 M |
78 | 0x4E | N | 大写字母 N |
79 | 0x4F | O | 大写字母 O |
80 | 0x50 | P | 大写字母 P |
81 | 0x51 | Q | 大写字母 Q |
82 | 0x52 | R | 大写字母 R |
83 | 0x53 | S | 大写字母 S |
84 | 0x54 | T | 大写字母 T |
85 | 0x55 | U | 大写字母 U |
86 | 0x56 | V | 大写字母 V |
87 | 0x57 | W | 大写字母 W |
88 | 0x58 | X | 大写字母 X |
89 | 0x59 | Y | 大写字母 Y |
90 | 0x5A | Z | 大写字母 Z |
91 | 0x5B | [ | 左方括号 |
92 | 0x5C | \ | 反斜杠 |
93 | 0x5D | ] | 右方括号 |
94 | 0x5E | ^ | 脱字符 |
95 | 0x5F | _ | 下划线 |
96 | 0x60 | ` | 反引号 |
97 | 0x61 | a | 小写字母 a |
98 | 0x62 | b | 小写字母 b |
99 | 0x63 | c | 小写字母 c |
100 | 0x64 | d | 小写字母 d |
101 | 0x65 | e | 小写字母 e |
102 | 0x66 | f | 小写字母 f |
103 | 0x67 | g | 小写字母 g |
104 | 0x68 | h | 小写字母 h |
105 | 0x69 | i | 小写字母 i |
106 | 0x6A | j | 小写字母 j |
107 | 0x6B | k | 小写字母 k |
108 | 0x6C | l | 小写字母 l |
109 | 0x6D | m | 小写字母 m |
110 | 0x6E | n | 小写字母 n |
111 | 0x6F | o | 小写字母 o |
112 | 0x70 | p | 小写字母 p |
113 | 0x71 | q | 小写字母 q |
114 | 0x72 | r | 小写字母 r |
115 | 0x73 | s | 小写字母 s |
116 | 0x74 | t | 小写字母 t |
117 | 0x75 | u | 小写字母 u |
118 | 0x76 | v | 小写字母 v |
119 | 0x77 | w | 小写字母 w |
120 | 0x78 | x | 小写字母 x |
121 | 0x79 | y | 小写字母 y |
122 | 0x7A | z | 小写字母 z |
123 | 0x7B | { | 左花括号 |
124 | 0x7C | ||
125 | 0x7D | } | 右花括号 |
126 | 0x7E | ~ | 波浪号 |
十进制 | 十六进制 | 字符 | 描述 |
---|---|---|---|
127 | 0x7F | DEL | 删除字符 |
ASCII 码分为 控制字符(0-31) 和 可打印字符(32-126)。 控制字符用于文本控制(如换行、退格等),可打印字符包括字母、数字和各种符号。 ASCII 的设计简洁且易于理解,是现代字符编码的基础。
头文件:<ctype.h>
字符函数用于单个字符的处理,通常定义在头文件 <ctype.h>
中。这些函数的返回值通常为 真(非0) 或 假(0)
函数 | 功能 | 示例 |
---|---|---|
isalpha(c) | 判断字符是否为字母 | isalpha('A') → 1 |
isdigit(c) | 判断字符是否为数字 | isdigit('5') → 1 |
isalnum(c) | 判断字符是否为字母或数字 | isalnum('A') → 1 |
islower(c) | 判断字符是否为小写字母 | islower('a') → 1 |
isupper(c) | 判断字符是否为大写字母 | isupper('A') → 1 |
isspace(c) | 判断字符是否为空白字符 | isspace(' ') → 1 |
ispunct(c) | 判断字符是否为标点符号 | ispunct('.') → 1 |
isxdigit(c) | 判断字符是否为十六进制数字 | isxdigit('F') → 1 |
iscntrl(c) | 判断字符是否为控制字符 | iscntrl('\n') → 1 |
isgraph(c) | 判断字符是否为可打印字符(非空格) | isgraph('A') → 1 |
isprint(c) | 判断字符是否为可打印字符 | isprint(' ') → 1 |
tolower(c) | 将字符转换为小写字母 | tolower('A') → 'a' |
toupper(c) | 将字符转换为大写字母 | toupper('a') → 'A' |
下面我们对常用的字符函数详细讲解!
isalpha
函数原型:
int isalpha ( int c );
参数:
c为需要判断的字符,其可以是一个整型值,代表一个字符的 ASCII 码。
功能:
判断一个字符是否为字母(包括大写和小写)
返回值:
如果c是字母,则返回一个非零值(通常是一个特定的非零整数),否则返回 0
示例:
int main() {
char ch = 'A';
if (isalpha(ch)) {
printf("%c is a letter.\n", ch);
}
else {
printf("%c is not a letter.\n", ch);
}
return 0;
}
输出:A是字母
A is a letter.
isdigit
函数原型:
int isdigit ( int c );
参数:
同isalpha函数,c为待判断字符的 ASCII 码表示。
功能:
判断一个字符是否为数字
返回值:
若c是数字字符(0 - 9),返回非零值,否则返回 0。
示例:
int main() {
char ch = '5';
if (isdigit(ch)) {
printf("%c is a digit.\n", ch);
}
else {
printf("%c is not a digit.\n", ch);
}
return 0;
}
输出:5是数字
5 is a digit.
islower
函数原型:
int islower ( int c );
参数:
c为要检测的字符。
功能:
判断一个字符是否为小写字母。
返回值:
当c
是小写字母(a
- z
)时返回非零值,不是则返回 0
示例:
int main() {
char ch = 'b';
if (islower(ch)) {
printf("%c is a lower case letter.\n", ch);
}
else {
printf("%c is not a lower case letter.\n", ch);
}
return 0;
}
输出:b是小写字母
b is a lower case letter.
isupper
函数原型:
int islower ( int c );
参数:
c为要检测的字符。
功能:
与islower
相反,判断字符是否为大写字母。
返回值:
若c
是大写字母(A
- Z
)返回非零值,否则返回 0。
示例:
int main() {
char ch = 'F';
if (isupper(ch)) {
printf("%c is an upper case letter.\n", ch);
}
else {
printf("%c is not an upper case letter.\n", ch);
}
return 0;
}
输出:F是大写字母
F is an upper case letter.
tolower
函数原型:
int tolower ( int c );
参数:
c
为要转换的字符,如果c
本身不是大写字母,则返回原字符。
功能:
将大写字母转换为小写字母
返回值:
转换后的小写字母字符(以 ASCII 码形式返回)
示例:
int main() {
char ch = 'G';
char lowerCh = tolower(ch);
printf("The lower case of %c is %c.\n", ch, lowerCh);
return 0;
}
输出:
The lower case of G is g.
toupper
函数原型:
int toupper ( int c );
参数:
c
为待转换字符,若不是小写字母则返回原字符。
功能:
把小写字母转换为大写字母。
返回值:
转换后的大写字母的 ASCII 码值。
示例:
int main() {
char ch = 'h';
char upperCh = toupper(ch);
printf("The upper case of %c is %c.\n", ch, upperCh);
return 0;
}
输出:
The upper case of h is H.
头文件:<string.h>
函数 | 功能 | 示例 |
---|---|---|
strcmp(str1, str2) | 比较字符串是否相等 | strcmp("abc", "abc") → 0 |
strncmp(str1, str2, n) | 比较字符串的前 n 个字符是否相等 | strncmp("abc", "abd", 2) |
函数原型:
int strcmp ( const char * str1, const char * str2 );
参数:
s1
和s2
是要比较的两个字符串。比较是基于字符的 ASCII 码值逐个字符进行的,从两个字符串的第一个字符开始,直到遇到不同的字符或者到达字符串末尾(以'\0'
为准)
功能:
比较两个字符串的大小。
返回值:
如果s1
小于s2
,返回一个负整数;如果s1
等于s2
,返回 0;如果s1
大于s2
,返回一个正整数。
示例:
int main() {
char s1[] = "apple";
char s2[] = "banana";
int result = strcmp(s1, s2);
if (result < 0) {
printf("%s is less than %s.\n", s1, s2);
}
else if (result == 0) {
printf("%s is equal to %s.\n", s1, s2);
}
else {
printf("%s is greater than %s.\n", s1, s2);
}
return 0;
}
输出:
apple is less than banana.
模拟实现:
int my_strcmp(const char* str1, const char* str2)
{
int ret = 0;
assert(str1 != NULL);
assert(str2 != NULL);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
函数原型:
int strncmp ( const char * str1, const char * str2, size_t num );
参数:
s1
和s2
是要比较的字符串,num
是要比较的字符个数。比较过程与strcmp
类似,但最多比较num
个字符。
功能:
类似于strcmp
,但只比较指定前num的字符。
返回值:
如果s1
小于s2
,返回一个负整数;如果s1
等于s2
,返回 0;如果s1
大于s2
,返回一个正整数。
示例:
int main() {
char s1[] = "apple";
char s2[] = "applet";
int result = strncmp(s1, s2, 5);
if (result < 0) {
printf("%s is less than %s in the first 5 characters.\n", s1, s2);
}
else if (result == 0) {
printf("%s is equal to %s in the first 5 characters.\n", s1, s2);
}
else {
printf("%s is greater than %s in the first 5 characters.\n", s1, s2);
}
return 0;
}
输出:
apple is equal to applet in the first 5 characters.
函数 | 功能 | 示例 |
---|---|---|
strcpy(dest, src) | 将字符串 src 复制到 dest | strcpy(dest, "hello"); |
strncpy(dest, src, n) | 复制字符串的前 n 个字符到 dest | strncpy(dest, src, 3); |
strcat(dest, src) | 将字符串 src 连接到 dest 末尾 | strcat(dest, src); |
strncat(dest, src, n) | 连接字符串的前 n 个字符到 dest | strncat(dest, src, 3); |
strcpy
函数原型:
char * strcpy ( char * destination, const char * source );
参数:
destination
是目标字符串数组,用于存储复制后的字符串;source
是源字符串,其内容将被复制到destination
中。源字符串必须以'\0'
结尾,且destination
要有足够的空间来容纳源字符串。
功能:
将一个字符串复制到另一个字符串中。
返回值:
返回指向目标字符串destination
的指针
示例:
int main() {
char source[] = "Hello, World!";
char destination[20];
strcpy(destination, source);
printf("Copied string: %s\n", destination);
return 0;
}
输出:
Copied string: Hello, World!
模拟实现 :
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while ((*dest++ = *src++))
{
;
}
return ret;
}
strncpy
函数原型:
char * strncpy ( char * destination, const char * source, size_t num );
参数:
destination
和source
与strcpy
类似,n
是要从源字符串复制到目标字符串的最大字符数。如果源字符串的长度小于n
,则目标字符串会在复制完源字符串后用'\0'
填充剩余空间;如果源字符串长度大于等于n
,则目标字符串不会自动添加'\0'
结尾
功能:
类似于strcpy
,但可以指定复制的字符个数。
返回值:
返回指向目标字符串destination
的指针
示例:
int main() {
char source[] = "Hello, World!";
char destination[10];
strncpy(destination, source, 5);
destination[5] = '\0'; // 确保目标字符串以'\0'结尾
printf("Copied string: %s\n", destination);
return 0;
}
输出:这里strncpy
函数只复制了源字符串的前 5 个字符到目标字符串,并手动添加'\0'
结尾后输出。
Copied string: Hello
strcat
函数原型:
char * strcat ( char * destination, const char * source );
参数:
destination
是目标字符串,source
是要连接到destination
末尾的源字符串。destination
必须有足够的空间来容纳连接后的字符串,且destination
原本应该是以'\0'
结尾的字符串。
功能:
将一个字符串连接到另一个字符串的末尾。
返回值:
返回指向目标字符串destination
的指针
示例:
int main() {
char destination[20] = "Hello, ";
char source[] = "World!";
strcat(destination, source);
printf("Concatenated string: %s\n", destination);
return 0;
}
输出:
Concatenated string: Hello, World!
模拟实现:
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
strncat
函数原型:
char * strncat ( char * destination, const char * source, size_t num );
参数:
destination
和source
同strcat
,n
是要从源字符串连接到目标字符串的最大字符数。连接后会自动在目标字符串末尾添加'\0'
。
功能:
将一个字符串连接到另一个字符串的末尾。
返回值:
返回指向目标字符串destination
的指针
示例:
int main() {
char destination[20] = "Hello, ";
char source[] = "World!";
strcat(destination, source);
printf("Concatenated string: %s\n", destination);
return 0;
}
输出:
Concatenated string: Hello, World!
函数 | 功能 | 示例 |
---|---|---|
strlen(str) | 返回字符串的长度 | strlen("hello") → 5 |
strchr(str, ch) | 查找字符串中第一个 ch 出现的位置 | strchr("hello", 'e') |
strrchr(str, ch) | 查找字符串中最后一个 ch 出现的位置 | strrchr("hello", 'l') |
strstr(haystack, needle) | 查找子字符串 needle | strstr("hello", "ll") |
strlen
函数原型:
size_t strlen ( const char * str );
参数:
str
是要计算长度的常量字符串(const char*)
功能:
计算字符串的长度(不包括字符串末尾的'\0'
字符)。
返回值:
返回字符串s
的长度,类型为无符号整数size_t
示例:
int main() {
char s[] = "Hello, World!";
size_t length = strlen(s);
printf("The length of the string is %zu.\n", length);
return 0;
}
输出:
The length of the string is 13.
模拟实现1: 计数器方式
int my_strlen(const char* str)
{
int count = 0;
assert(str);
while (*str)
{
count++;
str++;
}
return count;
}
模拟实现2: 不能创建临时变量计数器
int my_strlen(const char* str)
{
assert(str);
if (*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
模拟实现3: 指针-指针的方式
int my_strlen(char* str)
{
assert(str);
char* p = str;
while (*p != '\0')
p++;
return p - str;
}
strchr
函数原型:
const char * strchr ( const char * str, int character );
char * strchr (char * str, int character );
参数:
str
:这是一个指向字符(char *
)的指针,代表要进行查找操作的源字符串。
character
:它是一个整数(int
),代表要查找的字符。不过,在实际使用中,通常会传递一个字符常量,这个字符常量会自动转换为对应的 ASCII 码值
功能:
strchr
函数用于在字符串str
中查找字符character
第一次出现的位置。
返回值:
如果在字符串s中找到了字符c,strchr函数会返回一个指向字符c在字符串s中第一次出现位置的指针。如果在字符串s中没有找到字符c,函数会返回NULL。
示例:
int main() {
char str[] = "Hello, World!";
char* result = strchr(str, 'l');
if (result != NULL) {
printf("find 'l',position is:%ld\n", result - str);
}
else {
printf("not find 'l'\n");
}
return 0;
}
输出:
find 'l',position is:2
strrchr
函数原型:
const char * strrchr ( const char * str, int character );
char * strrchr ( char * str, int character );
参数:
str:这是一个指向字符( char *)的指针,表示要在其中查找字符的源字符串。
character:它是一个整数(int),代表要查找的字符。在实际使用中,通常会传入一个字符常量,这个字符常量会自动转换为它对应的 ASCII 码值。
功能:
strrchr
函数用于在字符串str
中查找字符character
最后一次出现的位置
返回值:
如果在字符串s中找到了字符c,strrchr函数会返回一个指向字符c在字符串s中最后一次出现位置的指针(类型为char *)。如果在字符串s中没有找到字符c,函数会返回NULL。
示例:
int main() {
char str[] = "Hello, World!";
char* result = strrchr(str, 'o');
if (result != NULL) {
printf("find 'o',the position is :%ld\n", result - str);
}
else {
printf("not find 'o'\n");
}
return 0;
}
输出:
find 'o',the position is :8
strstr
函数原型:
const char * strstr ( const char * str1, const char * str2 );
char * strstr (char * str1, const char * str2 );
参数:
str1:这是一个字符( char *)的指针,表示被查找的主字符串。 str2:同样是一个指向字符(char *)的指针,代表要在str1中查找的子字符串
功能:
strstr
函数用于在字符串str1中查找第一次出现字符串str2的位置
返回值:
如果在str1中找到了str2,函数会返回一个指向str2在str1中首次出现位置的指针(类型为char *)如果在str1中没有找到str2,函数返回NULL。这表示查找失败,没有在主字符串中发现要找的子字符串。
示例:
int main() {
char str1[] = "I love programming in C.";
char str2[] = "programming";
char* result = strstr(str1, str2);
if (result != NULL) {
printf("find str2,the position is :%ld\n", result - str1);
}
else {
printf("not find str2\n");
}
return 0;
}
输出:
find str2,the position is :7
模拟实现:
char* strstr(const char* str1, const char* str2)
{
char* cp = (char*)str1;
char* s1, * s2;
if (!*str2)
return((char*)str1);
while (*cp)
{
s1 = cp;
s2 = (char*)str2;
while (*s1 && *s2 && !(*s1 - *s2))
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
strtok
函数原型:
char * strtok ( char * str, const char * delimiters );
参数:
str:这是一个指向字符(char *)的指针,代表要切割的字符串。在第一次调用strtok函数时,传入待切割字符串。在后续调用时,传入NULL。 delimiters:分隔符集合(例如 ',' ' 、' ':' 等)。
功能:
strtok
函数用于将字符串str
分解为一组标记(tokens)。标记是由分隔符(delim
)分隔的子字符串
返回值:
当成功找到一个标记时,strtok函数返回一个指向该标记的指针(类型为char *)。这个指针指向的是原始字符串str内部的位置,用于提取标记。当没有更多的标记可以获取时(已经到达字符串末尾或者没有符合条件的标记),函数返回NULL。
注意:
strtok 会修改原字符串,将分隔符替换为 \0。 不能直接对 字符串字面量 使用 strtok,必须是可修改的字符串。 使用静态指针保存字符串的状态,因此不能在多线程环境或递归中使用。
单分隔符示例:
int main() {
char str[] = "Hello,World,This,is,C";
const char delim[] = ","; // 分隔符
char* token;
// 第一次调用,传入待分割的字符串
token = strtok(str, delim);
while (token != NULL) {
printf("tokens: %s\n", token);
token = strtok(NULL, delim); // 继续分割剩余字符串
}
return 0;
}
输出:
tokens: Hello
tokens: World
tokens: This
tokens: is
tokens: C
多分隔符示例:
int main() {
char str[] = "Hello;World,This:is-C";
const char delim[] = ";,:-"; // 多个分隔符
char* token;
token = strtok(str, delim);
while (token != NULL) {
printf("tokens: %s\n", token);
token = strtok(NULL, delim);
}
return 0;
}
输出:
tokens: Hello
tokens: World
tokens: This
tokens: is
tokens: C
函数原型:
char * strerror ( int errnum );
参数:
errnum:错误代码(整数类型),一般是 errno 的值。
功能:
strerror
是C语言中用于将错误代码转换为错误描述字符串的函数。它将错误代码映射到对应的 错误消息,方便程序员进行调试。
返回值:
strerror函数返回一个指向错误信息字符串的指针(类型为char *),包含了对错误码errnum所代表错误的描述。如果错误代码无效,strerror
返回类似 "Unknown error"
errno 与 strerror 的关系:
errno 是 C 标准库中的一个全局变量,用于保存最近发生的错误代码。 当调用系统函数失败时,errno 会被设置为特定的错误代码。 strerror 可以将 errno 的值转化为对应的错误描述。
示例:(尝试以只读方式打开不存在文件)
int main() {
// 尝试打开一个不存在的文件
FILE* fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
// 打印错误代码和错误描述
printf("错误代码: %d\n", errno);
printf("错误信息: %s\n", strerror(errno));
}
return 0;
}
输出:
错误代码: 2
错误信息: No such file or directory
常见错误代码与描述
错误代码 | 错误消息 | 描述 |
---|---|---|
0 | Success | 没有错误 |
1 | Operation not permitted | 操作不被允许 |
2 | No such file or directory | 文件或目录不存在 |
3 | No such process | 进程不存在 |
4 | Interrupted system call | 系统调用被中断 |
5 | Input/output error | 输入/输出错误 |
12 | Out of memory | 内存不足 |
13 | Permission denied | 权限被拒绝 |
17 | File exists | 文件已存在 |
22 | Invalid argument | 无效参数 |
28 | No space left on device | 设备上没有剩余空间 |
36 | File name too long | 文件名过长 |
113 | No route to host | 没有到主机的路由 |
注意:错误代码和消息可能因操作系统而异。
遍历所有错误码:
int main() {
// 遍历 0-133 范围内的错误代码
for (int i = 0; i < 134; i++) {
printf("错误码 %d: %s\n", i, strerror(i));
}
return 0;
}
输出:
错误码 0: No error
错误码 1: Operation not permitted
错误码 2: No such file or directory
错误码 3: No such process
错误码 4: Interrupted function call
错误码 5: Input/output error
错误码 6: No such device or address
错误码 7: Arg list too long
错误码 8: Exec format error
错误码 9: Bad file descriptor
错误码 10: No child processes
错误码 11: Resource temporarily unavailable
错误码 12: Not enough space
错误码 13: Permission denied
错误码 14: Bad address
错误码 15: Unknown error
错误码 16: Resource device
错误码 17: File exists
错误码 18: Improper link
错误码 19: No such device
错误码 20: Not a directory
错误码 21: Is a directory
错误码 22: Invalid argument
错误码 23: Too many open files in system
错误码 24: Too many open files
错误码 25: Inappropriate I/O control operation
错误码 26: Unknown error
错误码 27: File too large
错误码 28: No space left on device
错误码 29: Invalid seek
错误码 30: Read-only file system
错误码 31: Too many links
错误码 32: Broken pipe
错误码 33: Domain error
错误码 34: Result too large
错误码 35: Unknown error
错误码 36: Resource deadlock avoided
错误码 37: Unknown error
错误码 38: Filename too long
错误码 39: No locks available
错误码 40: Function not implemented
错误码 41: Directory not empty
错误码 42: Illegal byte sequence
错误码 43: Unknown error
错误码 44: Unknown error
错误码 45: Unknown error
错误码 46: Unknown error
错误码 47: Unknown error
错误码 48: Unknown error
错误码 49: Unknown error
错误码 50: Unknown error
错误码 51: Unknown error
错误码 52: Unknown error
错误码 53: Unknown error
错误码 54: Unknown error
错误码 55: Unknown error
错误码 56: Unknown error
错误码 57: Unknown error
错误码 58: Unknown error
错误码 59: Unknown error
错误码 60: Unknown error
错误码 61: Unknown error
错误码 62: Unknown error
错误码 63: Unknown error
错误码 64: Unknown error
错误码 65: Unknown error
错误码 66: Unknown error
错误码 67: Unknown error
错误码 68: Unknown error
错误码 69: Unknown error
错误码 70: Unknown error
错误码 71: Unknown error
错误码 72: Unknown error
错误码 73: Unknown error
错误码 74: Unknown error
错误码 75: Unknown error
错误码 76: Unknown error
错误码 77: Unknown error
错误码 78: Unknown error
错误码 79: Unknown error
错误码 80: Unknown error
错误码 81: Unknown error
错误码 82: Unknown error
错误码 83: Unknown error
错误码 84: Unknown error
错误码 85: Unknown error
错误码 86: Unknown error
错误码 87: Unknown error
错误码 88: Unknown error
错误码 89: Unknown error
错误码 90: Unknown error
错误码 91: Unknown error
错误码 92: Unknown error
错误码 93: Unknown error
错误码 94: Unknown error
错误码 95: Unknown error
错误码 96: Unknown error
错误码 97: Unknown error
错误码 98: Unknown error
错误码 99: Unknown error
错误码 100: address in use
错误码 101: address not available
错误码 102: address family not supported
错误码 103: connection already in progress
错误码 104: bad message
错误码 105: operation canceled
错误码 106: connection aborted
错误码 107: connection refused
错误码 108: connection reset
错误码 109: destination address required
错误码 110: host unreachable
错误码 111: identifier removed
错误码 112: operation in progress
错误码 113: already connected
错误码 114: too many symbolic link levels
错误码 115: message size
错误码 116: network down
错误码 117: network reset
错误码 118: network unreachable
错误码 119: no buffer space
错误码 120: no message available
错误码 121: no link
错误码 122: no message
错误码 123: no protocol option
错误码 124: no stream resources
错误码 125: not a stream
错误码 126: not connected
错误码 127: state not recoverable
错误码 128: not a socket
错误码 129: not supported
错误码 130: operation not supported
错误码 131: Unknown error
错误码 132: value too large
错误码 133: owner dead
函数原型:
void perror ( const char * str );
参数:
str
:错误消息的前缀字符串。如果 s
为 NULL
或空字符串,则只输出错误描述。
功能:
用于输出错误信息的函数,通常配合系统调用或者标准库函数来显示错误原因。它会根据 errno
变量的值输出对应的错误描述字符串。
输出格式为:s: 错误描述。 错误描述由 strerror(errno) 提供。
返回值:
无返回值
perror 与 errno 的关系:
errno 是一个全局变量,保存了最近发生的错误代码。 当系统调用或标准库函数失败时,errno 会被设置为对应的错误代码。 perror 会将 errno 的值转换为对应的错误描述,并输出到标准错误输出流 stderr。
示例:
int main() {
FILE* file = fopen("nonexistent.txt", "r");
if (file == NULL) {
perror("文件打开失败"); // 输出错误信息
}
return 0;
}
输出:perror 输出了前缀字符串 "文件打开失败",后面的错误描述 "No such file or directory" 来自 strerror(errno)
文件打开失败: No such file or directory
多个错误示例:
int main() {
// 第一次错误:打开不存在的文件
FILE* file = fopen("nonexistent.txt", "r");
if (file == NULL) {
perror("第一次错误");
}// 第二次错误:写入只读文件
file = fopen("/etc/passwd", "r"); // 只读文件
if (file != NULL) {
if (fputc('A', file) == EOF) {
perror("第二次错误");
}
fclose(file);
}
return 0;
}
输出:
第一次错误: No such file or directory
第二次错误: Bad file descriptor
perror
输出的格式如下:
<自定义前缀字符串>: <错误描述字符串>
前缀字符串:由用户指定的字符串。
错误描述字符串:通过 strerror(errno)
获取。
perror与 strerror
的区别
函数 | 功能 | 输出位置 | 用法 |
---|---|---|---|
perror | 输出错误信息,格式:前缀: 错误描述 | 标准错误流 | perror("错误前缀"); |
strerror | 返回错误描述字符串 | 返回字符串 | printf("%s", strerror(errno)); |
int main() {
FILE* file = fopen("nonexistent.txt", "r");
if (file == NULL) {
// 使用 perror
perror("perror 输出");
// 使用 strerror
printf("strerror 输出: %s\n", strerror(errno));
}
return 0;
}
输出:
perror 输出: No such file or directory
strerror 输出: No such file or directory
注意:
errno 必须是有效的:只有在系统调用或标准库函数失败后,errno 才会被设置为错误代码。
输出到标准错误流 stderr:perror 输出的错误信息会被发送到标准错误流,不会影响标准输出 stdout。
errno 的保留:在调用多个函数后,errno 可能会被覆盖。如果需要保存 errno 的值,可以先将它存储到一个临时变量中。
C 语言的字符与字符串处理知识丰富且关键。ASCII 码奠定基础,控制字符管底层,可打印字符展文本。字符函数中,判断函数识类别,转换函数改形态。字符串函数功能全,比较、拷贝、连接、长度查找与切割各有其用,还有错误处理函数来保障,共同撑起 C 语言字符与字符串处理的 “大厦”,有效应对各类文本任务,通过本文学习,掌握面对字符串处理问题的制胜法宝,为后续应对更复杂的C编程任务打下坚实的基础!
如上的讲解只是我的一些拙见,如有不足之处,还望各位大佬不吝在评论区予以斧正,感激不尽!创作不易,还请多多互三支持!你们的支持是我最大的动力!