C语言字符串使用指南

写在前面:学习的第一门语言是Java,之前对C也了解一点,也只是了解一点,在加上长时间没有接触了,基本就只会一个Hello World了。现在由于准备升本考试,不得不从头开始学C。这里从零开始,记录C语言学习点滴。欢迎正在学习C语言的小伙伴一起学习,未来可期,一起加油!

在C语言里边是没有字符串数据类型的,但在平时开发中肯定是少不了字符串操作的。因为字符串都是有字符组成的,所以在C语言中字符串是通过一维字符数组来实现的。

字符串

字符串常量就是用一对双引号括起来的字符序列,即一串字符,它有一个结束标志’ \0 '。例如,字符串 “happy” 有6字符组成,分别为 ’ h ‘、’ a ‘、’ p ‘、’ p ‘、’ y ’ 和 ’ \0 ‘,其中5个是字符串的有效字符,’ \0 ’ 是字符串结束符。

字符串的有效长度就是有效字符的个数,例如,“happy”的有效长度是5。

字符串的存储——数组初始化

字符串可以放在一维字符数组中。例如:

static char s[6] = { 'h', 'a', 'p', 'p', 'y', '\0' };

数组 s 中存放了字符串“happy”。

字符数组的初始化还可以使用字符串常量,上述初始化等价于:

static char s[6] = { "happy" };
或
static char s[6] = "happy";

将字符串存入字符数组时,由于它有一个结束符’ \0 ',数组长度至少是字符串的有效长度+1。例如,字符串“happy”的有效长度为5,存储它的数组的长度至少应为6。

如果数组长度大于字符串的有效长度+1,则数组中除了存入的字符串,还有其他内容,即字符串只占用了数组的一部分。例如:

char str[90] = "happy“;

上述代码只对数组的前6个元素(str[0] ~ str[5])赋初值,其他元素的值不确定。但这并不会影响对字符串“happy”的处理,由于字符串遇‘ \0 ’结束,所以,数组中第一个’ \0 ’ 前面的所有字符和第一个’ \0 ’ 一起构成了字符串“happy”,也就是说,第一个‘ \0 ’之后的其他数组与该字符串无关。

字符串由有效字符和字符串结束符’ \0 '组成。

字符串的存储——赋值和输入

将字符串存入数组,除了上面介绍的初始化数组,还可以采用赋值和输入的方法。例如:

static char s[80];
s[0] = 'a';
s[1] = '\0';

采用赋值的方法将字符串 “a” 存入数组s。它等价于:

static char s[80] = "a";

区分 “a” 和 ‘a’,前者是字符串常量,包括 ‘a’ 和 ‘\0’ 两个字符,用一维字符数组存放;后者是字符常量,只有一个字符,可以赋给字符变量。

输入的情况有些特殊,由于字符串结束符 ‘\0’ 代表空操作,无法输入,因此,输入字符串时,需要事先设定一个输入结束符。一旦输入它,就表示字符串输入结束,并将输入结束符转换为字符串结束符 ‘\0’。例如:

#include

//定义输出函数
void pin(char str[]);

int main(){
    int i = 0;
    //定义字符数组
    char str[80] = "a";

    //输出字符串
    pin(str);

    //输入字符串,重新赋值,输入回车结束
    while((str[i] = getchar()) != '\n'){
        i++;
    }
    str[i] = '\0';  //将结束符'\0'存入数组

    //输出新字符串
    pin(str);

    return 0;
}

//输出字符串函数
void pin(char str[]){
    int i;
    for(i = 0; str[i] != '\0'; i++){    //当字符为'\0'时字符串结束
        printf("%c", str[i]);
    }
    printf("\n");
}

先定义一个字符数组赋值为“a”,调用输出函数输出字符串“a”,之后在输入一个新的字符串到字符数组中,回车结束输入,调用输出函数,输出新的字符串。运行结果如下:
C语言字符串使用指南_第1张图片

常用的字符串处理函数

在使用字符串处理函数之前,需要引入stdio.h和string.h头文件。

1、字符串的输入和输出

函数输入和输出最常见的就是scanf()和printf()。除此之外字符串还可以用gets()和puts()函数输入输出。

