字符的输入
字符串是以空字符(\0)结尾的
字符串输入
puts()
函数只适用于字符串,而且自动在显示的字符串末尾加上换行符
字符串字面量
用双括号括起来的内容称为字符串字面量;双引号中的字符和编译器自动加入末尾的\0字符
如果要在字符串内部使用双引号
printf("\"Run, Spot, run!\" exclaimed Dick.\n");
字符串常量属于静态存储类别
gets()
读取整行输入,直到遇到换行符,然后丢弃换行符,存储其余字符,并在字符的末尾添加一个空字符使其成为一个c字符串
/* getsputs.c -- 使用 gets() 和 puts() */
#include <stdio.h>
#define STLEN 81
int main(void)
{
char words[STLEN];
puts("Enter a string, please.");
gets(words); // 典型用法
printf("Your string twice:\n");
printf("%s\n", words);
puts(words);
puts("Done.");
return 0;
}
fgets()
通过第二个参数限制读入的字符数来解决溢出的问题,专门设计用于处理文件的输入
与gets()的区别
指明了读入字符的最大数量,如果该参数的值为n,则读入的为n-1,或者读到遇到第一个换行符为止
读到一个换行符,会把它存储在字符串中,gets则会丢弃换行符
fgets函数的第三个函数指明要读入的文件,如果是从键盘中读入,则以stdin作为参数
fgets把换行符放在字符串的末尾,通常要与fputs()配套使用
fgets(words,STLEN,stdin); //第二个变量为读入字符的最大数量
fputs(words,stdout);
处理换行符
while(words[i]='\n')
i++;
word[i]='\0';
while(getchar()!='\n') //读取但不存储输入,包括\n
continue;
gets_s()
gets_s(words,STLEN);
gets_s()只从标准输入中读取数据,不需要第三个参数
读到换行符时不存储
读到最大字符数而没有读到换行符,会执行以下几步,先把目标数组中的首字符设置为空字符,读取并丢弃随后输入直至读到换行符或文件结尾,然后返回空指针,接着调用依赖的函数,可能会中止和退出函数
比较
输入行太长使用gets不安全,会擦写现有数据,存在安全隐患
gets_s函数很安全,但是如果不希望程序中止或者退出,得编写特殊的“处理函数。如果打算让程序继续运行,gets_s()会丢弃该输入行的其余字符
当输入太长,超过数组需要可容纳的字符串时,fgets()函数最容易使用
s_gets()函数
如果字符串中出现换行符,就用空字符代替他,如果字符串中出现空字符,就丢弃输入行中的其余字符,然后返回与fgets()相同的值
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<ins>
</ins> while (getchar() != '\n')
continue;
}
return ret_val;
}
丢弃过长输入行中的余下字符的原因
输入行中的多余的字符会被留在缓冲区中,成为下次读取语句的输入;如果下一条读取语句要读取的是double类型则可能导致程序崩溃;丢弃输入行余下字符保证了读取语句和键盘输入同步
缺陷
遇到不合适的输入时毫无反应。丢弃多余的字符时,既不通知用户也不告知用户
scanf()函数
更像是获取单词函数,从第一个非空白字符作为字符串的开始
以空行,空格,制表符或者换行符作为字符串的结束(字符串不包括空白字符)
scanf("%10s",d); //将读取10个字符或读到第一个空白字符停止
缺陷
无法完整读取书名或歌曲名,除非这些名称是一个单词
输入行过长,scanf()会导致数据溢出,不过在%s转换说明中使用字段宽度可防止溢出
用fgets读取从键盘输入的数据更合适
字符串的输出
puts()
/* put_out.c -- 使用 puts() */
#include <stdio.h>
#define DEF "I am a #defined string."
int main(void){
char str1[80] = "An array was initialized to me.";
const char * str2 = "A pointer was initialized to me.";
puts("I'm an argument to puts().");
puts(DEF);
puts(str1);
puts(str2);
puts(&str1[5]);
puts(str2 + 4);
}
//I'm an argument to puts().
//I am a #defined string.
//An array was initialized to me.
//A pointer was initialized to me.
//ray was initialized to me.
//inter was initialized to me.
puts函数在显示字符串时会自动在其末尾添加一个换行符
在遇到空字符时就会自动停止输入
/* nono.c -- 千万不要模仿! */
#include <stdio.h>
int main(void)
{
char side_a[] = "Side A";
char dont[] = { 'W', 'O', 'W', '!' };
char side_b[] = "Side B";
puts(dont); /* dont 不是一个字符串 */
return 0;
}
//输出WOW!Side A
fputs()
第二个参数指明要写入数据的文件。如果要打印在显示器上,可以用定义在stdio.h中的stdout作为该参数
不会再输出的末尾添加换行符
printf()
把字符串的地址作为参数,可以格式化不同的数据类型
不会自动在每个字符串末尾加上一个换行符。必须在参数中指明在哪里使用换行符
算机执行的时间也更长
然而,使用printf()打印多个字符串更加简单
总结
gets()丢弃输入中的换行符,但是puts()在输出中添加换行符。另一方面,fgets()保留输入中的换行符,fputs()不在输出中添加换行符
假设要编写一个循环,读取一行输入,另起一行打印出该输入。可以这样写
char line[81];
while(gets(line)) //==while(gets(line!=NULL))
puts(line);
//第二种方法
char line[81];
while (fgets(line, 81, stdin))
fputs(line, stdout);