Skip to content

字符串操作

在C语言中,字符串是以'\0'结尾的字符数组。字符串操作函数通常定义在<string.h>头文件中。而 char 类型在C语言中是一个字符类型,它通常占用1个字节的空间,用于表示ASCII码中的字符,因此,一个字符基本可以认为是一个字节,一个字符可以认为是一个 0-255 的整数。

字符串函数

c
#include <string.h>

/**
 * 字符串长度
 * 通过遍历字符串统计长度,直到遇到'\0'为止
 */
size_t strlen(const char *s);

/**
 * 字符串复制
 * 通过遍历字符串,将源字符串的字符复制到目标字符串,直到遇到'\0'为止
 */
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
// strdup和strndup函数会自动为复制的内容分配内存,并将复制的内容返回,因此需要手动释放内存
char *strdup(const char *s);
char *strndup(const char *s, size_t n);

/**
 * 字符串比较
 * 通过遍历字符串,逐一比较两个字符串的字符,判断是否相等
 */
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
int strcasecmp(const char *s1, const char *s2);  // 忽略大小写比较字符串
int strncasecmp(const char *s1, const char *s2, size_t n);  // 忽略大小写比较字符串的前n个字符

/**
 * 字符串查找
 */
char* strchr(const char *s, int c);  // 查找字符c在字符串s中首次出现的位置,返回指向该位置的指针,如果找不到则返回NULL
char* strstr(const char *haystack, const char *needle); // 查找字符串needle在字符串haystack中首次出现的位置,返回指向该位置的指针,如果找不到则返回NULL
char *strpbrk(const char *s, const char *accept); // 查找字符串 s 中第一个出现在 accept 字符串中的字符,并返回指向该字符的指针

/**
 * 字符串拼接
 * 通过遍历字符串,将源字符串的字符复制到目标字符串的末尾
 * 注意:目标字符串必须有足够的空间来容纳源字符串的内容
 */
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);

/**
 * 字符串分割
 * 通过遍历字符串,将字符串按照指定的分隔符进行分割,返回指向分割后的子字符串的指针数组
 * 注意:返回的指针数组需要手动释放内存
 */
char* strtok(char *str, const char *delim);

// eg:
char str[] = "Hello,World,This,Is,C";
const char delim[] = ",";

char *token = strtok(str, delim);  // 第一次调用,传入字符串
while (token != NULL) {
  printf("%s\n", token);          // 打印每个子串
  token = strtok(NULL, delim);    // 后续调用,传入 NULL
}
// 输出:
// Hello
// World
// This
// Is
// C


/**
 * 字符串转换
 * 将字符串转换为整数或浮点数
 */
int atoi(const char *nptr);  // 将字符串转换为 int
long atol(const char *nptr);  // 将字符串转换为 long
long long atoll(const char *nptr);  // 将字符串转换为 long long
double atof(const char *nptr);  // 将字符串转换为 double
long strtol(const char *nptr, char **endptr, int base);  // 将字符串转换为 long,并指定进制
double strtod(const char *nptr, char **endptr);  // 将字符串转换为 double

char* strlwr(char* str);  // 将字符串转换为小写
char* strupr(char* str);  // 将字符串转换为大写
char* strrev(char* str);  // 将字符串反转

// 字符串格式化
char *sprintf(char *str, const char *format, ...);
char *snprintf(char *str, size_t size, const char *format, ...);
char *vsprintf(char *str, const char *format, va_list ap);
char *vsnprintf(char *str, size_t size, const char *format, va_list ap);

// eg:
char str[100];
sprintf(str, "Hello, %s!", "world");  // 将字符串 "Hello, world!" 格式化并存储在 str 中
printf("%s\n", str);  // 输出 "Hello, world!"

/*
 * 字符串统计
 */
size_t strspn(const char *s, const char *accept);  // 统计字符串 s 中出现的字符在 accept 字符串中的个数
size_t strcspn(const char *s, const char *reject);  // 统计字符串 s 中没有出现在 reject 字符串中的字符个数

字节操作

字节操作是指对单个字节进行操作,例如读取、写入、比较等。在C语言中,可以使用以下类型来表示字节:

  • unsigned char:无符号字符类型,表示一个字节。
  • signed char:有符号字符类型,表示一个字节。
  • uint8_t:无符号8位整数类型,表示一个字节。

字节序

字节序是指多字节数据在内存中的存储顺序。常见的字节序有两种:

  • 大端序(Big-Endian):高位字节存储在低地址,低位字节存储在高地址。
  • 小端序(Little-Endian):低位字节存储在低地址,高位字节存储在高地址。

在C语言中,可以使用以下宏来检测和设置字节序:

c
#include <stdint.h>

// 检测字节序
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

位运算

在C语言中,可以使用以下位运算符来进行位操作:

  • &:按位与
  • |:按位或
  • ^:按位异或
  • ~:按位取反
  • <<:左移
  • >>:右移

字节操作函数

在C语言中,可以使用以下函数来进行字节操作:

c
/*
 * 将src指向的内存块复制到dest指向的内存块中,并返回dest指针
 */
void* memcpy(const void* dest, const void* src, size_t n);
void* memmove(void* dest, const void* src, size_t n);  // 与memcpy类似,但可以安全地处理重叠的内存块

/*
 * 将dest指向的内存块中的每个字节都设置为c,并返回dest指针
 */
void* memset(void* dest, int c, size_t n);

/*
 * 比较src1指向的内存块和src2指向的内存块的前n个字节,并返回它们的差值
 */
int memcmp(const void* src1, const void* src2, size_t n);

/*
 * 在src指向的内存块中查找c,并返回指向它的指针
 */
void* memchr(const void* src, int c, size_t n);