1、scanf(格式控制字符串, 输入参数)
格式控制字符串中使用格式控制说明%s,输入参数必须是字符型数组名。改该函数遇回车或空格输入结束,并自动将输入的数据和字符串结束符 ‘\0’ 存入数组中。例如:

scanf("%s", s);		//s为字符型数组

2、printf(格式控制字符串,输出参数表)
格式控制字符串中相应的格式控制说明用%s,输出参数可以是字符数组名或字符串常量。输出 ‘\0’ 结束。例如:

printf("%s", s);

由于在C语言中是使用一维字符数组存放字符串的,因此可以在字符串操作函数中直接使用数组名进行输入与输出。

3、字符串输入函数gets(s)
参数s是字符数组名。函数从输入得到一个字符串,输入回车结束,自动输入的数据和 ‘\0’ 送入数组中。采用函数gets()输入的字符串允许带空格
实际上函数gets()有返回值,如果输入成功则返回值是字符串第一个字符的地址,如果输入失败则返回NULL。但一般情况下使用gets()主要是为了输入字符串,并不会关心它的返回值。

4、字符串输出函数puts(s)
参数s可以是字符数组名或字符串常量。输出时遇’\0’自动将其转换为’\n’,即输出字符串后换行。同样函数puts()也有返回值,如果成功执行了输出字符串的操作,则返回换行符号’\n’,否则返回EOF。

scanf和printf函数输入与输出案例:

#include

int main(){
    //定义一个字符数组
    char str[80];

    scanf("%s", str);
    printf("%s", str);
    printf("hello");
    
    return 0;
}

运行结果如下:
C语言字符串使用指南_第2张图片
printf()函数输出遇 ‘\0’ 结束。但不会自动将其转换为’\n’。所以不会换行。

scanf和printf函数输入与输出案例:

#include

int main(){
    //定义一个字符数组
    char str[80];

    gets(str);
    puts(str);
    puts("Hello");

    return 0;
}

运行结果如下:
C语言字符串使用指南_第3张图片
puts()函数输出时遇 ‘\0’ 自动将其转换为 ‘\n’,即输出字符串后换行。

字符串的复制、连接和比较及字符串的长度

字符串复制、连接、和比较以及计算字符串长度的函数,在系统头文件string.h中定义。所以在使用之前,需要先引入string.h头文件。

1、字符串复制函数 char *strcpy(char *s1, char *s2)
该函数把字符串s2复制到s1,直到遇到s2中 ‘\0’ 为止。s1要有足够的空间容纳s2,且s1中的内容被覆盖,函数返回s1。同样可以简化以上函数的表达形式为:strcpy(s1, s2);

参数s1必须是字符型数组基地址,参数2可以是字符数组名或字符串常量。 例如:

int i;
char str1[80], str2[80], from[80] = "happy";		/* 初始化数组from */
strcpy(str1, from);
strcpy(str2, "key");

上述代码中,第三条语句调用了函数strcpy()把from中的字符串复制给str1; 第四条语句把字符串常量“key”复制给str2后,数组str1中存放了“happy”,数组str2中存放了“key”。

2、字符串连接函数strcat(s1, s2)
参数s1必须是字符数组基地址,参数s2可以是字符数组名或字符串常量。 strcat()函数将字符串s2接到字符串s1的后面,此时,s1中原有的结束符 ‘\0’ 被放置在连接后的结束位置上。数组s1的长度要足够大,以便存放连接后的新字符串。例如:

char str1[80] = "hello ", str2[80], t[80] = "world";
strcat(str1, t);
strcpy(str2, str1);
strcat(str2, "!");

先调用函数strcat()连接str1和t,结果放在str1中。如下图:
C语言字符串使用指南_第4张图片
在调用函数strcpy()将str1中的字符串赋给str2,最后调用函数strcat()连接str2和字符串常量 “!” 后,str2中存放了“Hello world!”。

C语言中不允许使用算术运算符加将字符串数组直接连接。即str1 = str1 + t是错误的。

3、字符串比较函数strcmp(s1, s2)
和函数strcpy()中对参数的要求不同,函数strcmp()中的参数s1和s2可以是字符数组名或字符串常量。函数strcmp()返回一个整数,给出字符串s1和s2的比较结果:

  1. 若s1和s2相等,返回0。
  2. 若s1大于s2,返回一个正数。
  3. 若s1小于s2,返回一个负数。

