欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C Primer Plus ---- Chapter 11 ----Character Strings and String Functions ---- 2.字符串输入函数

程序员文章站 2024-02-29 17:26:58
...

C Primer Plus ---- Chapter 11 ----Character Strings and String Functions ---- 2.字符串输入函数

1. 分配空间

想要读入字符串,首先要分配空间。

char *a;
scanf("%s",a);

上述会出错,因为指针 a 没有初始化,a 存放的地址未知。

2. gets( )函数

(1) gets() 读取整行的字符(包括空白字符)知道遇到换行符’\n’。
 
(2) gets() 舍弃换行符’\n’,然后在字符结尾添加空字符’\0’标记结束。
 
(3) 缺点: gets() 不会检查输入字符是否超出分配内存空间大小,因此可能会溢出。

char words[10];
gets(words);

words表示起始地址,gets()输入只知道将输入字符存放的起始位置,不知道结束位置。输入超过会出现segmentation fault,即访问了未分配的存储空间。
 
(4) gets()的返回值

 char * gets(char * s)
  {
                                          
       return s;                                
  }

gets() 如果读入成功,返回与参数相同的指针。如果发生错误,返回空指针 NULL。

3. fgets()函数

(1) 增加第二个参数 n 表明可以输入的最大字符串长度。可以读入最大 n-1 个字符 或者读到换行符 ‘\n’。
 
(2) 如果fgets() 读到换行符,它会将换行符存储而不舍弃。
 
(3) fgets() 函数是用于文件读取,因此添加第三个参数来表明从哪里读取文件。如果从键盘读取,则用 stdin 作为参数。
(4) fgets() 返回指向字符的指针,如果输入正确,返回第一个参数的地址,如果出错或者遇到 end-of-file ,返回空指针NULL。
 

/*11.7   fgets1.c -- using fgets() and fputs() */
#include <stdio.h>
#define STLEN 14
int main(void)
{
char words[STLEN];
puts("Enter a string, please.");
fgets(words, STLEN, stdin);
printf("Your string twice (puts(), then fputs()):\n");
puts(words);
fputs(words, stdout);
puts("Enter another string, please.");
fgets(words, STLEN, stdin);
printf("Your string twice (puts(), then fputs()):\n");
puts(words);
fputs(words, stdout);
puts("Done.");
return 0;
}

Answer:

Enter a string, please.
apple pie
Your string twice (puts(), then fputs()):
apple pie

apple pie
Enter another string, please.
strawberry shortcake
Your string twice (puts(), then fputs()):
strawberry sh
strawberry shDone.

程序分析:

  1. 第一次输入 apple pie 占9个字符,小于最大可输入字符 14-1。输入字符串后又又输入换行符,因此存放字符为 apple pie\n\0
  2. 输入 apple pie 后换行,光标移到下一行,同时将上第一条得到的字符存入数组 words 中。
  3. 执行 printf()函数输出字符后,接着执行 *puts(words)*语句,输出 字符串 “apple pie\n\0”,由于puts() 函数还会额外添加一个换行符,因此有两个换行符,多出一个空白行。
  4. 执行fputs(),不会自动添加换行符,因此只有原来字符串中一个换行符,光标移动到下一行。
  5. 第二次输入字符串*“strawberry shortcake”*超过了13个字符,因此只存13个字符加一个空字符 “strawberry sh\0”。再用 puts() 输出会添加换行符,而 fputs() 不会。
     
/* 11.8 fgets2.c -- using fgets() and fputs() */
#include <stdio.h>
#define STLEN 10
int main(void)
{
char words[STLEN];
puts("Enter strings (empty line to quit):");
while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n')
fputs(words, stdout);
puts("Done.");
return 0;
}

Answer:

Enter strings (empty line to quit):
By the way, the gets() function
By the way, the gets() function
also returns a null pointer if it
also returns a null pointer if it
encounters end-of-file.
encounters end-of-file.

Done.

程序分析:

  1. while()循环的条件为输入正常且输入不为空白行,则执行循环。
  2. 第一次输入字符串超过10个字符,但是只存储9个字符加一个空字符进入数组: “By the wa\0”
  3. 由于 fputs() 不自动添加换行符,输出后光标位于最后一个字符后面,接着执行while()进行第二次判断,此时输入缓冲区还有字符,因此自动将后面的字符 “y, the ge\0” 存入数组,因此fputs()接着输出。反复循环直到最后遇到换行符,再重新从键盘输入。
     
    如果不想要多余的字符,见如下程序:
// 11.9  fgets3.c ------ using gets()
#include <stdio.h>
#define LEN 10
int main()
{
   char words[LEN];
   int i;
   puts("Enter strings (empty to quit):");
   while(fgets(words,LEN,stdin) != NULL && words[0] != '\n')
   {
      i = 0;
      while (words[i] != '\n' && words[i] != '\0')
      i++;
      if (words[i] == '\n')
      {
          words[i] = '\0';
       }
       else //words[i] = '\0'
       {
            while(getchar() != '\n')
            continue;
       }
       puts(words[i]);
   }
   puts("Done!");
   return 0;
} 

Answer:

Enter strings (empty line to quit):
This
This
program seems
program s
unwilling to accept long lines.
unwilling
But it doesn't get stuck on long
But it do
lines either.
lines eit

Done!

空字符和空指针

空字符,即’\0’,是字符类型,用来标志字符串的结束,对应的 ASCLL 码为数字0。
 
空指针,NULL,是指针类型,它的值并不对应任何数据的有效地址,通常在函数中使用。
 

4. s_gets( )函数

// 11.10 s_gets.c
#include <stdio.h>
char *s_gets(char *st, int n)
{
   char *ret_val;
   int i = 0;
   ret_val = fgets(st, n, stdin);
   if (ret_val) //ret_val != NULL
   {
      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( )函数

scanf()函数搭配 %s 来读入字符串,然而 scanf() 只能读入"一个单词",即遇到空白字符就停止读。