c语言常见字符串操作函数大全,一篇胜千篇!

常见的c语言字符串操作

比较字符串

strcmp()

函数原型:int (const char *_Str1,const char *_Str2);

函数要比较的是字符串的内容,不是字符串的地址。
如果在机器排序序列(通常是ASCII值)中第1个字符串位于第2个字符串前面,strcmp()中就返回负数,表面第一个字符小于第2个字符,反之,strcmp()则返回正数。如果两个字符串开始的几个字符都相同,strcmp()会依次比较每个字符,直到发现第1对不同的字符为止。然后,返回相应的值。

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

int main(){
    char s1[]="hello world";
    char s2[]="hello woRld";
    char s3[]="hello world";
    printf("%d\n",strcmp(s1,s2));//r位于R的后面,r的ASCII值大于R的ASCII值
    printf("%d\n",strcmp(s2,s1));
    printf("%d\n",strcmp(s3,s1));
}

image-20240928112642464

strncmp()

函数原型:int strncmp(const char *_Str1,const char *_Str2,size_t _MaxCount);

比较字符串str1 和str2 中至多count 个字符,如果参数中任一字符串长度小于count, 那么当比较到第一个空值结束符时,就结束处理。

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

int main(){
    char s1[]="hello world";
    char s2[]="hello woRld";
    char s3[]="hello world HellO";
    printf("%d\n",strncmp(s1,s2,5));
    printf("%d\n",strncmp(s2,s1,10));
    printf("%d\n",strncmp(s3,s1,15));
}

image-20240928113128183

拼接字符串

strcat()

函数原型为:char * strcat(char * Dest,const char * Source);

strcat()函数接受两个字符串作为参数。该函数把第2个字符串的备份附加在第1个字符串末尾,返回值为第1个参数,即拼接第2个字符串后的第1个字符串的地址。

strcat()函数无法检查第1个数组是否能容纳第2个字符串。如果分配给第1个数组的空间不够大,多出来的字符溢出到相邻存储单元时就会出问题。

