提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
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
函数接受两个参数:str
和 delimiters
。其中:
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 函数时传入 str
和 delimiters
参数,并将返回的子字符串赋给 token
变量。然后通过一个循环不断调用 strtok
函数,传入 NULL
和 delimiters
参数,直到所有的子字符串都被分割出来。
该示例的输出结果为:
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
的结构体,包含一个字符串类型的姓名和一个整数类型的年龄。然后我们创建了两个结构体变量 person1
和 person2
,并初始化 person1
。
通过调用 memcpy
函数,我们将 person1
的内容复制到 person2
中。&person2
表示目标内存块的起始地址,&person1
表示源内存块的起始地址,sizeof(struct Person)
表示要复制的字节数(即结构体大小)。
最后,我们打印输出 person2
的姓名和年龄,可以看到 person2
成功复制了 person1
的值。
person2: name=Alice, age=25
需要注意的是,使用 memcpy 进行内存复制时需要确保目标内存块足够大,以防止发生溢出。此外,源内存块和目标内存块不应有重叠,否则结果将是不确定的。
总结:
以上便是字符串需要了解到底一些基本只是和常用函数的用法,除此之外还有别的函数,值得去自己用到的时候好好领会。