C 语言字符串操作总结

一、字符串操作

size_t 是一个无符号整型。

1.1 strcpy

函数原型:char *strcpy(char *dest, const char *src)。

功 能:把 src 所指向的字符串复制到 dest 中。

返 回 值:该函数返回一个指向最终的目标字符串 dest 的指针。

注意事项:需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。

#include <stdio.h>
#include <string.h>

#define STRING_LEN_24 24

int main()
{
    char src[] = "hello world";
    char dest[STRING_LEN_24];

    char *buf = strcpy(dest, src);

    // buf == dest, hello world
    puts(buf);
    puts(dest);

    return 0;
}

1.2 strncpy

函数原型:char *strncpy(char *dest, const char *src, size_t n)。

功 能:把 src 所指向的字符串复制到 dest,最多复制 n 个字符。

返 回 值:该函数返回一个指向最终的目标字符串 dest 的指针。

注意事项:

  1. 当 src 的长度小于 n 时,dest 的剩余部分将用'\0'填充。
  2. 第三个参数 size_t 一般设置为目标字符串 dest 的长度 - 1,因为要空出一位放置'\0'
#include <stdio.h>
#include <string.h>

#define STRING_LEN_24 24

int main()
{
    char src[] = "hello world";
    char dest[STRING_LEN_24];

    char *buf = strncpy(dest, src, STRING_LEN_24 - 1);

    // buf == dest
    puts(buf);
    puts(dest);

    return 0;
}

1.3 strcat

函数原型:char *strcat(char *dest, const char *src)。

功 能:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。

返 回 值:该函数返回一个指向最终的目标字符串 dest 的指针。

注意事项:确保目标数组 dest 有足够的空间容纳 src。

#include <stdio.h>
#include <string.h>

#define STRING_LEN_24 24

int main()
{
    char src[] = "hello world";
    char dest[STRING_LEN_24] = "ABCDE";

    char *buf = strcat(dest, src);

    // buf == dest, ABCDEhello world
    puts(buf);
    puts(dest);

    return 0;
}

1.4 strncat

函数原型:char *strncat(char *dest, const char *src, size_t n)。

功 能:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,最大复制 n 字符长度。

返 回 值:该函数返回一个指向最终的目标字符串 dest 的指针。

注意事项:第三个参数要确保不会溢出 dest,建议传入 dest 的剩余空间 - 1。

#include <stdio.h>
#include <string.h>

#define STRING_LEN_16 16

int main()
{
    char src[] = "hello world";
    char dest[STRING_LEN_16] = "ABCDE";

    // 第三个参数:dest 剩余可支配空间 - 1, 也就是 16 - 5 - 1 = 10
    char *buf = strncat(dest, src, STRING_LEN_16 - strlen(dest) - 1);

    // buf == dest, ABCDEhello worl
    puts(buf);
    puts(dest);

    return 0;
}

1.5 strcmp

函数原型:int strcmp(const char *str1, const char *str2)。

功 能:把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

返 回 值:

  1. 如果返回值小于 0,则表示 str1 小于 str2。
  2. 如果返回值大于 0,则表示 str1 大于 str2。
  3. 如果返回值等于 0,则表示 str1 等于 str2。

说 明:两个字符串自左向右逐个字符相比(按 ASCII 值大小相比较),直到出现不同的字符或遇 \0 为止。

1.6 strncmp

函数原型:int strcmp(const char *str1, const char *str2)。

功 能:把 str1 和 str2 进行比较,最多比较前 n 个字节。

返 回 值:

  1. 如果返回值小于 0,则表示 str1 小于 str2。
  2. 如果返回值大于 0,则表示 str1 大于 str2。
  3. 如果返回值等于 0,则表示 str1 等于 str2。

说 明:自左向右比较前 n 个字符,直到出现不同的字符或遇 \0 为止。

strncmp()函数首先将 str1 字符串的第一个字符的 ACSII 值减去 str2 第一个字符的 ACSII 值:1. 若差值为零则继续比较下去;2. 若差值不为零,则返回差值。

