C语言输入字符串的4种方法(附带示例)
在C语言中,输入字符串是一个常见的操作,但对于初学者来说可能会遇到一些困惑。本文将详细介绍几种C语言输入字符串的方法,并解释每种方法的优缺点以及使用场景。
C语言中最常用的输入字符串的函数有 scanf()、gets()、fgets()、scanf_s() 和 gets_s()。我们将逐一介绍这些函数的使用方法,并探讨它们的特点。
1. 使用 scanf() 函数输入字符串
scanf() 函数是 C 语言中最常用的输入函数之一,它可以用来输入各种数据类型,包括字符串。使用 scanf() 输入字符串时,我们需要使用%s
格式说明符。
以下是一个使用 scanf() 输入字符串的示例:
#include <stdio.h> int main() { char str[50]; printf("请输入一个字符串:"); scanf("%s", str); printf("你输入的字符串是:%s\n", str); return 0; }
在这个例子中,我们声明了一个长度为 50 的字符数组 str 来存储输入的字符串。使用 scanf("%s", str) 可以读取用户输入的字符串并存储到 str 数组中。
然而,使用 scanf() 输入字符串有一些限制和潜在的问题:
- scanf() 在遇到空格、制表符或换行符时会停止读取,这意味着它无法读取包含空格的完整句子。
- scanf() 不会检查输入的字符串长度是否超过数组的大小,可能导致缓冲区溢出的安全问题。
-
如果用户输入的字符串超过了数组的大小,多余的字符会留在输入缓冲区中,可能影响后续的输入操作。
因此,虽然 scanf() 使用简单,但在处理字符串输入时需要格外小心。
2. 使用 gets() 函数输入字符串
gets() 函数是另一种用于输入字符串的方法,它可以读取包含空格的完整行。以下是使用 gets() 函数的示例:
#include <stdio.h> int main() { char str[50]; printf("请输入一个字符串:"); gets(str); printf("你输入的字符串是:%s\n", str); return 0; }
gets() 函数会读取用户输入的整行内容,直到遇到换行符为止。这意味着它可以读取包含空格的完整句子,这是相对于 scanf() 的一个优势。
然而,gets() 函数存在严重的安全隐患:
- gets() 不会检查输入的字符串长度是否超过数组的大小,很容易导致缓冲区溢出。
-
由于安全问题,gets() 函数在 C11 标准中已经被废弃,许多现代编译器会发出警告或错误。
因此,尽管 gets() 使用方便,但由于其安全风险,我们不应该在实际的程序中使用它。
3. 使用 fgets() 函数输入字符串
fgets() 函数是一个更安全、更灵活的字符串输入方法,它允许我们指定最大读取的字符数,从而避免缓冲区溢出的风险。
以下是使用 fgets() 函数的示例:
#include <stdio.h> #include <string.h> int main() { char str[50]; printf("请输入一个字符串:"); fgets(str, sizeof(str), stdin); // 去除末尾的换行符 str[strcspn(str, "\n")] = 0; printf("你输入的字符串是:%s\n", str); return 0; }
fgets() 函数有三个参数:存储字符串的数组、最大读取的字符数(包括空字符)和输入流(这里使用 stdin 表示标准输入)。
fgets() 的优点包括:
- 可以安全地读取指定长度的字符串,避免缓冲区溢出。
- 可以读取包含空格的完整行。
- 如果输入的字符串过长,fgets() 会自动截断,而不会造成安全问题。
需要注意的是,fgets() 会保留输入中的换行符。在上面的例子中,我们使用 strcspn() 函数来去除末尾的换行符。
4. 使用安全函数
如果你仍然希望使用类似 scanf() 和 gets() 的语法,但又想避免缓冲区溢出的风险,可以考虑使用它们的安全版本,也即 scanf_s() 和 gets_s()。安全函数多了一个参数,用来指明缓冲区的大小,这样就能限制输入的字符串的长度了。
注意,安全函数最初由微软编译器(Microsoft Visual C++)提出,直到今天也没成为标准函数,所以并不是所有编译器都支持(当然微软的 Visual C++ 编译器是支持的),使用之前一定要亲自测试。
scanf_s() 函数
scanf_s() 是 scanf() 的安全版本,在使用时要求指定缓冲区的大小,以防止缓冲区溢出。用法如下:
#include <stdio.h> int main() { char str[50]; printf("请输入一个字符串:"); scanf_s("%49s", str, (unsigned)sizeof(str)); //最后一个参数指明缓冲区大小 printf("您输入的字符串是:%s\n", str); return 0; }
注意,s_scanf() 的可用性和具体语法可能因编译器而异。在使用之前,请查阅你的编译器文档。
gets_s() 函数
gets_s() 是 gets() 的安全版本,在使用时同样需要指明缓冲区的大小。以下是一个使用示例:
#include <stdio.h> int main() { char str[50]; printf("请输入一个字符串:"); gets_s(str, sizeof(str)); //最后一个参数指明缓冲区大小 printf("您输入的字符串是:%s\n", str); return 0; }
安全函数的优点是它们可以防止缓冲区溢出,提高程序的安全性,但是它们也有一些限制:
- 这些函数并不是 C 标准库的一部分,可能不是所有编译器都支持。
- scanf_s() 仍然无法读取包含空格的完整字符串(除非使用特殊的格式说明符)。
- 如果输入超过指定的长度,这些函数会触发运行时错误,程序可能会异常终止。
总结
在实际编程中,选择合适的字符串输入方法取决于多个因素,如安全性要求、跨平台兼容性、输入数据的特性等。一般来说,fgets() 是一个较为安全和灵活的选择,它既可以读取包含空格的字符串,又能有效防止缓冲区溢出。如果您的编译环境支持安全函数,并且安全性是首要考虑因素,那么 scanf_s() 或 gets_s() 也是不错的选择。