C语言简明教程(十三):字符串和字符串处理函数实例详解

接上一节:数组和指针完整实例详解

字符串在C语言中是常用的数据对象,却又是一个特殊的存在,本身并没有字符串类型,C语言的字符串实质是一个字符数组,它由一个个字符和结尾的空字符’\0’组成,另外字符串又和指针密切相关,字符数组名就是字符串的首地址。本文主要详细介绍C语言字符串的表示方式、字符串输入输出以及字符串相关的处理函数。

一、字符串声明

首先介绍一下字符串字面量,例如1或2就是数字字面量,像number或count这些是变量,字符串字面量就是用双括号括起来的内容,例如“string”或“name”,字符串字面量属于静态存储类别,存储在静态内存区,字面量为const数据,其值可读不可写,使用双括号的字符串实质表示的是该字符串的首地址,也就是说”string”是该字符串的首地址。一个固定的字符串,它在静态内存区,在程序的任何地方取该字符串的地址都是相同的,看如下代码以及相应的图解:

// "hello"字符串字面量存储在静态区,其地址固定
char str_01[20] = "hello";
char *str_02 = "hello";
printf("str_01 address: %p\n", str_01); // 输出:0028FE98
printf("str_02 address: %p\n", str_02); // 输出:0040630C
printf("hello address: %p\n", "hello"); // 输出: 0040630C
printf("%d\n", str_02 == "hello"); // 输出:1
C语言字符串字面量和静态内存区

1、数组方式表示字符串

数组方式表示字符串形如:char
message[10] = “message‘,首先”message”是一个字符串字面量,保存在内存静态区中,是一个const数据,声明一个字符数组message,将字符串字面量”message”复制给栈区中的message数组变量,数组的长度至少比字符串长度多1。

所以这种方式是对原始字面量字符串的复制,其指针不能更改,也可以使用一个字符数组的形式,但是要在末尾加上一个空字符,在声明字符串中初始化可以略去[count]中的count让编译器自动计算大小。因为是对原始字符串的复制,所以相对于下面的指针方式效率不高,但是如果需要修改字符串则可以使用此方式,具体实例代码如下:

// 使用数组表示字符串
    char str_01[4] = {'a', 'r', 'm', '\0'}; // 使用字符数组的形式
    char str[10] = "arm"; // 将静态内存区中的"arm"复制给str
//    str++; // 数组方式的字符串不能更改字符串地址
    char msg[] = "hello"; // 略去数组大小,让编译器自动计算字符串长度
    puts(str_01);
    puts(str);
    printf("%p\n", str);
    printf("%p\n", "arm");
    printf("%p\n", msg);

2、指针方式表示字符串

指针方式和数组方式的区别就是,数组方式拷贝的是原始字符串字面量,而指针方式拷贝的是原始字符串的地址,所以使用指针方式相当于直接指向了静态区中的字符串,例如char *msg = ”msg“,指针msg指向的是原始字符串,因为msg是一个字符指针,所以它可以被重新赋值,具体代码如下:

// 使用指针方式表示字符串
    char str_01[20] = "hello"; // 数组方式
    char *str_02 = "hello";
    char *msg = "200";
//    str_02 = msg; // 字符指针msg可以被重新赋值
//    str_01 = msg; // 但是数组形式的不可以
    printf("str_01: %p\n", str_01); // 输出:0028FE94
    printf("str_02: %p\n", str_02); // 输出:0040630C
    printf("\"hello\": %p\n", "hello"); // 输出:0040630C,和str_02字符指针的地址相同,字符指针直接指向原始字符串

那么字符串数组中char
*msg[]和char [][]又有什么区别?和上面提到的数组方式和指针方式的一样,前者直接指向原字符串字面量,后者复制原字符串。

二、字符串输入输出函数

字符串输入输出函数如下:

1、getchar和putchar:自定义字符串输入输出可以使用getchar和putchar函数,这两个函数在前几节中已经介绍过。

2、scanf和printf:格式化输入输出,前几节已详细介绍。

3、gets和puts函数:其中gets函数读取所有输入直到换行符,会将换行符丢弃读入,字符串过长会导致缓冲区溢出,puts函数添加换行符输出。

4、gets_s函数,C11标准添加的函数,用于替换gets函数,仅从标准输入中读取数据,字符串过长丢弃超出字符串,丢弃换行符。

5、fgets和fputs,fgets读取所有字符,不会丢弃换行符。

其中要注意,接受字符串输入的变量需要已经分配空间,只有已经分配空间才能接受字符串,例如char *msg和char [],前者并未分配字符串空间,仅仅分配一个地址空间,后者已经分配空间。

函数的具体使用示例如下:

// 1、使用getchar和putchar
int ch;
ch = getchar();
putchar(ch);
putchar('\n');

// 2、使用scanf和printf
char message[20]; // message需要已经分配字符空间,使用char*message可以结合malloc
scanf("%s", message);
printf("%s\n", message);

// 3、使用gets和puts
char str[20];
gets(str);
puts(str); // 添加换行符输出

// 4、使用fgets和fputs
char *msg = (char*)malloc(sizeof(char) * 20);
fgets(msg, 20, stdin);
fputs(msg, stdout);

// 5、使用gets_s和puts
char title[20];
gets_s(title, 20); // C11的可选函数
puts(title);

三、字符串处理函数

对于字符串处理函数,最重要的是对前面内容的理解,否则有些函数可能不知道怎么用,在这些函数中,一些参数是const修饰的表明字符串不可更改,例如strcpy函数则是允许修改字符串,而对数组或字符串的处理函数的设计,一般至少需要一个字符串或数组,然后需要设计一个长度参数,因为根据一个数组参数还不能计算得到数组的长度,例如这种形式的数组char *str,所以在使用C语言函数也要习惯一下C这种风格,这处理函数的头文件在stdlib.h和string.h中。

1、基本字符串处理函数

(1) sprintf格式化打印字符串,这个函数可以将其它类型的数据转换成字符串,是一个很有用的函数。

(2) strlen,获取字符串长度。

(3)strcat,字符串连接

(4) strcmp,比较字符串

(5)strncmp,比较字符串前n个字符

(6) strcpy,复制字符串

(7)strncpy,复制前n个字符

(8)strchr,查找字符,返回第一个出现字符的位置。

2、字符串转换函数

(1) atof,将字符串转为float。

(2) atoi,将字符串转为int。

(3) atol,将字符串转为long。

(4) strtod,将字符串转为double,base参数表示进制,例如2进制、10进制、16进制。 另外,在ctype.h头文件中有相关的字符测试函数,例如isalpha,isalnum等,具体的函数使用说明可以参考Linux C函数参考文档:

(Linux C函数参考文档CHM下载:

链接:
https://pan.baidu.com/s/16cqfnSMiRNBn5peRpiqwMw

提取码: r72s

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?