(代码中的m_fgets()函数是对fgets()的处理,这里可以当作是gets()的替换,了解详情看c语言输出输出一文

#include <stdio.h>
#include <string.h>
char* m_fgets(char s[], int n) {
    char* ret = NULL;
    int i = 0;
    ret = fgets(s, n, stdin);
    if (ret) {
        while (s[i] != '\0' && s[i] != '\n')i++;
        if (s[i] == '\n') s[i] = '\0';
        else
            while (getchar() != '\n') 
            continue;
    }
    return ret;
}
int main()
{
    char d[20];
    char s[10] = "zxcvbnm.";
    m_fgets(d, sizeof(d));
    fputs(d, stdout);
    strcat(d, s);
    printf("\nd=%s\n", d);

    char a[20];
    char b[10] = "zxcvbnm.";
    m_fgets(a, sizeof(a));
    fputs(a, stdout);
    strcat(a, b);
    printf("\nd=%s\n", a);
}

输入输出结果

image-20240928094051024

strncat()

函数原型:char *strncat(char * Dest,const char * Source,size_t _Count)

用strncat()函数的第3个参数指定了最大添加字符数。例如,strncat(d,s,5)将把s 字符串的内容附加给d,在加到第5个字符或遇到空字符'\0'时停止。因此,算上空字符d数组应该足够大,以容纳原始字符串(不包含空字符)、添加原始字符串在后面的5字符和末尾的空字符。

建议n的取值为目标数组大小-字符串长度-1

(代码中的m_fgets()函数是对fgets()的处理,这里可以当作是gets()的替换,了解详情看c语言输出输出一文

#include <stdio.h>
#include <string.h>
char* m_fgets(char s[], int n) {
    char* ret = NULL;
    int i = 0;
    ret = fgets(s, n, stdin);
    if (ret) {
        while (s[i] != '\0' && s[i] != '\n')i++;
        if (s[i] == '\n') s[i] = '\0';
        else
            while (getchar() != '\n') 
            continue;
    }
    return ret;
}
int main()
{
    char d[20];
    char s[10] = "zxcvbnm.";
    m_fgets(d, sizeof(d));
    fputs(d, stdout);
    strncat(d,s,5);//将s字符串的内容附加给d,加到第5个字符停止
    printf("\nd=%s\n", d);

    char a[20];
    char b[10] = "zx";
    m_fgets(a, sizeof(a));
    fputs(a, stdout);
    strncat(a, b, 5);//将s字符串的内容附加给d,未加到第5个字符时遇到空字符停止
    printf("\na=%s\n", a);
}

输入输出结果

image-20240928095222131

拷贝字符串

strcpy()

函数原型:char * strcpy(char *Dest,const char * Source);

strcpy()函数相当于字符串赋值运算符,strcpy()第2个参数指向的字符串被拷贝至第1个参数指向的数组中。第1个参数不必指向数组的开始,可用于拷贝数组的部分。strcpy()把源字符串中的空字符’\0’也拷贝在内

strcpy

#include <stdio.h>
#include <string.h>
int main()
{
    char d[15]="what is this?";
    char s[10] = "hello";
    strcpy(d+3,s);
    puts(d);
}

strncpy

函数原型:char *strncpy(char *target,const char * Source,size_t _Count)

strcpy()和strcat()都有同样的问题,它们都不能检查目标空间是否能容纳源字符串的副本。strncpy()更安全,该函数的第3个参数指明可拷贝的最大字符数。

如果source中的字符数小于n,则拷贝整个字符串,包括空字符。但是,strncpy()拷贝字符串的长度不会超过n

#include <stdio.h>
#include <string.h>
int main()
{
    char d[14]="what is this?";
    char s[5] = "hell";
    strncpy(d,s,14);
    puts(d);
}

strncpy2

如果拷贝到第n个字符时还未拷贝完整个源字符串,就不会拷贝空字符。所以,拷贝的副本中不一定有空字符。

strncpy.drawio

拷贝的目标数组中没有空字符结尾,D就不是一个字符串,例如下代码

#include <stdio.h>
#include <string.h>
int main()
{
    char d[10]="what is t";
    char s[15] = "helloworld";
    strncpy(d,s,10);
    puts(d);
}

image-20240928105720887

鉴于此,把n设置为比目标数组大小少1,然后把数组最后一个元素设置为空字符\0,确保储存的是一个字符串。

#include <stdio.h>
#include <string.h>
int main()
{
    char d[10]="what is t";
    char s[15] = "helloworld";
    strncpy(d,s,10-1);
    d[10]='\0';
    puts(d);
}

image-20240928110333876

  • 如果目标空间D能容纳源字符串的副本,那么从源字符串S拷贝的空字符便是该副本的结尾:
  • 如果目标空间D装不下副本,则把副本S最后一个元素设置为空字符。

切割字符串

strtok()

函数原型:char *strtok(char *str, const char *delim);

  • str:要分割的字符串。如果是第一次调用,需要传入待分割的字符串;后续调用应传入 NULL

  • delim:一个包含所有分隔符的字符串。

  • strtok 会在原字符串中插入 \0 字符,以终止每个标记,因此原字符串会被修改。

  • 返回值为指向下一个标记的指针。如果没有更多的标记可供提取,则返回 NULL

    (标记是由一系列字符组成的子字符串,这些字符被分隔符分开。例如,在字符串 "Hello, world!" 中,逗号和空格是分隔符,标记包括 "Hello""world"

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

int main() {
    char str[] = "Hello, world! Welcome to C programming.";
    const char *delim = " ,.!"; // 定义分隔符
    char *token;

    // 获取第一个子字符串
    token = strtok(str, delim);

    // 遍历所有子字符串
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, delim); // 获取下一个子字符串
    }

    return 0;
}

输出结果

image-20241010145734634

strtok 不是线程安全的。如果需要在多线程环境中使用,可以考虑使用 strtok_r

strtok_r()

函数原型:char *strtok_r(char *str, const char *delim, char **saveptr);strtok_r 需要额外的参数来维护上下文,这使得它在多线程环境中更安全

  • str:要分割的字符串。如果是第一次调用此函数,这个参数传入待分割的字符串;后续调用时传入 NULL
  • delim:分隔符字符串,包含所有可能用作分隔的字符。
  • saveptr:指向 char* 指针的指针,用于保存上下文信息,以便后续调用继续从上次停止的位置开始。
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, world! Welcome to C.";
    const char *delim = " ,.!"; // 定义分隔符
    char *token;
    char *saveptr; // 保存上下文

    // 第一次调用,获取第一个标记
    token = strtok_r(str, delim, &saveptr);
    printf("saveptr: %s\n", saveptr);
    // 遍历所有标记
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok_r(NULL, delim, &saveptr); // 后续调用
        printf("saveptr: %s\n", saveptr);
    }

    return 0;
}