1.7 strcasecmp

函数原型:int strcasecmp(const char *s1, const char *s2)。

功 能:把 str1 所指向的字符串和 str2 所指向的字符串不区分大小写的进行比较。

返 回 值:

  1. 如果返回值小于 0,则表示 str1 小于 str2。
  2. 如果返回值大于 0,则表示 str1 大于 str2。
  3. 如果返回值等于 0,则表示 str1 等于 str2。

1.8 strncasecmp

函数原型:int strncasecmp(const char *str1, const char *str2, size_t n)。

功 能:把 str1 所指向的字符串和 str2 所指向的字符串不区分大小写的进行比较,最多比较前 n 个字符。

返 回 值:

  1. 如果返回值小于 0,则表示 str1 小于 str2。
  2. 如果返回值大于 0,则表示 str1 大于 str2。
  3. 如果返回值等于 0,则表示 str1 等于 str2。

1.9 strspn

函数原型:size_t strspn(const char *str1, const char *str2)。

功 能:检索字符串 str1 开头连续有几个字符都出现在字符串 str2 中的字符个数。

返 回 值:该函数返回 str1 中第一个不在字符串 str2 中出现的字符下标。

举个例子:

str1 str2 返回值 说明
abcdefg abcd 4 e 是第一个未出现的,返回其下标 4
abcdefg acde 1 b 是第一个未出现的,返回其下标 1
abcdefg abcdefg 7 全都存在,返回 str1 的长度

1.10 strcspn

函数原型:size_t strcspn(const char *str1, const char *str2)。

功 能:检索字符串 str1 开头连续有几个字符都没有出现在字符串 str2 中的字符个数,与函数 strspn 的作用刚好相反。

返 回 值:返回 str1 开头连续都不含字符串 str2 中字符的字符数。

举个例子:

str1 str2 返回值 说明
abcdefg defg 3 字符 a、b、c 未出现
abcdefg aXYG 0 首字符 a 就出现了
abcdefg XYG 7 全都不存在
  • c : complementary,互补的
  • spn:span,跨度

二、格式化输出

2.1 sprintf

函数原型:int sprintf(char *str, const char *format, ...)。其中 ... 省略的是与 format 相匹配的参数们。

功 能:将格式化后的字符串保存到 str 所指向的字符串中。

返 回 值:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。

注 意:确保 str 空间足够大,不要溢出。

#include <stdio.h>
#include <string.h>

#define STRING_LEN_64 64

int main()
{
    char str1[] = "hello world";
    char str2[] = "how are you";
    char str[STRING_LEN_64];

    int n = sprintf(str, "str1[%s], str2[%s]", str1, str2);

    // 输出:str1[hello world], str2[how are you], 36
    printf("%s, %d\n", str, n);

    return 0;
}

类比 printf,区别在于 printf 是输出到屏幕上,而 sprintf 输出到字符串 str 中。

2.2 snprintf

函数原型:int snprintf(char *str, size_t size, const char *format, ...)。

功 能:将可变参数 ... 按照 format 格式化成字符串,并保存到 str 中,size 为要写入的字符的最大数目,超过 size 会被截断。

返 回 值:

  1. 如果格式化后的字符串长度小于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0。
  2. 如果格式化后的字符串长度大于等于 size,超过 size 的部分会被截断,只将其中的 size - 1 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define STRING_LEN_16 16

int main()
{
    char str1[] = "hello world";
    char str2[] = "how are you";
    char str[STRING_LEN_16];

    // 第二个参数传入字符串总大小即可,因为如果格式化后的字符串长度 >= size 的话,只保留 size - 1 个字符
    int n = snprintf(str, STRING_LEN_16, "str1[%s], str2[%s]", str1, str2);

    // 输出:str1[hello wor, 36
    printf("%s, %d\n", str, n);

    return 0;
}

通过输出 n 可验证,该函数返回值为欲写入的字符串长度,而不是写入的长度。

参考资料