C Primer Plus(十一)

第十一章 字符串和字符串函数

11.1 字符串表示和字符串I/O

字符串是以空字符(\0)结尾的char数组。

11.1.1 初始化

一、字符串常量

字符串常量又称字符串文字,是指位于一对双引号中的任何字符。双引号里的字符会加上编译器自动提供的结束标志\0字符,作为一个字符串被存储在内存里。
如果字符串文字中间没有间隔或者间隔的是空格符,ANSI C会将其串联起来。
例如 char get[50]="How are" "you";和 char get[50]="How are you";等同
如果想在字符串中使用双引号,可以在双引号前加一个反斜线符号。
字符串常量属于静态存储类,即在一个函数中多次调用这函数,该字符串在程序的整个运行过程中只存储一份。

二、字符串数组及初始化

指定数组大小时,一定要确保数组元素数比字符串长度至少多1。未被使用的元素均被自动初始化为0。(是\0而不是数字0)
字符数组名也是数组首元素的地址。
数组初始化是从静态存储区把一个字符串复制给数组,而指针初始化只是复制字符串的地址。

三、数组和指针的差别

char heart[]=" I love Tillie!";
char *head="I love MIllie!";
主要差别在于数组名heart是个常量,而指针head是个变量。
1、两者都可以使用数组符号。
2、两者都可以使用指针加法。
3、只有指针可以使用增量运算符。
数组的元素是变量,但是数组名不是变量。
可以在声明指针的时候加上const防止更改字符串内容。

const char *mytal1[5]  char mytal2[5][81]
前者是一个指向char的指针的数组,而后者是一个char数组的数组。
前者存放5个地址,而后者存放5个完整的字符数组。

11.2 字符串输入

首先声明数组大小:例如char name[81];

gets()读取换行符之前的所有字符,在这些字符后添加一个空字符。
gets()使用一个地址将字符串赋予它,而且它返回一个指向char的指针值,如果出错或者遇到文件结尾,它就返回一个空地址。(NULL)
while(gets(name)!=NULL)      while((ch=getchar())!=EOF) 
gets()的一个不足是它不检查预留存储区是否能够容纳实际输入的数据,多出来的字符简单的溢出到相邻的内存去。

fgets()函数改进了这个问题,它让您指定最大读入字符数。
1、它需要第二个参数来书名最大读入字符数。如果这个参数值为n,则它就会读取最多n-1个字符或者读完一个换行符为止,由最先满足的条件决定。
2、如果它读取到换行符,会把她存储到字符串中,而不是像gets()那样丢弃它。
3、它还需要第三个参数来说明读哪一个文件。从键盘读取数据时,可以用stdin作为该参数。

也可以使用带有%s格式的scanf()函数来读入一个字符串。scanf()更基于获取单词而不是获取字符串。

11.3 字符串输出

puts()函数使用很简单,只需要给出字符串参数的地址。puts()现实字符串时自动在其后添加一个换行符。

fputs()函数是gets()的面向文件版本
1、fputs()需要第二个参数来说明要写的文件,可以使用stdout作为参数来进行输出显示。
2、fputs()并不为输出自动添加换行符。

也可以使用printf()函数来进行字符串的输出。

11.4 自定义字符串输入\输出函数

#include<stdio.h>
void put1(const char *string)
{
while(*string!='\0')
putchar(*string++);
}
如果熟悉的话可以将while(*string!='\0')改为while(*string)

11.5 字符串函数 

一、strlen()函数

用strlen()函数可以得到字符串的长度。

二、strcat()函数

strcat()函数接受两个字符串参数,它将第二个字符串的一份拷贝添加到第一个字符串的结尾,从而使第一个字符串成为一个新的组合字符串,第二个字符串并没有改变。
strcat()函数是char *类型,这个函数返回它的第一个参数的值。

三、strncat()函数

