C语言——字符串和字符串函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

C语言中的字符串是由字符组成的字符数组,以空字符('\0')作为结尾。字符串在C语言中被广泛使用,因为它们可以用来表示文本和其他类型的数据。在本文中,我们将深入探讨C语言中的字符串和常见的字符串函数。

字符串的定义和初始化

在C语言中,字符串可以通过字符数组来定义和初始化。例如:

char str[10] = "Hello";

在这个例子中,我们定义了一个字符数组 str,大小为10,然后用字符串字面量 "Hello" 初始化它。请注意,字符数组的大小应该足够大以容纳字符串及其结尾的空字符。

另外,还可以使用字符指针来定义和初始化字符串:

const char* str = "World";

在这个例子中,我们定义了一个指向字符常量的指针 str,并将其初始化为字符串字面量 "World" 的地址。这种方式更常用,因为它方便且不需要显式指定数组大小。

字符串的输入与输出
要输出一个字符串,可以使用 printf 函数:

char str[] = "Hello";
printf("%s\n", str);

在这个例子中,我们使用 %s 格式说明符来输出字符串。

要从用户处输入一个字符串,可以使用 scanf 函数或 fgets 函数:

char str[20];
printf("请输入一个字符串:");
scanf("%s", str);  // 或者使用 fgets 函数

在这个例子中,我们使用 scanf 函数从用户处读取一个字符串,并将其存储在字符数组 str 中。请注意,scanf 函数遇到空格或换行符就会停止读取,所以不能读取含有空格的字符串。如果需要读取含有空格的字符串,可以使用 fgets 函数。
了读取含有空格的字符串,可以使用 fgets 函数。该函数可以读取一整行字符串,包括空格和其他字符,直到遇到换行符或读取的字符数达到指定的最大值为止。例如:

char str[100];
printf("请输入一个字符串:");
fgets(str, 100, stdin);

在这个例子中,我们使用 fgets 函数从标准输入流中读取一行字符串,并将其存储在字符数组 str 中,最多读取 99 个字符(包括结尾的空字符)。

需要注意的是,fgets 函数在读取完一行后会保留换行符 \n,因此如果不需要该字符,需要手动删除。

字符串的比较

要比较两个字符串是否相等,可以使用 strcmp 函数:

char str1[] = "Hello";
char str2[] = "World";
if (strcmp(str1, str2) == 0) {
    printf("字符串相等\n");
} else {
    printf("字符串不相等\n");
}

在这个例子中,我们使用 strcmp 函数比较字符串 str1 和 str2 是否相等。如果相等,strcmp 函数返回 0,否则返回非零值。

字符串的拼接

要将两个字符串拼接在一起,可以使用 strcat 函数:

char str1[20] = "Hello";
char str2[] = "World";
strcat(str1, str2);
printf("%s\n", str1);  // 输出 "HelloWorld"

在这个例子中,我们使用 strcat 函数将字符串 str2 拼接到字符串 str1 的末尾。

字符串的复制

我们看看下面的代码:
想要把zhangsan存到name里面,直接赋值是不行的,程序会报错说左值(也就是name)表达式必须是可修改的左值,

#include<stdio.h>
 int main()
{
char name[20] = "xxxxxxXX";
//"zhangsan"
//string copy
//strcpy(name,"zhangsan");
name =“zhansan”;//err,name数组名是地址,地址是一个常量值,不能被赋值
printf("%s\n", name);
return 0;
}

所以,我们直接赋值行不通,那么我们可以试着使用字符串函数。
要将一个字符串复制到另一个字符串,可以使用 strcpy 函数:

char str1[20] = "Hello";
char str2[] = "World";
strcpy(str1, str2);
printf("%s\n", str1);  // 输出 "World"

在这个例子中,我们使用 strcpy 函数将字符串 str2 复制到字符串 str1 中。

求字符串长度

要获取一个字符串的长度,可以使用 strlen 函数:

char str[] = "Hello";
int len = strlen(str);
printf("字符串长度:%d\n", len);  // 输出 5

在这个例子中,我们使用 strlen 函数获取字符串的长度,并将其存储在整型变量 len 中。
但是要注意的是,strlen函数的返回值为size_t,是无符号的,就像下面例子,虽然str1的长度比str2长,但是返回的是无符号数,3-6的结果在无符号数中算是一个很大的值,所以结果会是str2>str1

#include <stdio.h>
int main()
{
 const char*str1 = "abcdef";
 const char*str2 = "bbb";
 if(strlen(str2)-strlen(str1)>0)
 {
 printf("str2>str1\n");
 } 
 else
 {
 printf("srt1>str2\n");
 }
 return 0;
}

运行结果:

str2>str1

关于strlen函数,我们可以试着自己写一个库函数来 代替实现:
方法1:

//计数器方式
int my_strlen(const char * str)
{
 int count = 0;
 while(*str)
 {
 count++;
 str++;
 }
 return count;
}

方法2

//指针-指针的方式
int my_strlen(char *s)
{
       char *p = s;
       while(*p != ‘\0)
              p++;
       return p-s;
}

分割字符串

