前言
此文是FishC大佬第四堂课的内容小结,学到了很多,来总结一下。
文件操作
C语言版本
利用C语言编写一个文件复制的程序,如下所示。
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
/*
argc和argv[]
在程序中,main函数有两个参数,整型变量argc和字符指针数组argv[]。
argc的含义是程序的参数数量,包含本身。
argv[]的每个指针只想命令行的一个字符串,所以argv[]指向字符串“copyFile.exe”
argv[1]指向字符串sourceFile,argv[2]只想字符串destFile。
*/
{
FILE *in, *out; //in和out是我们声明的两个文件指针,它们的类型都是FILE*,分别作为两个I/O流对象使用。
int ch; // char
if( argc != 3 )
{
fprintf( stderr, "输入形式: copyFile 源文件名 目标文件名 \n" );
exit( EXIT_FAILURE );
}
if( ( in = fopen( argv[1], "rb") ) == NULL )
/*
通过fopen()函数我们以二进制的形式按照可读/可写方式打开两个文件
并返回两个文件指针给in和out
*/
{
fprintf( stderr, "打不开文件: %s \n", argv[1] );
exit( EXIT_FAILURE );
/*
为了确保文件成功打开,我们还对fopen()的返回值进行了检查,
如果未成功打开,我们就向标准错误流stderr发送一条消息。
*/
}
if( ( out = fopen( argv[2], "wb") ) == NULL )
{
fprintf( stderr, "打不开文件: %s \n", argv[2] );
fclose( in ); // 记得擦屁股
exit( EXIT_FAILURE );
}
while( (ch = getc(in)) != EOF ) // EOF == end of file
/*
getc()函数一次从输入流(stdin)读取一个字符
putc()函数把这个字符写到输出流(stdout)
*/
{
if( putc( ch, out ) == EOF )
{
break;
}
}
if( ferror( in ) )
{
printf("读取文件 %s 失败! \n", argv[1] );
}
if( ferror( out ))
{
printf("写入文件 %s 失败! \n", argv[2] );
}
printf("成功复制1个文件!\n");
fclose( in );
fclose( out );
return 0;
}
没什么好特别说明的,注释已经写到了程序当中。
C++版本
基本的文件读写操作:
ifstream in;
in.open("test.txt")
以及
ofstream out;
out.open("test.txt")
以上代码在创建一个ifstream和ofstream类的对象时,将文件的名字传递给它们的构造函数。
下面给出一个接收两个参数的实例:
ifstream in(char* filename,int open_mode)
其中:filename表示文件的名称,它是一个字符串;open_mode表示打开模式,其值用来定义以怎么样的方式打开文件(跟open的参数一样)
下面给出几种常见的打开模式:
ios::in -- 打开一个可读取文件
ios::out -- 打开一个可写入文件
ios::binary -- 以二进制的形式打开一个文件。
ios::app -- 写入的所有数据将被追加到文件的末尾。
ios::trunc -- 删除文件原来已经存在的内容
ios::nocreate -- 如果要打开的文件并不存在,那么以此参数调用open函数将无法进行。
ios::noreplace -- 如果要打开的文件已经存在,那么试图以此参数调用open函数将返回一个错误。
如果需要不只是一种打开方式,而是需要多种打开模式的话,可以用 OR操作符: |
而为什么可以使用OR操作符来选择多种打开模式呢,来看一段栗子:
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
fstream fp("test.txt", ios::in | ios::out );
if( !fp )
{
cerr << "打开文件失败!" << endl;
return 0;
}
fp << "IloveFishc.com!";
static char str[100];
fp.seekg(ios::beg); // 使得文件指针指向文件头 如果ios::end 则是文件尾。
fp >> str;
cout << str << endl;
fp.close();
return 0;
}
其中利用 | 选择了ios::in 和ios::out 两种打开模式,我们首先编译这段程序,然后右键ios::in 选择转到定义,可以看到ios_base.h文件,其中可以看到如下定义:
typedef _Ios_Openmode openmode;
/// Seek to end before each write.
static const openmode app = _S_app;
/// Open and seek to end immediately after opening.
static const openmode ate = _S_ate;
/// Perform input and output in binary mode (as opposed to text mode).
/// This is probably not what you think it is; see
/// http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch27s02.html
static const openmode binary = _S_bin;
/// Open for input. Default for @c ifstream and fstream.
static const openmode in = _S_in;
/// Open for output. Default for @c ofstream and fstream.
static const openmode out = _S_out;
/// Open for input. Default for @c ofstream.
static const openmode trunc = _S_trunc;
以及:
enum _Ios_Openmode
{
_S_app = 1L << 0,
_S_ate = 1L << 1,
_S_bin = 1L << 2,
_S_in = 1L << 3,
_S_out = 1L << 4,
_S_trunc = 1L << 5,
_S_ios_openmode_end = 1L << 16
};
可以发现定义成了一个枚举类型,其中1作为long int处理,占4byte,在此基础上,将1二进制左移不同的位数,在使用时进行OR操作的话具有唯一性。
输入数据合法性检查
cin对象有几个专门用来报告其工作情况的成员函数,它们将返回一个真/假值来表明cin的状态。
-eof() : 如果到达文件(或输入)末尾,那么返回True;
-fail() : 如果cin无法工作,返回True;
-bad() : 如果cin因为比较严重的原因(例如内存不足)而无法工作,返回True;
-good() : 如果上述情况均未发生,返回True。