• 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。

  • 相关阅读:
    Homebrew 更改国内阿里源
    Java数组以及内存分配
    Django-Scrapy生成后端json接口
    MySQL必知必会(1-12章)
    招聘网站爬虫模板
    ubuntu之jupyter notebook配置
    服务器基本配置(ubuntu)
    Typora+PicGo+码云Gitee搭建本地博客环境
    redis缓存雪崩,穿透,击穿。整理篇
    鼠标修复升级记录(下)
  • 原文地址:https://www.cnblogs.com/tuifeideyouran/p/3124929.html
Copyright © 2020-2023  润新知