image-20240928142634657

sscanf()

函数原型:int sscanf(const char *str, const char *format, …);

返回值:成功读取的项目数。如果没有读取任何项,则返回 0;如果发生错误,则返回 EOF。

作用:从字符串中读取格式化的数据

#include<stdio.h>
int main(){
        char log_line[] = "2024-09-28 12:34:56 Error: Something went wrong.";
        char date[11];
        char time[9];
        char message[100];
        sscanf(log_line, "%10s %8s %99[^\n]", date, time, message);
        printf("date=%s\ntime=%s\nmessage=%s",date,time,message);
}

image-20240928114832523

sprintf()

函数原型:int sprintf(char str, const char format, …);

返回值为写入到字符串的字符总数,不包括终止的空字符。

sprintf()函数格式化字符串并写入到str中。

#include<stdio.h>
int main(){
        char s[100] ;
        char date[11]="2024-09-28";
        char time[9]="12:34:56";
        char message[100]="Error: Something went wrong.";
        sprintf(s,"date=%s time=%s message=%s\n",date,time,message);
        printf("s=%s",s);
}

image-20240928125526551

常见的字符串操作

  1. char * strchr(const char * s,int c); 字符查找

    如果s字符串中包含c字符,该函数返回指向s字符串第一次出现的位置的指针(末尾的空字符也是字符串的一部分,所以在查找范围内);如果在字符串s中未找到c字符,该函数则返回空指针。

  2. char* strrchr(const char* s,int c);字符查找
    该函数返回s字符串中c字符的最后一次出现的位置(末尾的空字符也是字符串的一部分,所以在查找范围内)。如果未找到c字符,则返回空指针。

  3. char * strpbrk(const char *s1,const char *s2);字符查找
    如果s1字符中包含s2字符串中的任意字符,该函数返回指向s1字符串首位置的指针:如果在s1字符串中未找到任何s2字符串中的字符,则返回空字符。

  4. char *strstr(const char*s1,const char*s2);子字符串查找
    该函数返回指向s1字符串中s2字符串出现的首位置。如果在s1中没有找到s2,则返回空指针

  5. int atoi(const char *str);将字符串转换为int整数

    如果字符串仅以整数开头,atio()函数也能处理,它只把开头的整数转换为字符。例如atoi(“42regular”)将返回整数 42。**如果字符串无法转换(例如,前导字符不是数字),则返回 0。然而C标准规定,这种情况下的行为是未定义的。**因此,使用有错误检测功能的strtol()函数会更安全。

  6. long strtol(const char *str, char **endptr, int base);将字符串转换为int整数

    endptr指向字符指针的指针,用于存储指向解析后字符串中未转换部分的指针;base表示进制,支持 2 到 36 之间的值

    返回转换后的长整型值。如果没有可转换的数字,则返回 0。如果发生溢出,则返回 LONG_MAXLONG_MIN,并设置 errnoERANGE,示例代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    int main() {
        const char *numStr = "12345well";
        char *endptr;
        long num = strtol(numStr, &endptr, 10);
    
        if (*endptr != '\0') {
            printf("Converted number: %ld\n", num);
            printf("Conversion stopped at: %s\n", endptr);
        } else {
            printf("Converted number: %ld\n", num);
        }
        printf("------------------------------------------------------\n");
        // 处理溢出
        const char *largeNumStr = "99999999999999999999"; // 超过 long 的范围
        errno = 0; // 重置 errno
        long largeNum = strtol(largeNumStr, NULL, 10);
    
        if (errno == ERANGE) {
            printf("Overflow occurred!\n");
        } else {
            printf("Converted large number: %ld\n", largeNum);
        }
    
        return 0;
    }
    

    image-20240928133855498

  7. 在 C 语言中,可以使用标准库函数将整数转换成字符串。最常用的方法是使用 sprintfsnprintf 函数。在一些编译器中,你可能还可以使用 itoa 函数(例如在某些 MSVC 编译器中),不过它不是标准 C 函数。

    #include <stdlib.h>
    #include<stdio.h>
    int main() {
        int num = 12345;
        char str[20];
    
        itoa(num, str, 10);  // 将整数转换为字符串, 10
        printf("%s\n", str);
        return 0;
    }
    //10
    

