C语言进阶输入输出重定向与fopen函数使用示例详解

目录
  • 正片开始
  • 输入输出重定向
  • fopen函数

正片开始

大多数情况下,我们所熟知的输入输出都是标准I/O(标准输入输出),也就是我们在写代码时会直接从键盘读取,从屏幕输出。但是当我们涉及到数据统计或者多组未定义内容输入时,我们的程序就会出现一些小问题

int n = 0;
while(scanf("%d",&n)==1)

按照常理来说,这里 scanf 的返回值是成功输入的数的个数,输入一但结束,scanf 函数就无法继续读取 n,返回0,我们测试一下,输入“1,2,3,4,5”看看,好家伙,根本没有结果显示。是代码问题还是运行太慢?其实是还在等待输入,虽然我们可能觉得一个回车就可以搞定,但程序不会。

记得 scanf 的输入格式上对于空格,Tab,Enter键都是一视同仁,那如何才能告诉 程序我们输入结束了呢?在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再按Enter才能结束输入。在Linux下,只需Ctrl+Z即可结束输入。

也就是说上面的程序不是很方便,每次测试需要手动输入很多数,如果面对多组输入并且需要大量验证的测试,数据也只能保存在命令行中,仍然不够方便。

输入输出重定向

以上场景我们有个好的方法就是用文件把输入输出的数据放在文件里面,也就是所谓的输入输出重定向,放入事先准备好的数据,就不必每次重复输入了,也可以太多的输出一卷屏跑出来,属实不方便,而且在文件中放好标准的答案,可以很方便的进行比对,无需我们再去逐一的排查。有个不争的事实就是几乎所有算法的输出数据和标准答案都是放在文件里的。

在使用输入输出重定向时,只需在main函数的入口处加入两条语句:

freopen("input.txt","r","stdin");
freopen("output.txt","w","stdout");

其作用很简单,就是使得scanf从文件 input.txt 读入,printf 再从output.txt输出。
我们给出一个代码:

#define Max
#include<stdio.h>
int main()
{
#ifdefine Max
freopen("input.txt","r","stdin");
freopen("output.txt","w","stdout");
#endif
}

#ifdefine Max#endif 的特殊之处就是我们只有在Max被定义了情况下才可以编译这两条 freopen 语句。事实上不只scanf 和 printf,所用从键盘键入从屏幕输出的数据都会改用文件,这确实方便,但在很多算法竞赛中禁止访问文件,甚至允许访问文件却禁止使用 freopen 这样的重定向读写文件。这种特殊情况我们又该作何打算呢?没错,那就是 fopen 函数

fopen函数

fopen函数表达式为:

FILE *fopen(char *filename, *type);

这个表达式不细说,只作了解,又是一堆晦涩陌生的名词,有兴趣的可以自行搜索。
我们来看个代码:

FILE *fin,*fout;
fin = fopen("test.in","r");
fout = fopen("test.out","w");
fclose(fin);
fclose(fout);

这里先声明了变量fin 和 fout,后续如果要输入输出我们需要把printf改为fprintf ,把 scanf 改为 fscanf,最后fclose关闭两个文件。

fopen和 freopen长的差不多,起初我甚至觉得他们就是一个东西,freopen和fopen之间有各自的优劣,重定向的方法写起来简单自然,但不能同时读写文件与标准输入输出;fopen写法稍微繁琐一点,但灵活性更大,就可以反复打开和读写文件。

这里的fscanf,fprintf都是针对数据流的,而什么是数据流?

数据流是一组有序,有起点和终点的字节的数据序列,包括输入流和输出流。就像水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。

“流是磁盘或其它外围设备中存储的数据的源点或终点。”

而对于fscanf 的使用难点在于以下几点:

  • 对空白符的处理(空格、制表符、换行符);
  • *的用法;
  • [] 以及 [^] 的用法;
  • EOF 的处理;

上述问题,网上的文章都语焉不详,具体内容参见 fscanf详谈

当我们想把fopen的程序改成标准输入输出,只需赋值"fin = stdin;fout = stdout",不用再调用fopen和fclose。

