zoukankan      html  css  js  c++  java
  • C语言风格字符串的概念、定义、输入字符串、输出字符串

    字符串: C语言中最有用、最重要的数据类型之一。

    字符串:是以字符结尾的char类型数组。所以可以把数组和指针知识应用于字符串。

    如何在程序定义字符串:

    1、字符串字面量

    用双引号括起来的内容称为字符串字面量,也叫作字符串常量。双引号中的字符和编译器自动加入末尾的字符,都作为字符串储存在内存中。

    如果要在字符串内部使用引号,必须要在双引号前面加上一个反斜杠(

    字符串字面量被视为const,就不能更改了。

    字符串常量属于静态存储类别。这说明如果在函数中使用字符串常量,该字符串只会被储存一次,在整个程序的生命期内存在,即使函数被调用多次。用双引号括起来的内容被视为指向该字符串储存位置的指针。

    2、字符串数组和初始化

    定义字符串数组时,必须让编译器知道需要多少空间,一种方法是足够空间的数组储存字符串。

    指定数组大小的时候,必须确保数组的元素个数至少比字符串长度多1

    省略数组初始化声明中的大小,编译器会自动计算数组的大小;

     

    数组表示法_创建字符串:char words[MAXLENGTH]=“I am a string in an array.”

    指针表示法_创建字符串:char * pt1 = “Something is pointing at me.”

    3数组和指针

    数组表示法_创建字符串:char words[MAXLENGTH]=“I am a string in an array.”

                  这种表示法,字符串字面量被存储在静态存储区。数组只有在运行时才会被分配内存。此时,才将字符串拷贝到数组中。此时字符串有两个副本,一个是在静态内存中的字符串字母量,另一个是储存在words数组中的字符串。

           指针表示法_创建字符串:char * pt1 = “Something is pointing at me.”

                  编译器为字符串在静态存储区预留了29个元素的空间。一旦开始运行程序,它就会为指针变量pt1留出一个储存位置,并把字符串的地址储存在指针变量中。

    4数组和指针的区别

           char heart[] = “I love Tillie!”;  ->数组名heart是常量;

           const char *head = “I love Millie!”; ->指针名是head变量;

           head =heart ->可以;

           heart =head –>不可以,非法构造,赋值运算符左边必须是变量

    5、字符串数组

           const char *mytalents[LIM]={

        "Adding number swiftly",

        "Multiplying accurately",

        "Stashing data",

        "Following instructions to the letter",

        "Understanding the C language"

    };

     

        char yourtalents[LIM][SLEN]={

        "Walking in a straight line",

        "Sleeping","Watching television",

        "Mailing letters","Reading email"

    };

     

    字符串数组分配内存的使用率低。因为数组中储存着字符串字面量的副本。每个字符串都被储存了两次。

     

    如果要使用数组表示待显示的字符串,建议使用指针数组。指针数组也有缺陷,就是字符串字面量不能更改。如果要改变或者为字符串输入预留空间,不要使用指向字符串字面量的指针。

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++

    字符串的输入:

    想把字符串读入程序,首先必须预留储存该字符串的空间。然后用输入函数获取该字符串。

    如何分配空间:

      要做的第1件事就是分配空间。以储存稍后读入的字符串。意味着必须为字符串分配足够的空间。不能指望计算机在读取字符串时顺便计算它的长度。

           char *name;

           scanf(“%s”,name);

           name是未初始化的指针,name可能指向任何地方。所以可能会擦写掉程序中的数据或代码,从而导致程序异常中止。

     

           最简单的办法:在声明时显式指明数组的大小。

           char name[81];

     

           现在name是一个已分配块(81字节)的地址。还有一种办法就是使用C库函数来分配内存。

           

      空字符:

          用于标记C字符串末尾的字符;对应的字符ASCII编码是0;

      空指针:

    有一个值,该值不会与任何有效的地址对应。

      本质上讲空字符是整数类型,占1个字节;

      空指针是指针类型,是一个地址,占4个字节。

      丢弃输入行中余下的字符,是因为,输入行中多出来的字符会被留在缓冲区中。成为下一次读取语句的输入。

      

      1、gets() 函数    这个函数不安全,被摒弃了

      scanf()和转换说明%s只能读取一个单词,可是在程序中经常要读取一整行输入,而不仅仅是一个单词。

    很久前gets()就用于处理这种情况。gets()函数简单易用,它读取整行输入,直至遇到换行符。

    gets()函数有个问题,无法检查数组是否装得下行。数组名会被转换成数组首元素的地址。get()函数只知道数组的开始处,并不知道数组中有多少个元素。

    如果输入字符串过长,会导致缓冲区溢出(buffer overflow)。多余的字符超出了指定的目标空间。如果这些多余的字符只是占用了尚未使用的内存,就不会立即出现问题。但是一旦擦写掉程序中的其他数据,就会导致程序异常中止。

    C99标准建议不要使用get()函数,甚至被C11标准摒弃了。

      

      2、fgets()函数

      函数原型:char *fgets(char *buf, int bufsize, FILE *stream);  ---->从指定的文件读取一个字符串

    buf 字符型指针,指向存储读入数据的缓冲区的地址;---->存到哪

    n 从流中读入n-1个字符;--->读多少个

    stream 指向读取的流;   --->从哪读                                                                                  

    会在读入的最后一个字符后加上串结束标志''

    返回值:读取失败或读到文件结尾返回NULL;输入成功时,返回 char 型指针,指向读入的字符串内容,含换行键;

      为什么会有换行符问题:因为输入时会敲回车嘛,就产生换行符。函数会把换行符一并存储起来。(读一行字符串的范畴)

      fgets()会存储换行符,有好处也有坏处。好处就是:检查末尾有没有换行符就知道是否读取了一整行。坏处就是:你可能并不想把换行符储存在字符串中,这样的换行符会带来一些麻烦。

      如何处理掉换行符:在已经储存的字符串中查找换行符,将其替换成空字符

    while (words[i] != ‘ ’)

    i++;

    words[i]=’’;

      

      3、gets_s()函数

      函数原型: gets_s(words,STLEN);

            只从标准输入中读取数据,不需要第3个参数;

            如果读到换行符,会丢弃它,而不是储存它;(不存换行符)

            如果读到最大STLEN字符数的话,.....很复杂;

            没有fgets()函数灵活,易用;不建议用;

     

      4、s_gets()函数

    函数实现如下:

     1 char * s_gets(char * st, int n)
     2 {
     3     char * ret_val;
     4     int i=0;
     5 
     6     ret_val = fgets(st, n, stdin); //读取成功,返回一个指针,指向输入字符串的首字符;
     7     if(ret_val)
     8     {
     9         while(st[i]!='
    ' && st[i]!='')
    10             i++;
    11         if(st[i] =='
    ') //fgets会把换行符也吃进来了,fgets会在末尾自动加上;
    12             st[i]='';
    13         else   //其实是''
    14             while(getchar() != '
    ')  //会把缓冲区后续的字符都清空
    15                 continue;
    16     }
    17     return ret_val;
    18 }

    特性:1、会吃进换行符,但是会将其替换成空字符;2、会把后续的缓冲区内容都清空,为的是不干扰下次输入;

     

      5、scanf()函数

      函数原型:int scanf(const char * restrict format,...);

      返回一个整数值:该值等于sanf()成功读取的项数或EOF(文件结尾)。文件结尾不存在于文件中,而仅仅是一种标志,流的状态的标志。

    scanf("%d %d",&a,&b);
    函数返回值为int型。如果a和b都被成功读入,那么scanf的返回值就是2;
    如果只有a被成功读入,返回值为1;
    如果a和b都未被成功读入,返回值为0;
    如果遇到错误或遇到end of file,返回值为EOF。end of file为Ctrl+z 或者Ctrl+d。

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++

    字符串的输出:

    1、puts()函数

    自动在字符串末尾加上换行符,

    函数只用来输出字符串,没有格式控制,里面的参数可以直接是字符串或者是存放字符串的字符数组名。

    2、fputs()函数

    int fputs(const char *str, FILE *stream); ---->向指定的文件写入一个字符串;

    str  这是一个数组;

    stream 指向FILE对象的指针,该FILE对象标识了要被写入字符串的流。

    3、printf()函数

    函数的输出格式很多,可以根据不同格式加转义字符,达到格式化输出。

  • 相关阅读:
    嵌入式设备之web服务器
    动环监控的设备架构设计
    墓碑机制
    淘宝APP消息推送模型
    Service Mesh架构的持续演进 单体模块化 SOA 微服务 Service Mesh
    网关架构演进之路
    理解了云原生,才能正确迎接云时代的到来 | 技术前沿 百度智能云 2019-09-10
    策略模式 VS 状态模式
    权限管理机制支持多种访问控制模型。
    二维码生成服务架构的演进与思考
  • 原文地址:https://www.cnblogs.com/grooovvve/p/9938322.html
Copyright © 2011-2022 走看看