【C语言】基础知识详解(二) 字符串

一、什么是字符串?

在C语言中,字符串是一种特殊的字符数组,用于存储一系列字符。

  1. 字符串的表示:在C语言中,字符串是由字符组成的数组,并以空字符 '\0' 结束。空字符用于标识字符串的结束。例如,字符串 "hello" 在内存中实际上是 {'h', 'e', 'l', 'l', 'o', '\0'}

  2. 字符串声明:可以使用字符数组来声明字符串。例如:

  3. char str[6] = "hello";
    

    注意数组的大小是6,因为包括了字符串的结束符 '\0'

  4. 字符串初始化:可以在声明时直接初始化字符串,也可以通过逐个字符的方式来赋值:

char str1[] = "hello"; // 自动分配足够的空间
char str2[6] = "hello"; // 明确指定数组大小

二、字符串与字符数组 

字符数组是一种存储字符数据的基本数据结构。它们是处理文本数据的核心工具之一。

       1.字符数组的定义: 字符数组是由一组字符元素组成的数组。可以用以下方式声明和初始化字符数组:

char array[10];      // 声明一个可以存储10个字符的数组
char str[] = "hello"; // 声明并初始化一个字符数组,大小自动计算

        2.字符数组的访问: 你可以通过下标来访问字符数组中的每个字符。例如: 

char str[] = "hello";
char first_char = str[0]; // 'h'
char second_char = str[1]; // 'e'

        3.字符数组的大小: 字符数组的大小是固定的,一旦定义不能更改。如果数组的实际大小不足以存储所有需要的字符(包括结束符),会导致缓冲区溢出或未定义行为。正确设置数组的大小是很重要的:

char buffer[20]; // 足够大的缓冲区以存储20个字符

        4.字符串与字符数组的区别:虽然字符串在C中是字符数组的特例,但它们有一些不同之处。字符数组可以容纳任意字符数据,而字符串必须以 '\0' 结束才能正确处理。

三、字符串的常用操作函数

C语言为我们提供了许多操作函数用来处理字符串变量,它们主要集中在 <string.h> 头文件中。下面为大家简单介绍几个常用的操作函数:

1. strcmp

功能: 比较两个字符串。

原型:

int strcmp(const char *str1, const char *str2);

返回值:

  • 0:两个字符串相等。
  • 负数:str1 小于 str2
  • 正数:str1 大于 str2

示例:

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

int main() {
    char str1[] = "apple";
    char str2[] = "banana";
    int result = strcmp(str1, str2);
    if (result < 0) {
        printf("str1 is less than str2\n");
    } else if (result > 0) {
        printf("str1 is greater than str2\n");
    } else {
        printf("str1 is equal to str2\n");
    }
    return 0;
}

 与此函数功能相似的还有strncmp函数:

功能: 比较两个字符串的前 n 个字符。

原型:

int strncmp(const char *str1, const char *str2, size_t n);

参数:

  • str1:第一个字符串。
  • str2:第二个字符串。
  • n:要比较的字符数。

返回值: 与 strcmp 相同,但仅比较前 n 个字符。

2. strcat

功能: 连接两个字符串,将 str2 追加到 str1 的末尾。

原型:

char *strcat(char *dest, const char *src);

参数:

  • dest:目标字符串,必须有足够的空间来存放连接后的结果。
  • src:源字符串。

返回值: dest

示例:

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

int main() {
    char str1[20] = "Hello, ";
    char str2[] = "World!";
    strcat(str1, str2);
    printf("%s\n", str1); // 输出 "Hello, World!"
    return 0;
}

 与此函数功能相似的还有strncat函数:

功能: 将源字符串的前 n 个字符追加到目标字符串的末尾。

原型:

char *strncat(char *dest, const char *src, size_t n);

参数:

  • dest:目标字符串。
  • src:源字符串。
  • n:要追加的字符数。

返回值: dest

示例:

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

int main() {
    char dest[20] = "Hello, ";
    char src[] = "World!";
    strncat(dest, src, 3); // 仅追加 "Wor"
    printf("%s\n", dest); // 输出 "Hello, Wor"
    return 0;
}

3. strcpy

功能: 复制源字符串到目标字符串。

原型:

char *strcpy(char *dest, const char *src);

参数:

  • dest:目标字符串,必须有足够的空间来存放源字符串及结束符。
  • src:源字符串。

返回值: dest

示例:

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

int main() {
    char src[] = "Hello, World!";
    char dest[50];
    strcpy(dest, src);
    printf("%s\n", dest); // 输出 "Hello, World!"
    return 0;
}