今天就先到这里吧,摸了家人们,更多关于C语言输入输出重定向fopen函数的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言文件操作函数freopen详细解析

    今天做USACO  用到了文件的操作. 之前做USACO只是格式化的些 写  freopen("xxx.in","r",stdin)  和"freopen("xxx.out","w",stdout)" 百度百科上是这么介绍的: 函数名: freopen 功 能: 替换一个流,或者说重新分配文件指针,实现重定向.如果stream流已经打开,则先关闭该流.如果该流已经定向,则freopen将会清除该定向.此函数

  • C语言格式化输入输出函数详解

    一:格式输出函数printf() 1.调用形式一般为:printf("格式化控制字符串",输出表列): 2.格式化控制字符串用于指定输出格式,它有三种形式: 1.格式说明符:规定了相应输出表列内容的输出格式,以%打头,如%d.%o等 2.转义字符:用来输出转义字符所代表的控制代码或者特殊字符,比如常用的'\n'.'\t' 3.普通字符:需要原样输出的字符. 3.输出表列为若干需要输出的数据项,它与格式说明符在数量和类型上一一对应: 4.格式字符m指定输出数据所占宽度,n对实数表示输出n

  • 详解C语言中的fopen()函数和fdopen()函数

    C语言fopen()函数:打开一个文件并返回文件指针 头文件: #include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * path, const char * mode); [参数]path为包含了路径的文件名,mode为文件打开方式. mode有以下几种方式: 在POSIX 系统,包含Linux 下都会忽略 b 字符.由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_I

  • C语言数据输入与输出实例详解

    C语言数据输入与输出实例详解 1 概论 C语言提供了跨平台的数据输入输出函数scanf()和printf()函数,它们可以按照指定的格式来解析常见的数据类型,例如整数,浮点数,字符和字符串等等.数据输入的来源可以是文件,控制台以及网络,而输出的终端可以是控制台,文件甚至是网页. 2 数据输出 从第一个c语言程序中,就使用了跨平台的库函数printf实现将一段文字输出到控制台,而实际上,printf()不仅可以将数据按照指定的格式输出到控制台,还可以是网页或者是指定的文件中,printf()函数执

  • 详解C语言中freopen()函数和fclose()函数的用法

    C语言freopen()函数:打开文件函数,并获得文件句柄 头文件: #include <stdio.h> 定义函数: FILE * freopen(const char * path, const char * mode, FILE * stream); 函数说明: 参数 path 字符串包含欲打开的文件路径及文件名. 参数mode 请参考fopen()说明.. 参数stream 为已打开的文件指针. Freopen()会将原stream 所打开的文件流关闭, 然后打开参数path 的文件.

  • C语言进阶输入输出重定向与fopen函数使用示例详解

    目录 正片开始 输入输出重定向 fopen函数 正片开始 大多数情况下,我们所熟知的输入输出都是标准I/O(标准输入输出),也就是我们在写代码时会直接从键盘读取,从屏幕输出.但是当我们涉及到数据统计或者多组未定义内容输入时,我们的程序就会出现一些小问题 int n = 0; while(scanf("%d",&n)==1) 按照常理来说,这里 scanf 的返回值是成功输入的数的个数,输入一但结束,scanf 函数就无法继续读取 n,返回0,我们测试一下,输入“1,2,3,4,

  • C/C++语言八大排序算法之桶排序全过程示例详解

    基本思路是将所有数的个位十位百位一直到最大数的最高位一步步装桶,先个位装桶然后出桶,直到最高位入桶出桶完毕. 首先我们要求出一个数组的最大数然后求出他的最大位数 //求最大位数的函数 int getmaxweisu(int* a,int len)// { int max = a[0]; for (int i = 0; i < len; i++) { if (max < a[i]) { max = a[i]; } } int count = 1; while (max/10) { count++

  • Go语言学习教程之goroutine和通道的示例详解

    目录 goroutine 通道 Range 和 Close Select 官方留的两道练习题 等价的二叉树 网络爬虫 源码地址 goroutine goroutine是由Go运行时管理的轻量级线程. go f(x, y, z)在一个新的goroutine中开始执行f(x, y,z). goroutines运行在相同的地址空间中,所以对共享的内存访问必须同步.sync包提供了基本的同步原语(synchronization primitives),比如互斥锁(mutual exclusion loc

  • C语言嵌入式实现支持浮点输出的printf示例详解

    目录 简介 背景 C语言可变参数函数 踩坑 功能实现 简介 mr-printf 模块为 mr-library 项目下的可裁剪模块,以C语言编写,可快速移植到各种平台(主要以嵌入式mcu为主). mr-printf 模块用以替代 libc 中 printf, 可在较小资源占用的同时支持绝大部分 printf 功能,于此同时还支持对单独功能模块的裁剪以减少用户不需要功能的资源占用. 背景 printf 大家应该使用的比较多,但是在嵌入式平台中,尤其是单片机中,libc中的printf对内存的占用较高

  • C语言编程题杨氏矩阵算法快速上手示例详解

    目录 题目概要 一.解题思路 二.具体代码 题目概要 有一个数字矩阵,矩阵的每行从左到右都是递增的,矩阵从上到下都是递增的,请编写程序在这样的矩阵中查找某个数字是否存在? 一.解题思路 对于查找一个数组中元素是否存在,很多同学第一想法就是从头到尾遍历一遍.这样的想法优点是代码简单且无脑容易上手,但是这样的缺点也很明显,比如是m *n的数组,你从头到尾遍历,最坏情况要找m *n次.题目给的相关条件比如从左向右递增,从上向下递增你也完全没有使用,这样的暴力求解显然不是我们想看到的 我们来介绍一种方法

  • python模块shutil函数应用示例详解教程

    目录 本文大纲 知识串讲 1)模块导入 2)复制文件 3)复制文件夹 4)移动文件或文件夹 5)删除文件夹(慎用) 6)创建和解压压缩包 本文大纲 os模块是Python标准库中一个重要的模块,里面提供了对目录和文件的一般常用操作.而Python另外一个标准库--shutil库,它作为os模块的补充,提供了复制.移动.删除.压缩.解压等操作,这些 os 模块中一般是没有提供的.但是需要注意的是:shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile这两个模块来进行的. 知识串

  • Go语言基础Json序列化反序列化及文件读写示例详解

    目录 概述 JSON序列化 结构体转JSON map转JSON 切片转JSON JSON反序列化 JSON转map JSON转结构体 JSON转切片 写JSON文件 map写入JSON文件 切片写入JSON文件 结构体写入JSON文件 读JSON文件 解码JSON文件为map 解码JSON文件为切片 解码JSON文件为结构体 示例 概述 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的.键值对的数据交换格式.结构由大括号'{}',中括

  • Go语言基础for循环语句的用法及示例详解

    目录 概述 语法 注意 示例一  死循环,读取文件 示例二  打印乘法表 示例三  遍历字符串,数组,map 概述 for循环是一个循环控制结构,可以执行指定次数的循环 语法 第一种 for {} //无线循环 第二种 for 条件语句{} 第三种 for 初始语句; 条件语句; 迭代后语句 {} 第四种 for key,value:=range 表达式/变量{} 注意 省略初始条件,相当于while循环体必须用 { } 括起来初始化语句和后置语句是可选的如果只剩下条件表达式了,那么那两个分号也

  • Go语言基础switch条件语句基本用法及示例详解

    目录 概述 语法 第一种[switch 带上表达式] 第二种[switch 不带表达式] 第三种[switch 初始化,表达式] 注意 示例一[根据今天的日期打印今天星期几] 示例二[根据分数打印A,B,C,D] 示例三[算数] 概述 传入条件的不同,会执行不同的语句 每一个case分支都是唯一的,从上到下逐一测试,直到匹配为止. 语法 第一种[switch 带上表达式] switch 表达式 { case 表达式1,表达式2, ... : 语句块1 case 表达式3, 表达式4, ... :

  • socket编程之bind()函数使用示例详解

    目录 正文 端口号具体是怎么绑定 老代码 端口被占用的问题解决 正文 当你创建了socket之后,你会想要把这个socket和你本机上的某个端口号(port)进行关联. 端口号是内核用来确认将收到的数据包交给哪个具体进程的socket descriptor的依据. 通常在写服务端程序的时候我们才需要进行关联,客户端程序不需要我们手动绑定端口,直接connect()就好了. 端口号具体是怎么绑定 #include <sys/types.h> #include <sys/socket.h&g

随机推荐