标签:指令 ase == 输入 asc ring ict 字符串输入 保留
字符串输入首先要考虑的是存储位置和存储空间大小。
例子:char *name; scanf("%s", name); 指针未初始化,可能指向内存中的任意地方,字符串读入的时候有可能覆盖内存中的关键数据,造成程序或机器崩溃。
char name[81]; 这种方式显式声明空间并进行初始化。
scanf("%s", str)函数读入单个word。而gets()可以读取一整行的字符串。它通过换行符读取整行,丢弃换行符,存储剩余的字符,添加空字符(‘\0‘)以创建C字符串。一般和puts()搭配使用。
示例:
#include<stdio.h>
#define STLEM 81
int main(void)
{
char words[STLEM];
puts("Enter a string, please.");
gets(words);
printf("Your string twice:\n");
printf("%s\n", words);
puts(words);
puts("Done.");
return 0;
}
??:gets函数的问题(int puts(const char *);):虽然在定义字符串的时候声明了大小为81,但gets函数无法阻止输入超过大小的字符串长度,编译运行时将报错"warning: this program uses gets(), which is unsafe."
gets函数只接收一个参数,char类型的指针。没有其他参数限定用户输入的字符串长度。gets()只知道数组的开始位置,却不知道数组的长度。
如果输入字符串太长,则会出现缓冲区溢出,这意味着多余的字符溢出了指定的目标。 额外的字符可能只是进入未使用的内存并且没有立即出现问题,或者它们可能会覆盖程序中的其他数据,但这些肯定不是唯一的可能性。
C99已经不建议使用该函数,并建议将gets()从标准库中移除,C11已经将gets()从标准中移除。但C的标准只是要求编译器厂商必须符合所要求的标准,而不是限制编译器厂商不能做什么。所以,主流的编译器依然支持gets()函数已确保向后兼容。
为了解决gets()函数容易引起的缓冲区溢出问题,出现了fgets()函数。char fgets(char __restrict, int, FILE *);
fgets()与gets的主要不同点为:
示例:
#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;
}
输出:
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.
解读:
fgets()函数的返回值为指向char类型的指针。指针指向输入的字符串地址。但是,如果函数遇到文件结尾,则返回一个称为空指针的特殊指针。这是一个确保不指向有效数据的指针,因此它可用于指示特殊情况。在代码中,该指针可以表示为数字0,或者在C中更通常的表示方法为宏NULL。
由于fgets()会保存换行符,这就带来了一些问题。有时,你不想保存该换行符,而仅仅将用户输入的换行符作为buffered I/O的一个指令,通知临时存储区的数据可以被fgets()函数使用。
如何丢弃换行符?
while (words[i] != ‘\n‘)
i++;
words[i] = ‘\0‘;
words为通过fgets()得到的输入字符串,将换行符替换为‘\0‘。
如果想将超过数组定义大小的剩余字符串也丢弃掉,以免作为下次的输入,如何做到呢?
while (getchar() != ‘\n‘)
continue;
NULL字符或‘\0‘,用来标记字符串的结束。代码为0的字符,ASCII 为0的字符。
空指针或NULL具有与有效数据地址不对应的值。 它通常由函数使用,否则返回有效地址以指示某些特殊情况,例如遇到文件结束或未能按预期执行。
另外,空字符是int类型,而NULL指针是指针类型。
C11引入了一个新函数gets_s(),类似fgets(),但和fgets也有不同之处。
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;
}
s_gets()函数为自定义函数,可以丢弃fgets()函数保留的换行符,同时丢弃超过最大字符数的剩余输入。
一般我们使用scanf()函数和%s格式读取字符串。scanf()更像是读取一个单词,而不是一个字符串。
示例:
Input Statement | Original Input Queue* | Name Contents | Remaining Quenue |
---|---|---|---|
scanf("%s‘, name); | Fleebert#Hup | Fleebert | #Hup |
scanf("%5s", name); | Fleebert#Hup | Fleeb | ert#Hup |
scanf("%5s", name); | Ann#Ular | Ann | #Ular |
‘#’代表space character(/t, /b等)。
可以到,scanf会在遇到空白字符或最大字符时读取结束,其他字符将再下次输入时读取。scanf的返回值为成功读取到的字符串个数。
标签:指令 ase == 输入 asc ring ict 字符串输入 保留
原文地址:https://www.cnblogs.com/jeffrey-yang/p/10224803.html