设str1和str2都是字符串,在C语言中,str1 == str2、str1 > str2 和 str1 <= str2比较的是两个字符串的起始地址,而strcmp(str1, str2) == 0、strcmp(str1, str2) > 0 和 strcmp(str1, str2) <= 0 比较两个字符串的内容。

字符串比较的规则是:从两个字符串的首字符开始,依次比较相对应的字符(比较字符的ASCII码),直接出现不同的字符或遇 ‘\0’ 为止。如果所有的字符都相同,返回0;否则,以第一个不相同字符的比较结果为准,返回这两个字符的差,即第一个字符串中的字符减去第二个字符串中的字符得到的差。例如:

strcmp("sea", "sea");   //值为0,说明“sea”, "sea"相等
strcmp("compute", "compare");  //值为('u' - 'a')是个正数,说明"compute"大于"compare"。
strcmp("happy", "z")   //值为('h' - 'z')是个负数,说明"happy"小于"z"。
strcmp("sea", "seat")  //值为('\0' - 't')是个负数,说明“sea”小于“seat”。

4、字符串长度函数strlen(s1)
参数s1可以是字符数组名或字符串常量。函数strlen()返回字符串s1的‘\0’之前的字符个数。即字符串有效字符的个数(不包括字符结束符’\0’)。

例如:strlen(“happy”)的值是5,strlen(“A”)的值是1。

字符串和字符指针

上面字符串都是以一维字符数组实现的。除了字符数组还可以使用字符型指针去接收字符串常量值。

如果定义一个字符指针接收字符串常量的值,该指针就指向字符串的首字符。这样,字符数组和字符指针都可以用来处理字符串。例如:

char sa[] = "array";
char *sp = "point";
printf("%s ", sa);	/* 数组名sa作为输出参数 */
printf("%s ", sp);	/* 字符指针sp作为输出的参数 */
printf("%s\n", "string"); 	/* 字符串常量作为输出的参数 */

运行结果如下:
C语言字符串使用指南_第5张图片
调用printf()函数,以%s的格式输出字符串时,作为输出参数,数组名sa,指针sp和字符串“string”的值都是地址(起始地址),从该地址所指定的单元开始连续输出其中的内容,直到遇到 ‘\0’ 结束。因此,字符串中其他字符的地址也能作为输出参数。例如:

printf("%s ", sa+2);	/* 数组元素sa[2]的地址作为输出参数 */
printf("%s ", sp+3); 	/* sp+3作为起始地址 */
printf("%s\n", "string" + 1);

运行结果如下:
C语言字符串使用指南_第6张图片
字符数组与字符指针都可以处理字符串,但两者之间还是有区别的。例如:

char sa[] = "This is a string";
char *sp = "This is a string";

字符数组sa在内存中占用了一块连续的单元,有确定的地址,每个数组元素放字符串的一个字符,字符串就存放在数组中。字符指针sp只占用一个可以存放地址的内存单元,存储字符串首字符的地址,而不是将字符串放到字符指针变量中去。如图:
C语言字符串使用指南_第7张图片
如果需要改变数组sa所代表的字符串,只能改变数组元素的内容。如果要改变指针sp所代表的字符串,通常直接改变指针的值,让它指向新的字符串。因为sp是指针变量,它的值可以改变,指向其他单元。例如:

strcpy(sa, "Hello");
sp = "Hello";

分别改变了sa和sp所表示的字符串。而sa = “Hello”; 是错误的,因为数组名是常量,不能对它赋值。

定义字符指针后,如果没有对它赋值,指针的值是不确定的,不能明确它指向的内存单元。因此,如果引用未赋值的指针,对指针指向的单元赋值会出现问题。例如:

char *s;
scanf("%s", s);

没有对指针s赋值,却对s指向的单元赋值。如果该单元已分配给其他变量,其值就改变了。

char *s, str[20];
s = str;
scanf("%s", s);

上述定义是正确的。数组str有确定的存储单元,s指向数组str的首元素,并对数组赋值。

为了尽量避免引用未赋值的指针所造成的错误,在定义指针时,可以先将它的初值置为空,如char *s = NULL。


由于初学C语言,上述内容如有错误地方,恳请各位大佬指出!

你可能感兴趣的:(C语言基础系列,编程语言,c语言)