7.1 一维数组的赋值

7.1.1 memset函数

标准库函数 memset 可实现对某内存块的各字节单元整体赋同样的值。主要适合于字节型数组的整体赋值。其原型如下:

  • void *memset (void *s, char ch, unsigned n)
  • 什么是字节型数组?初步认为是单元为char类型等占1字节的数组。如int [],每个int型占2字节,就不是字节型数组?

其功能就是将s为首地址的一片连续的n个字节内存单元都赋值为ch。
例如,

  1. 下面的程序是将数组str的每个数据单元赋值为’a’:

char str[10];
memset (str, 'a', 10);

  1. 也可对非字节型数组进行清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”; //正确的

  1. <a name="T29Xt"></a>
  2. ### 7.2.2 字符及字符串操作的常用函数
  3. <a name="Upvsl"></a>
  4. #### 1. gets()、puts()
  5. 包含在头文件<stdio.h><br />`gets(字符数组变量名);`
  6. - 将输入字符存放在字符数组中,**直到遇到回车符返回,可以接收空格**。 `'\n'` 不会被存储,而是转换为 `'\0'` 存储。
  7. `puts(字符串首地址);`
  8. - 输出时将末尾的 `'\0'` 转换为 `'\n'` 输出。该函数无法进行格式控制。
  9. <a name="wEUYS"></a>
  10. #### 2. scanf()、printf()
  11. ```c
  12. char str[80];
  13. scanf("%s",str); //不可写成&str,因为str本身就是地址
  14. char str1[40],str2[40];
  15. scanf("%s%s",str1,str2);
  16. char str3[10];
  17. 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' 后面的。