字符串在计算机编程中具有广泛的应用。字符串指的是由字符组成的序列,它是一种常见的数据类型,用于表示和处理文本数据。在这一篇文章中,我们将会字符串相关的内容:
- 字符串原理
- 字符串和内存
- 字符串操作函数
1. 字符串原理
C 语言中的字符串是字符序列 + 特殊的 \0 字符组成,注意 \0 字符串并不是数字 0,一个字符 0, 如下图所示:
为什么要在结束位置加上 \0 字符呢?
字符串数据不同于 int、double 等类型,它的数据长度不固定,读取时就没办法确定字符串的结束边界,因此,C 字符串使用 \0来作为结束符,即:当知道首字符的地址时,我们就一直往后读取,直到 \0 字符结束。
注意:指针无论存储什么类型的数据,都是存储其首字符地址。
2. 字符串和内存
在 C 语言中,字符串定义时会存在各种方式,我们需要了解不同方式定义时,内存分配是怎么样的,下面全面总结了各种情况:
#include <stdio.h> #include <string.h> #include <stdlib.h> // 1. 第一种情况 // p1 变量存储在全局区,由于 const 修饰,只读 // "hello world" 存储在字符串常量区,只读 const char* p1 = "hello world"; // 2. 第二种情况 // p2 存储在全局区,数组名不允许修改指向,只读 // "hello world" 存储在全局区,可读可写 char p2[] = "hello world"; int main() { printf("p1 = %s\n", p1); printf("p2 = %s\n", p2); // 3. 第三种情况 // p3 存储在栈区,由于 const 修饰,只读 // "hello world" 存储在字符串常量区,程序运行期间不会被销毁,只读 const char* p3 = "hello world"; printf("p3 = %s\n", p3); // 4. 第四种情况 // p4 存储在栈区,数组名不允许修改指向,只读 // hello world" 存储在栈区,函数结束则会被销毁,可读可写 char p4[] = "hello world"; printf("p4 = %s\n", p4); // 5. 第五种情况 // p5 存储在栈区,函数结束则会被销毁,可读可写 // "hello world" 存储在堆区,用户决定何时销毁,可读可写 char* p5 = (char *)malloc(strlen("hello world") + 1); strcpy(p5, "hello world"); printf("p5 = %s\n", p5); return 0; }
另外在定义字符串常量时,务必加上 const 修饰,这是因为标准规定字符串常量不允许修改,但是有些编译器是允许修改的,如下代码在 Borland C++ 编译器中是合法:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char* p = "hello world"; // 下面代码在 VC++ 中是不允许的,在 Borland C++ 中是允许的 p[0] = 'A'; // 为了统一字符串常量的行为,强烈要求同学们如下定义字符串常量 const char *p = "hello world"; // 下面代码无论在 VC++、Borland C++ 行为都是一样的,都禁止修改 p[0] = 'A'; return 0; }
3. 字符串操作函数
下面给出 C 字符串常用的操作函数。
- strlen(str):返回字符串 str 的长度(不包括终止符 ‘\0’)。
- strcpy(dest, src):将字符串 src 复制到 dest 中,并返回 dest。
- strncpy(dest, src, n):将字符串 src 的前 n 个字符复制到 dest 中,并返回 dest。如果 src 的长度小于 n,则剩余的字符会用 ‘\0’ 填充。
- strcat(dest, src):将字符串 src 连接到 dest 的末尾,并返回 dest。
- strncat(dest, src, n):将字符串 src 的前 n 个字符连接到 dest 的末尾,并返回 dest。如果 src 的长度小于 n,则剩余的字符会用 ‘\0’ 填充。
- strcmp(str1, str2):比较字符串 str1 和 str2 的大小。如果两个字符串相等,返回 0;如果 str1 小于 str2,返回一个负数;如果 str1 大于 str2,返回一个正数。
- strncmp(str1, str2, n):比较字符串 str1 和 str2 的前 n 个字符的大小。如果两个子字符串相等,返回 0;如果 str1 小于 str2,返回一个负数;如果 str1 大于 str2,返回一个正数。
- strchr(str, c):在字符串 str 中查找字符 c 第一次出现的位置,并返回该位置的指针。
- strrchr(str, c):在字符串 str 中查找字符 c 最后一次出现的位置,并返回该位置的指针。
- strstr(str1, str2):在字符串 str1 中查找字符串 str2 第一次出现的位置,并返回该位置的指针。
- strtok(str, delim):将字符串 str 按照分隔符 delim 进行分割,并返回第一个分割得到的子字符串的指针。