Jialong's Blog

Do things I love, and seek happiness.

0%

字符串输入、输出和字符串函数

一、字符串输入

1.gets()函数

  • 使用方法:读取整行输入,直到遇到换行符,然后丢弃换行符,储存其余的字符,并在字符末尾添加一个空字符使之成为一个C字符串。
  • 使用中存在的问题:gets(words)(char words[STLEN])的唯一参数为words,该函数无法检查数组是否装得下输入行。数组名会被转化成该数组首元素的地址,该函数只知道数组的开始处,并不知道数组在何处结束。
  • 如果输入过长,会导致缓存区溢出,详情见书上内容。

2.gets()的替代品:fgets()函数

  • fgets()函数通过第二个参数来限制读入的字符数来解决溢出问题。
  • 相较于gets()的区别:
    • 第二个参数指明了读入字符的最大数量,若该值为n,那么将读入n-1个字符,或遇到第一个换行符为止。
    • 第三个参数指明了要读入的文件,如果要从键盘输入,则参数设置为stdin标识符。
    • 如果读到一个换行符,fgets()会将其储存在数组中,而不是将其丢弃。

3.gets_s()函数

  • fgets()的区别

    • 该函数只从标准输入中读取,所以无需第三个参数。

    • 读到换行符会将其丢弃

    • 如果读到最大字符数都没有读到换行符,会进行以下操作:

      首先设置目标数组的首字符为空字符

      读取并丢弃随后的输入直至读到换行符或文件结尾

      返回空指针

      然后调用依赖实现的“处理函数”

4.s_gets()函数

  • 读取整行输入并用空字符替代换行符,或者(在字符串未结束就遇到了空字符)读取一部分输入,并丢弃其余的部分。

该函数的代码:

char * s_gets(char * st, int n)
{
    char *ret_val;
    int i = 0;
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        while (st[i] != '\n' && st[i] != '\0')
            i++;
        if (st[i] == '\n')
            st[i] = '\0';
        else 
            while (getchar() != '\n')
                continue;
    }
    return ret_val;
}

5.scanf()函数

  • 以第一个非空白字符座位读取的开始,以第一个空白字符(空行、空格、制表符、换行符)座位字符串的结束。
  • 其他内容略。

二、字符串输出

1.puts()函数

  • 该函数显示字符串时会在末尾添加一个换行符
  • 该函数的参数为地址,且用双引号括起来的字符串常量作为参数时,参数被视为该字符串的地址。
  • 当参数为数组中某个项的地址时,如str[5],会从这个位置开始依次输出。
  • 结束条件为空字符

2.fputs()函数

  • 第二个参数要指明写入数据的文件,若要打印在显示器上,则用stdout作为参数。
  • 该函数不会在字符串末尾添加换行符

3.printf()

  • 省略

三、字符串函数

0.这里只写出书上详细介绍的5组字符串函数:strlen() | strcat()/strncat() | strcmp()/strncmp() | strcpy()/strncpy() | sprintf()

1.strlen函数

  • 该函数用于统计字符串的长度,函数返回值为字符串的长度。

2.strcat()函数

  • 基本定义
    • 该函数用于拼接字符串
    • 接受两个字符串作为参数
    • 把第二个字符串的备份附在第一个字符串的末尾,并把拼接后形成的新字符串作为第一个字符串,第二个字符串不变。
    • 该函数的函数类型是char *,即指向char的指针。
    • 所以该函数返回第一个参数,即拼接第二个字符串后的第一个字符串的地址
  • 存在的问题
    • 无法检查第一个数组是否能容纳第二个字符串。

3.strncat()函数

  • 该函数的第三个参数指定了最大添加字符数
  • 例如strncat(bugs, addon, 13)会把addon字符串的聂荣附加给bugs,加到第13个字符或者遇到空字符的时候停止
  • 所以,算上空字符(必须要添加空字符,否则就不是字符串了),bugs数组应该足够大,以容纳原始字符串(不包含空字符)、添加在后面的13个字符、末尾的空字符。

4.strcmp()函数

  • 用来把用户的响应于已储存的字符串作比较(比较两个字符串的内容)
  • 比较的是字符串的内容而不是字符串的地址,例如
    • 定义:
      • #define ANSWER "Grant"
      • #define SIZE 40
      • char try[SIZE]
      • s_gets(try, SIZE)\
      • 如果使用while (try == ANSWER),则永远得不到两者相等的结果,因为while比较的是指针,即地址,二者的地址肯定不相同
      • 但使用strcmp(try, ANSWER)则能够得到两者内容相等的结果。
    • 注:该函数只会比较try中第一个空字符前面的部分,所以该函数可以比较储存在不同大小数组中的字符串。
  • 该函数的返回值:
    • 返回实例:
      • 比较“A"和本身,返回0
      • 比较”A"和"B",返回-1
      • 比较“B"和”A“,返回1
    • 结论:
      • 二者相等返回0
      • 第一个的ASCII码比第二个大就返回负数,比第二个大就返回整数
      • 返回的整数和负数即为二者的ASCII码之差
    • 注:
      • 返回值的具体数值并不重要,重要的是它是0还是非0
      • 该函数比较的是字符串而不是字符
  • 局限:
    • 该函数比较字符串中的字符,直到发现不同的字符为止,这个过程可能会持续到字符串末尾。

5.strncmp()函数

  • 该函数可以比较字符不同的地方,也可以只比较第三个参数指定的字符数

  • 例如书中的实例:可以限定函数只查找这几个字符。


6.strcpy()函数

  • 该函数是用来拷贝整个字符串的内容,即相当于字符串赋值运算符
    • 例如:
      • str1和str2都是指向字符串的指针
      • str2 = str1;这个语句拷贝的指针的地址而不是具体内容
      • 所以要想拷贝整个字符串就要用到该函数
    • 注意:
      • 接受两个字符串指针作为参数,可以把第二个指针声明为指针、数组或者字符串常量
      • 第一个指针应该指向一个数据对象如数组,且该字符串有足够的空间存储源字符串的副本。
    • 其他属性:
      • 该函数的返回类型是char *,返回的是第一个参数的值,即一个字符的地址。
      • 第一个参数不必指向数组的开始,该属性可用于拷贝数组的一部分,详情见书上的程序。
  • 局限:
    • strcat()一样,不能检查目标空间是否能容纳的下源字符串的副本。

7.strncpy()函数

  • 该函数的第三个参数指明了可拷贝的最大字符数
    • 如果要拷贝的字符超过了指定的参数n,当拷贝了n个字符后就会停止,并且也不会在后面添加空字符,容易出现错误,所以要非常注意。

8.sprintf()函数

  • 该函数与printf()函数类似,但这个是把数据写入字符串,而不是打印在显示器上。

  • 该函数的第一个参数是目标字符串的地址,其余的与printf()类似。

    • 示例:
    char first[MAX];
    char last[MAX];
    char formal[2 * MAX + 10];
    //给以上前面两个数组赋值后就可以进行如下的操作
    sprintf(formal, "%s, %-19s\n", last, first);