7.1 一维数组的赋值
7.1.1 memset函数
标准库函数 memset
可实现对某内存块的各字节单元整体赋同样的值。主要适合于字节型数组的整体赋值。其原型如下:
void *memset (void *s, char ch, unsigned n)
- 什么是字节型数组?初步认为是单元为char类型等占1字节的数组。如int [],每个int型占2字节,就不是字节型数组?
其功能就是将s为首地址的一片连续的n个字节内存单元都赋值为ch。
例如,
- 下面的程序是将数组str的每个数据单元赋值为’a’:
char str[10];
memset (str, 'a', 10);
- 也可对非字节型数组进行清0 。下面的程序是将数组a的每个数据单元赋值为0:
int a[10];
memset (a, 0, 10*sizeof(int));
7.1.2 memcpy函数
对于两个数据类型和大小都相同的数组,如果将其中一个数组各单元的值要赋值给另一个数组的各数据单元,可以用 memcpy
库函数。其原型如下:
void *memcpy (void *d, void *s, unsigned n);
其功能就是将s为首地址的一片连续的n个字节内存单元的值拷贝到以d为首地址的一片连续的内存单元中。
在使用memset和memcpy函数时,源程序中要包含头文件”string.h”。VC下也可用”memory.h”。
7.2 字符串与数组
7.2.1 字符串的本质
- 字符串常量:用双引号括起来的一组字符。
- 字符串:本质为一种字符型数组,且数组的最后一位为
'\0'
。该字符作标识字符串的结束。 - 注意,
char str[3] = {'a', 'b', 'c'};
这是错的!str不能作为字符串使用,因为没有地方存储\0
char str[] = {"abcdef"};
这种声明方式也是正确的。- 字符串常量只能在定义字符数组变量时赋值给字符数组变量,而不能将一个字符串常量直接赋值给字符数组变量。 ```c char str[] = “china”; //数组大小为6 //等价于 char str[] = {‘c’,’h’,’i’,’n’,’a’,’\0’}; //数组大小为6 //也等价于 char str[] = {“china”}; //数组大小为6
char str[] = {‘c’,’h’,’i’,’n’,’a’}; //数组大小为5,但不是字符串!(没有\0)
//也可以如下赋值 char str[10] = “china”; //数组大小为10 //等价于 char str[10] = {‘c’,’h’,’i’,’n’,’a’}; //数组大小为10,未指定的单元为0
char str[10], *s=str; str = “china”; //错误的 s=”china”; //正确的
<a name="T29Xt"></a>
### 7.2.2 字符及字符串操作的常用函数
<a name="Upvsl"></a>
#### 1. gets()、puts()
包含在头文件<stdio.h><br />`gets(字符数组变量名);`
- 将输入字符存放在字符数组中,**直到遇到回车符返回,可以接收空格**。 `'\n'` 不会被存储,而是转换为 `'\0'` 存储。
`puts(字符串首地址);`
- 输出时将末尾的 `'\0'` 转换为 `'\n'` 输出。该函数无法进行格式控制。
<a name="wEUYS"></a>
#### 2. scanf()、printf()
```c
char str[80];
scanf("%s",str); //不可写成&str,因为str本身就是地址
char str1[40],str2[40];
scanf("%s%s",str1,str2);
char str3[10];
scanf("%9s",str3);
- 任何时候都会忽略前导空格,即字符串开头的空格不会被存入字符数组。
- 遇到空格符或回车符就停止输入操作。因此在连续输入多个字符串时,用空格隔开。
- scanf会自动在字符串后面加
'\0'
。因此为避免输入字符串过长,可以通过%ns
控制输入长度,如例3中%9s
就只能输入9个字符,剩下的一个存放'\0'
。 ```c char name[]=”john smith”; printf(“the name is:%s\n”,name); //name等价于(可替换为)&name[0],即从数组的首地址开始输出,直到’\0’。’\0’不会被输出 printf(“last name is:%s\n”,&name[5]); //输出name中第6个单元开始的字符串
printf(“%8s”,”john”); //%ns可以指定字符串显示的宽度。若字符串长度不够,则填充空格,若长度大于n,则全部显示 ```
3. strlen()
求字符串长度的库函数是strlen,其调用的格式为strlen(字符串的地址);
- 返回字符串中包含的字符个数,即字符串的长度,不包含’\0’。
4. strcpy()、strncpy()
字符串的复制。包含在头文件strcpy(字符数组1,字符串2);
- 将字符串2复制到字符数组1中去。(包含字符串结尾符’\0’)
- 第一个参数必须是一个字符数组变量,第二个参数可以是一个包含字符串的字符数组变量,也可以是一个字符串常量。
- 字符数组1的大小必须足够大以便能容纳字符串中所有字符,包括‘\0’。
strncpy(字符数组1,字符串2,长度n);
- 将字符串2的前n个字符复制到字符数组1中去,并在末尾加’\0’。即字符串的部分复制。
- 当n>=strlen(字符串2)时,strncpy等价于strcpy。
5. strcmp()、stricmp/strcmpi()、strncmp()、strnicmp()
字符串的比较不能通过>,<,==来进行,必须通过上述等库函数进行。包含在头文件strcmp(字符串1,字符串2);
- 若字符串1>字符串2,则返回一个正整数;若小于则返回一个负整数;若相等则返回0。
- 比较规则:逐个字符比较ASCII码大小,直到遇到不同的字符或’\0’为止。若全部字符相同,则相等;如果出现不同的字符,则以第一个不相同的字符的比较结果为准。
stricmp()/strcmpi()与strcmp()相同,只不过前者在比较时忽略字母的大小写。i可看做是ignore(忽略)的缩写。
strncmp(字符串1,字符串2,长度n);
- 将字符串1的前n个字符的子串与字符串2的前n个字符的子串进行比较,返回值及比较规则同strcmp。
- 当n>=其中某字符串长度时,strncmp等价于strcmp。
strnicmp()调用格式与strncmp()相同,但不区分大小写。注意:不同于stricmp(),不存在strncmpi(),即 i 不能写在末尾。
6. strcat()
如果想要将两个字符串连接起来构成新的字符串,可以调用strcat函数。strcat(字符数组1,字符串2);
- 将字符串2连接到字符数组1的后面(包括结尾符’\0’)。
- 连接后,字符串2没变,但字符串1的字符会增加,因此同上,字符串1的数组长度应该足够大,保证可以存储连接以后的所有字符。
7. 其他常用的字符和字符串处理库函数
函数用法 | 函数功能 | 头文件 |
---|---|---|
strset(字符数组,字符) | 将字符数组中所有字符设置为指定字符 | string.h |
strlwr(字符数组) | 所有字符变小写 | string.h |
strupr(字符数组) | 所有字符变大写 | string.h |
toupper(字符) | 字符变大写 | ctype.h |
tolower(字符) | 字符变小写 | ctype.h |
atoi(字符串) | 字符串变整型(i就是int) | stdlib.h |
atol(字符串) | 字符串变长整型 | stdlib.h |
atof(字符串) | 字符串变浮点数 | stdlib.h |
ultoa(无符号长整数,字符数组,进制) | 将无符号长整数(ul)转换成指定的进制数并以字符串的形式存放到字符数组中 | stdlib.h |
7.3 字符串数组
构成数组的数据为字符串时,这个数组就是字符串数组。其实质为字符型的二维数组,每一行的所有字符元素(一个字符数组)构成一个字符串。char 字符串数组名[行数m][列数n] = {字符串1,字符串2,...,字符串m};
- 每个字符串的长度应小于n-1,因为结尾符
'\0'
占用一个单元。 - 字符串多余空位补0。注意,这个0是补在结尾符
'\0'
后面的。