目录
- 一)字符函数
- 二)字符串函数
-
-
- [字符串长度 - strlen](#字符串长度 - strlen)
- [字符串复制 - strcpy / strncpy](#字符串复制 - strcpy / strncpy)
- [字符串连接 - strcat](#字符串连接 - strcat)
- [字符串比较 - strcmp / strncmp](#字符串比较 - strcmp / strncmp)
- [字符串查找 - strstr](#字符串查找 - strstr)
- 字符串分隔strtok
- [错误码 - strerror](#错误码 - strerror)
-
- FILE结构体
-
- [1. fopen()](#1. fopen())
- [2. fclose()](#2. fclose())
- [3. fread()](#3. fread())
- [4. fwrite()](#4. fwrite())
- [5. fgetc()](#5. fgetc())
- [6. fputc()](#6. fputc())
- [7. fgets()](#7. fgets())
- [8. fputs()](#8. fputs())
- [9. fflush()](#9. fflush())
- [10. fseek()](#10. fseek())
- [11. ftell()](#11. ftell())
- [12. rewind()](#12. rewind())
- [13. feof()](#13. feof())
- [14. ferror()](#14. ferror())
- [15. perror()](#15. perror())
- 额外:perror
-
- 总结
- 如果你觉得这篇文章对你有帮助,请给文章一个三连吧
一)字符函数
字符函数大部分都定义在
<ctype.h>
头文件中
在C语言中,字符是以其对应的ASCII码(整数)存储的。例如,字符A
的ASCII码是65,a
是97,0
是48。字符函数本质上就是对传入的整数值(字符)进行判断或运算
字符分类函数
这些函数用于检查一个字符是否属于特定的类型。它们接收一个
int
类型的参数(字符的ASCII码),返回一个int
类型的值:非零(真)或 零(假)
函数名 | 功能描述 | 包含范围 | 示例 |
---|---|---|---|
iscntrl |
检查字符是否为控制字符 | ASCII码 0~31 和 127 (DEL) | iscntrl('\n') → 真 iscntrl('a') → 假 |
isspace |
检查字符是否为空白字符 | 空格' ' 、换页\f 、换行\n 、回车\r 、水平制表符\t 、垂直制表符\v |
isspace(' ') → 真 isspace('A') → 假 |
isdigit |
检查字符是否为十进制数字 | '0' ~ '9' |
isdigit('5') → 真 isdigit('a') → 假 |
isxdigit |
检查字符是否为十六进制数字 | '0' `'9'`、`'a'`'f' 、'A' ~'F' |
isxdigit('a') → 真 isxdigit('G') → 假 |
islower |
检查字符是否为小写字母 | 'a' ~ 'z' |
islower('g') → 真 islower('G') → 假 |
isupper |
检查字符是否为大写字母 | 'A' ~ 'Z' |
isupper('X') → 真 isupper('x') → 假 |
isalpha |
检查字符是否为字母 | 'a' ~'z' 和 'A' ~'Z' |
isalpha('K') → 真 isalpha('2') → 假 |
isalnum |
检查字符是否为字母或数字 | 'a' `'z'`、`'A'`'Z' 、'0' ~'9' |
isalnum('B') → 真 isalnum('!') → 假 |
ispunct |
检查字符是否为标点符号 | 任何不属于字母数字的可打印图形字符 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ \ { | } ~` |
ispunct('!') → 真 ispunct(' ') → 假 |
isgraph |
检查字符是否为图形字符 | 所有可打印字符(不包括空格) | isgraph('A') → 真 isgraph(' ') → 假 |
isprint |
检查字符是否为可打印字符 | 所有图形字符 + 空格' ' |
isprint('A') → 真 isprint('\n') → 假 |
代码练习
通过从小写字母中减去 32 将字符串转换为大写
转换原理: 在ASCII码中,小写字母比对应的大写字母正好大32
c
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
c = str[i];
if (islower(c))
c -= 32;
putchar(c);
i++;
}
return 0;
}
字符转换函数(to表示转变的意思)
字符大小写转换函数
我们只需要学习前两种大小写转换函数,后面的我们作了解即可
C语言提供了2个字符转换函数:
cint tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写 int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写
示例代码
c
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
c = str[i];
if (islower(c)) {
c = toupper(c);
}
putchar(c);
i++;
}
return 0;
}
c
#include <stdio.h>
#include <ctype.h>
int main() {
char ch1 = 'a', ch2 = 'B', ch3 = '5';
printf("'%c' 转换为大写: '%c'\n", ch1, toupper(ch1));
printf("'%c' 转换为小写: '%c'\n", ch2, tolower(ch2));
printf("'%c' 转换: '%c'\n", ch3, toupper(ch3)); // 数字不变
return 0;
}
字符与数字转换
字符 ↔ 数字
一般情况下我们都会采取==+'0'或者-'0'==来转换
下面我们介绍几种字符转换函数
atoi() - 字符串转整数
c
#include <stdio.h>
#include <stdlib.h>
int main() {
char str1[] = "123";
char str2[] = "45.67";
char str3[] = "abc123";
printf("'%s' -> %d\n", str1, atoi(str1)); // 123
printf("'%s' -> %d\n", str2, atoi(str2)); // 45(遇到非数字停止)
printf("'%s' -> %d\n", str3, atoi(str3)); // 0(开头非数字)
return 0;
}
atof()
-- 字符串转浮点数atol()
-- 字符串转长整数
itoa() - 整数转字符串
c
#include <stdio.h>
#include <stdlib.h>
int main() {
char buffer[20];
// 十进制
itoa(12345, buffer, 10);
printf("十进制: %s\n", buffer); // "12345"
// 二进制
itoa(10, buffer, 2);
printf("二进制: %s\n", buffer); // "1010"
// 十六进制
itoa(255, buffer, 16);
printf("十六进制: %s\n", buffer); // "ff"
return 0;
}
sprintf() - 格式化输出到字符串
c
#include <stdio.h>
int main() {
char buffer[100];
int integer = 123;
float floating = 45.67;
double double_num = 89.123456;
// 整数转字符串
sprintf(buffer, "%d", integer);
printf("整数: %s\n", buffer); // "123"
// 浮点数转字符串
sprintf(buffer, "%.2f", floating);
printf("浮点数: %s\n", buffer); // "45.67"
// 多种数据类型组合
sprintf(buffer, "整数:%d, 浮点数:%.3f", integer, double_num);
printf("组合: %s\n", buffer); // "整数:123, 浮点数:89.123"
// 不同进制转换
sprintf(buffer, "十进制:%d, 十六进制:%x, 八进制:%o", 255, 255, 255);
printf("进制: %s\n", buffer); // "十进制:255, 十六进制:ff, 八进制:377"
return 0;
}
二)字符串函数
使用前记得添加头文件
c
#include <string.h> // 字符串函数
#include <stdio.h> // 输入输出
字符串长度 - strlen
c
char str[] = "hello";
int len = strlen(str); // len = 5
字符串复制 - strcpy / strncpy
- 功能: 将源字符串 src(包括终止空字符 \0)复制到目标缓冲区 dest。
c
#include <string.h>
char *strcpy(char *dest, const char *src);
- 代码示例
c
char src[] = "hello";
char dest[10];
strcpy(dest, src); // dest = "hello"
strncpy
在VS中好像会出现安全性问题,这时候我们可以添加宏定义
c
#define _CRT_SECURE_NO_WARNINGS
- 功能: 最多复制 n 个字符从 src 到 dest
c
#include <string.h>
char *strncpy(char *dest, const char *src, size_t n);
- 代码示例
c
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello World";
char dest[10];
// 安全复制,留一个位置给 \0
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // 手动添加终止符
printf("安全复制: %s\n", dest); // Hello Wor
return 0;
}
字符串连接 - strcat
- 函数原型
cchar * strcat ( char * destination, const char * source );
- 功能: 字符串追加,把
source
指向的源字符串中的所有字符都追加到destination
指向的空间
中。- 参数:
destination
:指针,指向⽬的地空间
source
:指针,指向源头数据- 返回值:
strcat
函数返回的⽬标空间的起始地址
c
char str[20] = "Hello";
strcat(str, " World"); // "Hello World"
strncat(str, "!!!", 2); // "Hello World!!"
字符串比较 - strcmp / strncmp
- 函数原型
c
int strcmp ( const char * str1, const char * str2 );
- 功能: ⽤来⽐较
str1
和str2
指向的字符串,从两个字符串的第⼀个字符开始⽐较,如果两个字符
的ASCII码值相等,就⽐较下⼀个字符。直到遇到不相等的两个字符,或者字符串结束。
参数:
str1
:指针,指向要⽐较的第⼀个字符串
str2
:指针,指向要⽐较的第⼆个字符串- 返回值:
- 标准规定:
◦ 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字
◦ 第⼀个字符串等于第⼆个字符串,则返回0
◦ 第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字
- 代码示例
c
#include <stdio.h>
#include <string.h>
int main() {
char password[] = "secret123";
char input[50];
printf("请输入密码: ");
scanf("%49s", input);
if (strcmp(input, password) == 0) {
printf("密码正确!\n");
} else {
printf("密码错误!\n");
}
// 字符串排序判断
char name1[] = "John";
char name2[] = "Alice";
if (strcmp(name1, name2) < 0) {
printf("'%s' 在 '%s' 之前\n", name1, name2); // 不会执行
} else {
printf("'%s' 在 '%s' 之后\n", name1, name2); // 会执行
}
return 0;
}
strncpy
c
#include <string.h>
int strncmp(const char *str1, const char *str2, size_t n);
-
功能
比较两个字符串的前 n 个字符
-
代码示例
c
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "apple pie";
char str2[] = "apple cake";
// 只比较前5个字符
int result = strncmp(str1, str2, 5);
printf("前5字符比较: %d\n", result); // 0(相同)
// 比较前8个字符
result = strncmp(str1, str2, 8);
printf("前8字符比较: %d\n", result); // 1(不同)
return 0;
}
字符串查找 - strstr
- 函数原型
c
char * strstr ( const char * str1, const char * str2);
strstr 的使⽤得包含<string.h>
- 参数:
str1 :指针,指向了被查找的字符串
str2 :指针,指向了要查找的字符串 - 返回值:
如果str1指向的字符串中存在str2指向的字符串,那么返回第⼀次出现位置的指针
如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL
- 代码示例
c
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
if (pch != NULL)
printf("%s\n", pch);
else
printf("查找的字符串不存在\n");
return 0;
}
字符串分隔strtok
- 函数原型
c
#include <string.h>
char *strtok(char *str, const char *delim);
-
参数说明
str:要分割的字符串(第一次调用时传入,后续传入NULL)
delim:分隔符字符串(包含所有分隔字符)
-
返回值
成功:返回指向下一个token的指针
结束:返回NULL(没有更多token)
strtok 函数会:
记住位置:在第一次调用后,它内部保存了当前处理的位置
继续分割:后续调用时从上次结束的位置继续
- 代码示例
c
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "apple,banana,cherry,date";
char *token;
printf("分割字符串: %s\n", str);
// 第一次调用
token = strtok(str, ",");
// 后续调用
while (token != NULL) {
printf("Token: %s\n", token);
token = strtok(NULL, ","); //告诉函数"继续处理同一个字符串,从上一次的位置开始"
}
return 0;
}

错误码 - strerror
- 函数原型
c
#include <string.h>
char *strerror(int errnum);
-
功能
将错误代码转换为对应的错误描述字符串
-
参数
errnum
:错误代码(通常是errno
变量的值) -
返回值
返回指向错误描述字符串的指针
c
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
// 假设发生了文件不存在的错误
errno = 2; // ENOENT 错误代码
printf("错误说明: %s\n", strerror(errno));
// 输出: No such file or directory
return 0;
}
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在
errno.h
这个头文件中说
明的,C语言程序启动的时候就会使用一个全局的变量errno
来记录程序的当前错误码,只不过程
序启动的时候errno
是 0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,
就会将对应的错误码,存放在errno
中,而一个错误码的数字是整数,很难理解是什么意思,所
以每一个错误码都是有对应的错误信息的。strerror
函数就可以将错误码对应的错误信息字符串的地
址返回。
- 代码示例
我们看看0-10对应的错误码表示什么
c
#include <errno.h>
#include <string.h>
#include <stdio.h>
//我们打印---下0~10这些错误码对应的信息
int main()
{
int i = 0;
for (i = 0; i <= 10; i++) {
printf("%d: %s\n", i, strerror(i));
}
return 0;
}
c
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
FILE结构体
下面我们简单讲解一下
FILE
这个结构体的内容
我们看下面这段代码
c
/*
* 错误处理演示程序
* 展示strerror和errno的使用方法
*/
// 包含标准输入输出头文件,提供FILE类型和fopen、printf等函数
#include <stdio.h>
// 包含字符串处理头文件,提供strerror函数
#include <string.h>
// 包含错误号定义头文件,提供errno变量和错误代码常量
#include <errno.h>
// 包含文件控制头文件,提供文件操作相关函数和常量(在此程序中未实际使用)
#include <fcntl.h>
// 主函数,程序入口点
int main() {
// 声明文件指针变量,用于指向打开的文件
// FILE是一个结构体类型,包含文件操作所需的所有信息
FILE *file;
// 尝试以只读模式("r")打开一个不存在的文件
// fopen函数返回:
// - 成功:指向FILE结构的指针
// - 失败:NULL指针,同时设置errno变量
file = fopen("nonexistent_file.txt", "r");
// 检查文件是否打开成功
// 由于文件不存在,fopen会返回NULL
if (file == NULL) {
// 输出错误代码:errno是一个全局变量,存储最近一次系统调用的错误代码
// 此时errno的值应该是2(ENOENT),表示"No such file or directory"
printf("错误代码: %d\n", errno);
// 使用strerror函数将错误代码转换为可读的错误描述字符串
// strerror(errno)会返回类似于"No such file or directory"的字符串
printf("错误描述: %s\n", strerror(errno));
}
// 注意:如果文件打开成功,这里应该有关闭文件的代码
// else {
// fclose(file);
// }
// 演示循环:展示前5个错误代码对应的描述信息
// 注意:不是所有数字都有对应的错误描述,有些可能是"Unknown error"
for (int i = 0; i < 5; i++) {
// 对每个错误代码i,输出其对应的错误描述
// strerror(i)会查找代码i对应的错误描述字符串
printf("错误代码 %d: %s\n", i, strerror(i));
}
// 程序正常结束,返回0表示成功
return 0;
}

- 程序执行流程详细说明:
- 声明阶段:
FILE *file;
声明一个文件指针,此时它还没有指向任何有效的文件结构。 - 文件打开尝试:
fopen("nonexistent_file.txt", "r")
尝试打开文件,但由于文件不存在而失败。 - 错误处理:
errno
被自动设置为相应的错误代码(通常是2,表示文件不存在)
strerror(errno)
将数字错误代码转换为人类可读的描述 - 错误代码演示:循环显示前5个错误代码的描述,帮助理解错误代码与描述之间的映射关系。

C 标准库中提供了许多函数来操作 FILE 结构体,从文件的打开、读取、写入到关闭文件等。以下是与 FILE 类型相关的常见函数及其功能解释。
1. fopen()
打开一个文件并返回一个文件指针
(FILE*)
c
FILE *fopen(const char *filename, const char *mode);
filename
:文件的路径。mode
:文件打开模式(如 "r", "w", "a", "rb", "wb" 等)。- 返回值:如果成功,返回一个
FILE*
指针;如果失败,返回NULL
。
c
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
}
2. fclose()
关闭一个打开的文件。
c
int fclose(FILE *stream);
-
stream
:指向一个已打开文件的FILE*
。 -
返回值:成功返回
0
,失败返回EOF
。
c
fclose(file);
3. fread()
从文件中读取数据到内存。
c
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
-
ptr
:指向存储读取数据的内存块。 -
size
:每个数据项的字节大小。 -
count`:要读取的数据项数量。
-
stream
:文件指针。 -
返回值:成功读取的项数。如果返回值小于 count,可能是到达文件末尾或发生错误。
c
char buffer[100];
size_t n = fread(buffer, 1, sizeof(buffer), file);
4. fwrite()
向文件中写入数据。
c
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
-
ptr
:指向要写入的数据的内存块。 -
size
:每个数据项的字节大小。 -
count
:要写入的数据项数量。 -
stream
:文件指针。 -
返回值:成功写入的项数。
c
const char *data = "Hello, World!";
fwrite(data, 1, strlen(data), file);
5. fgetc()
从文件中读取一个字符。
c
int fgetc(FILE *stream);
-
stream
:文件指针。 -
返回值:成功时返回一个字符(int 类型,允许返回 EOF)。如果到达文件末尾,返回 EOF。
c
int c = fgetc(file);
if (c == EOF) {
printf("End of file or error.\n");
}
6. fputc()
向文件写入一个字符。
c
int fputc(int c, FILE *stream);
-
c
:要写入的字符。 -
stream
:文件指针。 -
返回值:成功时返回写入的字符,失败时返回 EOF。
c
fputc('A', file);
7. fgets()
从文件中读取一行(包含换行符)。
c
char *fgets(char *str, int n, FILE *stream);
str
:存储读取行的缓冲区。n
:最多读取的字符数(包括 \0 字符)。stream
:文件指针。- 返回值:返回指向缓冲区的指针,或者如果读取失败或到达文件末尾返回 NULL。
c
char line[100];
if (fgets(line, sizeof(line), file)) {
printf("Line: %s", line);
}
8. fputs()
向文件写入一个字符串。
c
int fputs(const char *str, FILE *stream);
-
str
:要写入的字符串。 -
stream
:文件指针。 -
返回值:成功时返回非负值,失败时返回 EOF。
c
fputs("Hello, World!", file);
9. fflush()
刷新文件流缓冲区,即将缓冲区中的数据写入文件。
c
int fflush(FILE *stream);
-
stream
:文件指针。如果为 NULL,则刷新所有输出流。 -
返回值:成功时返回 0,失败时返回 EOF。
c
fflush(file);
10. fseek()
移动文件指针到指定位置。
c
int fseek(FILE *stream, long offset, int whence);
-
stream
:文件指针。 -
offset
:偏移量。 -
whence
:起始位置(SEEK_SET, SEEK_CUR, SEEK_END)。 -
返回值:成功时返回 0,失败时返回 -1。
c
fseek(file, 0, SEEK_END); // 移动到文件末尾
11. ftell()
获取当前文件指针的位置。
c
long ftell(FILE *stream);
-
stream
:文件指针。 -
返回值:返回当前位置的偏移量,失败时返回 -1L。
c
long pos = ftell(file);
12. rewind()
将文件指针移动到文件开头,并清除文件的错误标志。
c
void rewind(FILE *stream);
stream
:文件指针。
c
rewind(file); // 将文件指针移回文件开头
13. feof()
检查是否到达文件末尾。
c
int feof(FILE *stream);
-
stream
:文件指针。 -
返回值:到达文件末尾时返回非零值,否则返回 0。
c
if (feof(file)) {
printf("End of file reached.\n");
}
14. ferror()
检查文件是否发生错误。
c
int ferror(FILE *stream);
-
stream
:文件指针。 -
返回值:如果文件出错,返回非零值,否则返回
0
。
c
if (ferror(file)) {
printf("Error reading from file.\n");
}
15. perror()
打印文件操作相关的错误信息。
c
void perror(const char *str);
str
:一个自定义的前缀字符串(如错误发生的上下文)。
c
perror("File opening error");
额外:perror
-
功能
perror
函数将当前错误代码对应的描述信息输出到标准错误流(stderr
),并可以附加自定义的前缀信息。 -
函数原型
c
#include <stdio.h>
void perror(const char *s);
-
参数
s
:自定义的前缀字符串(可以为NULL
) -
基本用法
c
#include <stdio.h>
#include <errno.h>
int main() {
FILE *file;
// 尝试打开不存在的文件
file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
// 使用 perror 输出错误信息
perror("文件打开失败");
// 输出: 文件打开失败: No such file or directory
}
return 0;
}
总结
字符函数和字符串函数是 C 语言中处理字符和字符串的重要工具,它们用于执行一系列与字符和字符串相关的操作,广泛应用于数据处理、文本处理和文件处理等多个领域。
如果你觉得这篇文章对你有帮助,请给文章一个三连吧
