用于用户输入|的内置库函数scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s

940 阅读6分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

scanf() : C 库函数 int scanf (const char *format, ...) 从 stdin 读取格式化的输入。

Syntax:
int scanf(const char *format, ...)

Return type: Integer

Parameters:
format: 包含类型说明符的字符串
"..." (ellipsis): 指示函数接受可变数量的参数

每个参数必须是写入转换结果的内存地址。成功后,该函数返回填充的变量数。如果输入失败,在成功读取任何数据之前,将返回 EOF。
可在 scanf 中使用的类型说明符:

%c — Character
%d — Signed integer
%f — Floating point
%s — String
//C 程序演示scanf语句
#include <stdio.h>
#include <stdlib.h>

int main()
{
	char a[10];
	printf("Please enter your name : \n");
	
	//scanf语句
	scanf("%s", a);

	printf("You entered: \n%s", a);

return 0;
}

输入:

haiyong

输出:

Please enter your name : 
You entered: 
haiyong

sscanf( ):sscanf( ) 用于从字符串中读取格式化的输入。

Syntax:
int sscanf ( const char * s, const char * format, ...);

Return type: Integer

Parameters:
s: 用于检索数据的字符串
format: 包含类型说明符的字符串
… : 参数包含用于分配具有适当类型的存储的指针。

这些参数的数量应至少与格式说明符存储的值的数量相同。

成功后,该函数返回填充的变量数。在输入失败的情况下,在成功读取任何数据之前,将返回 EOF。

// 说明sscanf语句的C程序
#include <stdio.h>

int main ()
{
	// 声明数组 s
	char s [] = "3 red balls 2 blue balls";
	char str [10],str2 [10];
	int i;
	
	// %*s用于跳过单词
	sscanf (s,"%d %*s %*s %*s %s %s", &i, str, str2);
	
	printf ("%d %s %s \n", i, str, str2);
	
	return 0;
}

输出:

3 blue balls

fscanf( ):fscanf( ) 从文件中读取格式化数据并将其存储到变量中。

Syntax:
int fscanf(FILE *stream, const char *format, ...)

Parameters:
Stream: 指向标识流的File对象的指针。
format: 是包含类型说明符的字符串

成功后,该函数返回填充的变量数。在输入失败的情况下,在成功读取任何数据之前,将返回 EOF。

// 说明sscanf语句的C程序
//此程序将在文件file.txt的系统上运行

#include <stdio.h>
#include <stdlib.h>

int main()
{
	char s1[10], s2[10], s3[10];
	int year;
	
	// 文件指针
	FILE * fp;
	
	// 打开/创建文件
	fp = fopen ("file.txt", "w+");	
	
	// 在文件中存储字符串
	fputs("Hello World its 2017", fp);
	
	// 将文件位置设置为文件的开头
	rewind(fp);
	
	// 从文件中获取输入
	fscanf(fp, "%s %s %s %d", s1, s2, s3, &year);
	
	printf("String1 |%s|\n", s1 );
	printf("String2 |%s|\n", s2 );
	printf("String3 |%s|\n", s3 );
	printf("Integer |%d|\n", year );
	
	// 关闭文件指针
	fclose(fp);	
	
	return(0);
}

输出:

String1 |Hello|
String2 |World|
String3 |its|
Integer |2017|

scanf_s() : 此函数特定于微软编译器。它与 scanf 相同,只是不会导致缓冲区过载。

Syntax:
int scanf_s(const char *format [argument]...);

argument(parameter): 在这里,您可以指定缓冲区大小并实际控制输入应用程序的限制。

成功后,该函数返回填充的变量数。在输入失败的情况下,在成功读取任何数据之前,将返回 EOF。
为什么要使用 scanf_s()?
scanf 只读取控制台提供的任何输入。C 不检查用户输入是否适合您指定的变量。
如果你有一个名为 color[3] 的数组,并且你使用 scanf 表示 “Red”,它会正常工作,但如果用户输入超过 3 个字符,scanf 开始写入不属于 color 的内存。C 不会捕获或警告您,它可能会也可能不会使程序崩溃,具体取决于是否有内容试图访问并写入不属于颜色的内存插槽。这就是scanf_s发挥作用的地方。scanf_s检查用户输入是否适合给定的内存空间。

