C语言专题-字符串
字符串
字符串:以 \0
为结束标志的字符序列 null-terminated byte string (NTBS)
C 语言没有专门用于储存字符串的变量类型,字符串都被储存在 char 类型的数组中。
char 数组存储字符串时最末尾的一个字符必须是 null character\0
。
char 数组的容量必须至少比待存储字符串中的字符数多 1。
https://en.cppreference.com/w/c/language/array
字符串的存储类型
- ASCII字符串:
char s[] = "abc";
- UTF8字符串:
char s[] = u8"abc";
- UTF16字符串:
char16_t s[] = u"abc";
- UTF32字符串:
char32_t s[] = U"abc";
- 宽字符串:
wchar_t s[] = L"abc";
https://en.cppreference.com/w/c/locale/setlocale
字符串字面量
字符串字面量可直接给一个字符数组进行初始化
字符串字面量会自动在尾部添加一个 \0
字符,用来表示该字符串的结束符
在C语言标准中,对字符串字面量中的字符进行修改是一个未定义的行为
stringLiteralWrite: Modifying string literal "abc" directly or indirectly is undefined behaviour
字符串的初始化
使用字符指针
char *p1 = "hello, world";
创建字符指针,指向字符串字面量(作为常量,存储在静态存储区)
无论是全局指针变量还是局部指针变量,都指向同一地址
ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
所以建议添加const显式限定:const char *p1 = "hello, world";
使用字符数组
char ca1[] = "hello, world";
创建字符数组,在栈中分配内存并初始化
字符数组初始化之后,不能直接接受字符串赋值,需使用字符串函数 strcpy 等进行操作
https://www.cnblogs.com/littleswan/p/12162958.html
https://www.geeksforgeeks.org/whats-difference-between-char-s-and-char-s-in-c/
字符串的度量
size_t strlen( const char *str );
: 返回字符串str中除 '\0' 结束标志符以外的字符序列的长度
https://en.cppreference.com/w/c/string/byte/strlen
The bit width of size_t is not less than 16. (since C99)
sizeof(object)
: 单目运算符,计算字节长度(不要对任何数据类型的长度做先入为主的假设)
https://en.cppreference.com/w/c/language/sizeof
https://en.cppreference.com/w/c/types/limits
size_t
: 属于无符号整数类型
#include <stddef.h>
ptrdiff_t
对于无符号数减法,必须保证被减数大于减数,
否则就会下界溢出而得到一个比较大的正数
所以在比较时最好使用 if (strlen(str2) > strlen(str1))
sizeof(array)和sizeof(pointer)
字符串的输入
int scanf( const char *restrict format, ... );
int scanf("格式控制字符串", 参数地址表);
%c
字符: 接受空格和换行符%s
字符串: 以空白字符(空格、换行符)为读入结束标志%d
整数: 以空白字符(空格、换行符)为读入结束标志%[^\n]
: 读取一行字符内容
原样输入
int fscanf( FILE *restrict stream, const char *restrict format, ... );
https://en.cppreference.com/w/c/io/fscanf
char *gets( char *str );
: 从 stdin 读入一行文本,丢弃换行符,在末尾添加 \0
,写入 str 中
https://en.cppreference.com/w/c/io/gets
char *gets_s( char *str, rsize_t n );
: 从 stdin 读入一行文本中最多 n-1 个字符,在末尾添加 \0
,写入 str 中
char *fgets( char *restrict str, int count, FILE *restrict stream );
https://en.cppreference.com/w/c/io/fgets
字符串的输出
format specifier placeholder: %[flag][width][.prec][length]type
- flag:
+
,-
,空格
,#
,0
- type:
%c
: unsigned char (大于255的整数会被截断取余)%d
或%i
: signed int%u
: 十进制表示的 unsigned int%o
: 八进制表示的 unsigned int%x
: 十六进制表示的 unsigned int%s
:char *
%.5s
: 字符数组的最多前5个字符
%p
: 指针地址%f
: 浮点数(默认打印小数点后6位有效数字)%n
int printf( const char *restrict format, ... );
http://www.cplusplus.com/reference/cstdio/printf/
- 默认右对齐
- 转义字符: 在编译时处理
- 占位符: 在运行时处理
常见问题:
- 格式说明符与参数的类型不匹配
- 格式说明符与参数的数目不匹配
- 格式化字符串全部或部分由用户输入
- 格式化字符串的长度没有限制
int fprintf( FILE *restrict stream, const char *restrict format, ... );
: 将可变参数 ... 按照 format 格式化为字符串,输出到 stream
https://en.cppreference.com/w/c/io/fprintf
int puts( const char *str );
: 打印字符串 str,并在末尾添加换行符
https://en.cppreference.com/w/c/io/puts
int fputs( const char *restrict str, FILE *restrict stream );
: 把字符串 str 输出到文件流 stream
https://en.cppreference.com/w/c/io/fputs
字符串的连接
char *strcat( char *restrict dest, const char *restrict src );
Appends a copy of the null-terminated byte string pointed to by src to the end of the null-terminated byte string pointed to by dest.
The character src[0] replaces the null terminator at the end of dest. The resulting byte string is null-terminated.
https://en.cppreference.com/w/c/string/byte/strcat
errno_t strcat_s(char *restrict dest, rsize_t destsz, const char *restrict src);
字符串的复制
char *strcpy( char *restrict dest, const char *restrict src );
: 若字符串src长度大于目标缓冲区长度,会发生缓冲区溢出
https://en.cppreference.com/w/c/string/byte/strcpy
errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
char *strncpy( char *restrict dest, const char *restrict src, size_t count );
https://en.cppreference.com/w/c/string/byte/strncpy
errno_t strncpy_s(char *restrict dest, rsize_t destsz, const char *restrict src, rsize_t count);
字符串的比较
int strcmp( const char *lhs, const char *rhs );
https://en.cppreference.com/w/c/string/byte/strcmp
int strncmp( const char *lhs, const char *rhs, size_t count );
https://en.cppreference.com/w/c/string/byte/strncmp
int memcmp( const void* lhs, const void* rhs, size_t count );
https://en.cppreference.com/w/c/string/byte/memcmp
字符串的分割
char *strtok( char *restrict str, const char *restrict delim );
https://en.cppreference.com/w/c/string/byte/strtok
char *strtok_s(char *restrict str, rsize_t *restrict strmax, const char *restrict delim, char **restrict ptr);
字符串的查找
char *strchr( const char *str, int ch );
char *strrchr( const char *str, int ch );
https://en.cppreference.com/w/c/string/byte/strchr
https://en.cppreference.com/w/c/string/byte/strrchr
Rabin-Karp算法
字符串的转化
long strtol( const char *restrict str, char **restrict str_end, int base );
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具