ASCII表

ASCII(美国标准信息交换码)是一种字符编码标准,用于表示文本中的字符。

十进制十六进制字符说明
000NUL空字符
101SOH标题开始
202STX正文开始
303ETX正文结束
404EOT传输结束
505ENQ查询
606ACK确认
707BEL响铃
808BS退格
909TAB水平制表符
100ALF换行
110BVT垂直制表符
120CFF换页
130DCR回车
140ESO移出
150FSI移入
1610DLE数据链路转义
1711DC1设备控制1
1812DC2设备控制2
1913DC3设备控制3
2014DC4设备控制4
2115NAK拒绝确认
2216SYN同步
2317ETB传输块结束
2418CAN取消
2519EM结束媒介
261ASUB替代
271BESC转义
281CFS文件分隔符
291DGS组分隔符
301ERS记录分隔符
311FUS单元分隔符
3220(space)空格
3321!感叹号
3422"双引号
3523#井号
3624$美元符号
3725%百分号
3826&
3927单引号
4028(左括号
4129)右括号
422A*星号
432B+加号
442C,逗号
452D-减号
462E.
472F/斜杠
48300数字0
49311数字1
50322数字2
51333数字3
52344数字4
53355数字5
54366数字6
55377数字7
56388数字8
57399数字9
583A:冒号
593B;分号
603C<小于号
613D=等号
623E>大于号
633F?问号
6440@井字号
6541A大写字母A
6642B大写字母B
6743C大写字母C
6844D大写字母D
6945E大写字母E
7046F大写字母F
7147G大写字母G
7248H大写字母H
7349I大写字母I
744AJ大写字母J
754BK大写字母K
764CL大写字母L
774DM大写字母M
784EN大写字母N
794FO大写字母O
8050P大写字母P
8151Q大写字母Q
8252R大写字母R
8353S大写字母S
8454T大写字母T
8555U大写字母U
8656V大写字母V
8757W大写字母W
8858X大写字母X
8959Y大写字母Y
905AZ大写字母Z
915B[左中括号
925C\反斜杠
935D]右中括号
945E^逻辑异或
955F_下划线
9660`反引号
9761a小写字母a
9862b小写字母b
9963c小写字母c
10064d小写字母d
10165e小写字母e
10266f小写字母f
10367g小写字母g
10468h小写字母h
10569i小写字母i
1066Aj小写字母j
1076Bk小写字母k
1086Cl小写字母l
1096Dm小写字母m
1106En小写字母n
1116Fo小写字母o
11270p小写字母p
11371q小写字母q
11472r小写字母r
11573s小写字母s
11674t小写字母t
11775u小写字母u
11876v小写字母v
11977w小写字母w
12078x小写字母x
12179y小写字母y
1227Az小写字母z
1237B{左花括号
1247C|竖线
1257D}右花括号
1267E~波浪号
1277FDEL删除字符

大部分控制字符(如 NUL、BEL 等)用于特殊目的,常用字符包括字母、数字和标点符号。

116 | 74 | t | 小写字母t |
| 117 | 75 | u | 小写字母u |
| 118 | 76 | v | 小写字母v |
| 119 | 77 | w | 小写字母w |
| 120 | 78 | x | 小写字母x |
| 121 | 79 | y | 小写字母y |
| 122 | 7A | z | 小写字母z |
| 123 | 7B | { | 左花括号 |
| 124 | 7C | | | 竖线 |
| 125 | 7D | } | 右花括号 |
| 126 | 7E | ~ | 波浪号 |
| 127 | 7F | DEL | 删除字符 |

大部分控制字符(如 NUL、BEL 等)用于特殊目的,常用字符包括字母、数字和标点符号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值