strtok 函数是 C 语言中用于分割字符串的函数,其原型如下:

char* strtok(char* str, const char* delimiters);

strtok 函数接受两个参数:strdelimiters。其中:

str:要分割的字符串,可以是一个指向字符数组或字符串字面量的指针。
delimiters:分割符号,指定了用于切割字符串的字符集合。可以是一个字符串字面量,也可以是一个字符数组。
strtok 函数会将 str 字符串按照 delimiters 中的字符进行分割,并返回分割出的子字符串。每次调用 strtok 函数时,会返回一个不同的子字符串,直到字符串被完全分割。

在首次调用 strtok 函数时,需要传入 str 参数,后续的调用则将 str 设置为 NULL。这是因为 strtok 函数会使用静态变量来保存上一次被分割的位置,通过将 str 参数设置为 NULL 来告知函数继续使用上一次的分割位置。

以下是一个使用 strtok 函数分割字符串的示例:

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

int main() {
    char str[] = "Hello,world,how,are,you";
    char delimiters[] = ",";

    char* token = strtok(str, delimiters); // 第一次调用 strtok
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, delimiters); // 后续调用 strtok
    }

    return 0;
}

上述示例中,str 字符串中的单词使用逗号 , 分隔。首次调用 strtok 函数时传入 strdelimiters 参数,并将返回的子字符串赋给 token 变量。然后通过一个循环不断调用 strtok 函数,传入 NULLdelimiters 参数,直到所有的子字符串都被分割出来。
该示例的输出结果为:

Hello
world
how
are
you

每次调用 strtok 函数会返回一个分割的子字符串,直到没有更多的子字符串可分割时,函数会返回 NULL

获取错误码对应的错误信息

strerror 函数是 C 语言中用于获取错误码对应的错误信息的函数,其原型如下:

char* strerror(int errnum);

strerror 函数接受一个整数参数 errnum,代表错误码。它会返回一个指向字符串的指针,该字符串包含了与错误码对应的错误信息。

通常情况下,errnum 参数是由其他系统调用或库函数返回的错误码。strerror 函数会根据给定的错误码查找对应的错误信息并返回。如果找不到对应的错误信息,则返回一个通用的错误描述。

以下是一个使用 strerror 函数的示例:

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

int main() {
    FILE* file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        int errnum = errno;
        printf("Error opening file: %s\n", strerror(errnum));
    }

    return 0;
}

在上述示例中,我们尝试打开一个不存在的文件 "nonexistent.txt"。由于文件不存在,fopen 函数会返回一个空指针,并且设置全局变量 errno 为适当的错误码。

接着,我们使用 strerror 函数获取与错误码对应的错误信息,并将其打印出来。strerror(errno) 表示获取当前的错误信息。

假设错误码为 ENOENT(表示文件不存在),那么输出结果将类似于:

Error opening file: No such file or directory

注意,strerror 函数返回的字符串是一个静态存储的字符串,因此不需要手动释放内存。每次调用 strerror 函数都会返回一个指向相应错误信息的指针,但是在多线程环境中使用时要小心,因为这个字符串是共享的。

另外,要正确使用 strerror 函数,需要包含头文件 <string.h><errno.h><errno.h> 头文件定义了各种错误码的宏定义。

内存拷贝的函数

memcpy 函数是 C 语言中用于内存拷贝的函数。它的原型如下:

void* memcpy(void* dest, const void* src, size_t n);

memcpy 函数将 src 指针指向的内存块的内容复制到 dest 指针指向的内存块中,复制的字节数由 n 参数指定。

dest:指向目标内存块的指针,即要将数据复制到的位置。
src:指向源内存块的指针,即要从中复制数据的位置。
n:要复制的字节数。

memcpy 函数会按字节对内存进行复制,不考虑复制的内容是什么类型。因此,可以用它来复制任意类型的数据(包括基本类型、结构体、数组等)。

以下是一个使用 memcpy 函数的示例:

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

struct Person {
    char name[20];
    int age;
};

int main() {
    struct Person person1 = {"Alice", 25};
    struct Person person2;

    memcpy(&person2, &person1, sizeof(struct Person));

    printf("person2: name=%s, age=%d\n", person2.name, person2.age);

    return 0;
}

在上述示例中,我们定义了一个名为 Person 的结构体,包含一个字符串类型的姓名和一个整数类型的年龄。然后我们创建了两个结构体变量 person1person2,并初始化 person1

通过调用 memcpy 函数,我们将 person1 的内容复制到 person2 中。&person2 表示目标内存块的起始地址,&person1 表示源内存块的起始地址,sizeof(struct Person) 表示要复制的字节数(即结构体大小)。

最后,我们打印输出 person2 的姓名和年龄,可以看到 person2 成功复制了 person1 的值。

person2: name=Alice, age=25

需要注意的是,使用 memcpy 进行内存复制时需要确保目标内存块足够大,以防止发生溢出。此外,源内存块和目标内存块不应有重叠,否则结果将是不确定的。

总结:

以上便是字符串需要了解到底一些基本只是和常用函数的用法,除此之外还有别的函数,值得去自己用到的时候好好领会。

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值