strcat()函数并不检查第一个数组是否能够容纳第二个字符串。strncat()函数需要另一个参数来指明最多允许添加的字符的数目,例如strncat(bugs,addon,13);直到加到13个字符或遇到空字符位置。

四、strcmp()函数

strcmp()函数用来比较字符串内容,它比较的是第一个空字符之前的部分,因此可以用来比较存放在不同大小数组里的字符串。
如果第一个字符串在字母表中的顺序先于第二个字符串,strcmp()返回一个负数,如果相同,它返回0,如果顺序后于则返回一个正数。
strcmp()是按机器编码顺序来进行比较的。

五、strncmp()函数

strncmp()比较字符串时,一直比较到找到不同的相应字符,也可以比较完由第三个参数指定的字符数。

六、strcpy()和strncpy()函数

strcpy()接受两个字符串指针参数。将第二个字符串内容复制到第一个指针指定的地址。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #define SIZE 40
  4. #define LIM 5
  5. int main(void)
  6. {
  7. char qwords[LIM][SIZE];
  8. char temp[SIZE];
  9. int i=0;
  10. while(i<LIM&&gets(temp))
  11. {
  12. if(temp[0]!='q')
  13. {
  14. printf("error!\n");
  15. }
  16. else
  17. strcpy(qwords[i++],temp);
  18. }
  19. for(i=0;i<LIM;i++)
  20. puts(qwords[i]);
  21. return 0;
  22. }

strcpy()函数还有另外两个有用的属性。首先,它是char *类型,它返回的是第一个参数的值,即一个字符的地址。其次,第一个参数不需要指向数组的开始,这样就可以只复制数组的一部分。
strncpy()需要第三个参数来指明最大可复制的字符数。

七、sprintf()函数

sprintf()函数的第一个参数是目标字符串的地址,其余的参数和printf()一样。例如:sprintf(formal,"%s,%-19s:$%6.2f\n",last,first,prize);
将输入格式化为标准形式后存放在字符串formal中。

11.6 命令行参数

  1. #include<stdio.h>
  2. int main(int argc,char *argv[])
  3. {
  4. int count;
  5. printf("The command line has %d arguments: \n",argc-1);
  6. for(count=1;count<argc;count++)
  7. printf("%d:%s\n",count,argv[count]);
  8. printf("\n");
  9. return 0;
  10. }

把这个程序编译为可执行文件repeat。 命令行 C>repeat Resistance is futile输出如下
The command has 3 arguments
1: Resistance
2: is
3: futile
main()中的两个参数,第一个参数是命令行中的字符串数,包括命令在内。第二个参数是一个指向字符串的指针数组。(argc:argument count;argv:argument value)
如果使用 repeat "I am hungry" now  则argc=3;

11.7 把字符串转换为数字

strol()、stroul()、strtod()其中strol()函数把一个字符串转换为long型值。其原型如下
long strol(const char *nptr,char **endptr,int base);

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main(int argc,char *argv[])
  4. {
  5. char number[30];
  6. char *end;
  7. long value;
  8. puts("Enter a number:");
  9. while(gets(number)&&number[0]!='\0')
  10. {
  11. value=strtol(number,&end,10);
  12. printf("value:%ld,stopped at %s(%d)\n",value,end,*end);
  13. value=strtol(number,&end,16);
  14. printf("value:%ld,stopped at %s(%d)\n",value,end,*end);
  15. }
  16. return 0;
  17. }

如果基数是10,字符串“10”就被转换为10;如果基数是16,则转为16。第一次转换在遇到空字符时结束,这样end就指向空字符。
对于输入的第二个字符串,end是‘a’字符的地址,因此,输出end显示的是字符串“atom”,输出*end显示的则是‘a’字符的ASCII码。但是,如果基值变为16,'a'字符就会被识别为一个有效的十六进制数字,函数会把十六进制数10a转换为十进制的266。

posted on 2013-06-07 18:34  颓废的悠然  阅读(431)  评论(3编辑  收藏  举报

导航