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

https://en.cppreference.com/w/c/string/byte/strtol

posted @ 2022-04-16 17:26  4thirteen2one  阅读(15)  评论(0编辑  收藏  举报