// 说明sscanf_s语句的C程序

//scanf_s()只能在Microsoft Visual Studio中工作。
#include <stdio.h>
#include <stdlib.h>

int main()
{
	char a[5];
	
	// sizeof(a)是缓冲区大小
	scanf_s("%s", a, sizeof(a));
	
		printf("\n%s ", a);

	return 0;
}

输入:

Red

输出:

Red

输入:

Yellow

输出:

No Output

说明缓冲区大小和数组大小之间的关系。

// C程序使用输入后按下的Enter键(换行符)
#include<stdio.h>

char ch[100000];
printf("Enter characters: ");
scanf_s("%s", ch, 99999);
getchar();
// C++程序使用输入后按下的Enter键(换行符)

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
	// 实例
	char ch[100000];
	printf("Enter characters: ");
	scanf_s("%s", ch, 99999);
	getchar();
	return 0;
}
  1. 如果缓冲区大小等于或小于数组的大小,则输入大于或等于缓冲区大小将不执行任何操作。

  2. 如果缓冲区大小大于数组的大小,则

    a. 输入小于缓冲区大小将起作用,但会给出错误

    “运行时检查失败 #2 – 变量'variable_name'周围的堆栈已损坏。”
    

    b. 输入大于缓冲区大小将无助于任何操作并给出相同的错误。

fscanf_s() : fscanf() 和 fscanf_s() 之间的区别与 scanf() 和 scanf_s() 的区别相同。fscanf_s() 是安全函数,安全函数要求每个 c、C、s、S 和 [ type 字段的大小作为紧跟变量后面的参数传递。

Syntax:
int fscanf_s(   FILE *stream,  const char *format ,[argument ]... ); 

fscanf_s has an extra argument(parameter) where you can 
specify the buffer size and actually control the limit of the input.

成功后,该函数返回填充的变量数。在输入失败的情况下,在成功读取任何数据之前,将返回 EOF。

// 说明fscanf_s语句的C程序此程序将在MS Visual studio上运行
#include <stdio.h>
#include <stdlib.h>

int main()
{
	char s1[10], s2[10], s3[10];
	int year;
	
	// 文件指针
	FILE * fp;

	// 安全打开文件
	fopen_s(&fp,"file.txt", "w+");
	
	fputs("Hello World its 2017", fp);

	rewind(fp);

	// 使用 fscanf_s
	fscanf_s(fp, "%s", s1, sizeof(s1));
	fscanf_s(fp, "%s", s2, sizeof(s2));
	fscanf_s(fp, "%s", s3, sizeof(s3));
	fscanf_s(fp, "%d", &year, sizeof(year));

	printf("String1 |%s|\n", s1);
	printf("String2 |%s|\n", s2);
	printf("String3 |%s|\n", s3);
	printf("Integer |%d|\n", year);

	fclose(fp);

	return(0);
}

输出:

String1 |Hello|
String2 |World|
String3 |its|
Integer |2017|

sscanf_s() : sscanf_s() 是 sscanf() 的安全函数,安全函数要求每个 c、C、s、S 和 [ 类型字段的大小作为紧跟在变量后面的参数传递。

Syntax:
int sscanf_s(const char *restrict buffer, const char *restrict format, ...);

sscanfs有一个额外的参数(参数),您可以在其中指定缓冲区大小并实际控制输入的限制。

成功后,该函数返回填充的变量数。在输入失败的情况下,在成功读取任何数据之前,将返回 EOF。

//说明sscanf_s语句的C程序
//此程序将在MS Visual studio上运行
#include <stdio.h>

int main()
{
	char s[] = "3 red balls 2 blue balls";
	char str[10], str2[10];
	int i;

	// %*s用于跳过单词
	sscanf_s(s, "%d", &i, sizeof(i));
	sscanf_s(s, "%*d %*s %*s %*s %s", str, sizeof(str));
	sscanf_s(s, "%*d %*s %*s %*s %*s %s", str2, sizeof(str2));
	
	printf("%d %s %s \n", i, str, str2);

	return 0;
}

输出:

3 blue balls 

注意: sscanf_s() 仅适用于 Microsoft Visual Studio。