注意,strcpy函数通常用于字符串赋值。因为在一定场景下对字符串进行赋值时,若使用“=”,只会将原始数据的地址(即一个常量)赋值给目标变量。而使用strcpy函数会使用两个字符串进行拷贝操作,确保了赋值的准确性。

与以上的几个函数一样,也存在strncpy函数可以进行部分拷贝,可以灵活地将字符串给分割。此处不过多赘述。

4. strlen

功能: 计算字符串的长度(不包括结束符 '\0')。

原型:

size_t strlen(const char *str);

参数:

  • str:待计算长度的字符串。

返回值: 字符串的长度。

示例:

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

int main() {
    char str[] = "Hello, World!";
    size_t length = strlen(str);
    printf("Length: %zu\n", length); // 输出 "Length: 13"
    return 0;
}

5. strtok

功能: 分解字符串为一系列标记(tokens),根据分隔符分割。

原型:

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

参数:

  • str:待分解的字符串。第一次调用时传递原始字符串,之后传递 NULL 以获取后续标记。
  • delim:分隔符字符串,包含所有用作分隔的字符。

返回值: 指向当前标记的指针。

示例:

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

int main() {
    char str[] = "Hello, World! How are you?";
    char *token = strtok(str, " ,!?");
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, " ,!?");
    }
    return 0;
}

6. strstr

功能: 查找子字符串在主字符串中的第一次出现位置。

原型:

char *strstr(const char *haystack, const char *needle);

参数:

  • haystack:主字符串。
  • needle:要查找的子字符串。

返回值: 指向子字符串在主字符串中的位置;如果未找到,则返回 NULL

示例:

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

int main() {
    char str[] = "Hello, World!";
    char *pos = strstr(str, "World");
    if (pos != NULL) {
        printf("Found substring: %s\n", pos); // 输出 "World!"
    }
    return 0;
}

四、字符串的引申应用

以上所提到的字符串操作函数被引申至内存上,有了一部分内存操作函数,内存操作函数主要集中在 <stdlib.h><string.h> 头文件中。

1. memcpy

功能: 从源内存块复制指定字节数到目标内存块。

原型:

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

参数:

  • dest:目标内存块。
  • src:源内存块。
  • n:要复制的字节数。

返回值: 返回 dest

示例:

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

int main() {
    char src[] = "Hello, World!";
    char dest[20];
    memcpy(dest, src, strlen(src) + 1); // 复制字符串,包括结束符
    printf("%s\n", dest); // 输出 "Hello, World!"
    return 0;
}

2. memmove

功能: 从源内存块移动指定字节数到目标内存块,允许内存重叠。

原型:

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

参数:

  • dest:目标内存块。
  • src:源内存块。
  • n:要移动的字节数。

返回值: 返回 dest

示例:

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

int main() {
    char str[] = "abcdefghij";
    memmove(str + 2, str, 5); // 移动前5个字符
    printf("%s\n", str); // 输出 "ababcde"
    return 0;
}

 memcpy与memmove函数的区别:

memcpymemmove 都是用于内存操作的函数,用于复制内存块中的数据,但它们在处理内存重叠情况时有不同的行为。

memcpy 用于从一个内存位置复制数据到另一个内存位置,通常用于内存块之间的简单数据复制。它通常比 memmove 更快,因为它不处理内存重叠的情况。需要注意的是,如果源内存块和目标内存块重叠,memcpy 的行为是未定义的。这可能导致数据丢失或未预期的结果,因此 memcpy 不适用于重叠内存区域。

memmove 适用于处理内存块重叠的情况。在需要将内存中的数据从一个区域移动到另一个区域时,即使这两个区域重叠,memmove 也能安全地处理。memmove 在执行过程中会采取一些措施来处理源和目标区域重叠的情况,从而保证数据的正确性。

因此,选择使用 memcpy 还是 memmove 主要取决于是否需要处理内存区域的重叠。如果确定内存区域不重叠,使用 memcpy 可以获得更好的性能和更高的效率 ;如果内存区域可能重叠,则应该使用 memmove 以确保数据的正确性。

3. memset

功能: 设置内存块的每个字节为指定的值。

原型:

void *memset(void *ptr, int value, size_t num);

参数:

  • ptr:要设置的内存块。
  • value:要设置的值(将被转为无符号字符)。
  • num:要设置的字节数。

返回值: 返回 ptr

示例:

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

int main() {
    char str[20];
    memset(str, '*', sizeof(str) - 1); // 设置所有字节为 '*'
    str[19] = '\0'; // 确保以 null 结束
    printf("%s\n", str); // 输出 "*******************"
    return 0;
}

五、结语

以上就是我对字符串模块基础知识点的一些总结,欢迎小伙伴们在评论区发布讨论,一起交流。

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值