北京大学MOOC C++学习笔记(六)输入输出和文件操作

输入输出相关的类

与输入输出流操作相关的类:

  • istream是用于输入的流类,cin就是该类的对象。
  • ostream是用于输出的流类,cout就是该类的对象。
  • ifstream是用于从文件读取数据的类。
  • ofstream是用于向文件写入数据的类。
  • iostream是既能用于输入,又能用于输出的类。
  • fstream 是既能从文件读取数据,又能向文件写入数据的类。

标准流对象:

  • 输入流对象: cin 与标准输入设备相连
  • 输出流对象:cout 与标准输出设备相连   cerr 与标准错误输出设备相连      clog 与标准错误输出设备相连

缺省情况下,cerr << "Hello,world" << endl;
                      clog << "Hello,world" << endl;
                      cout << “Hello,world” << endl; 一样

  • cin对应于标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据。
  • cout对应于标准输出流,用于向屏幕输出数据,也可以被重定向为向文件写入数据。
  • cerr对应于标准错误输出流,用于向屏幕输出出错信息,
  • clog对应于标准错误输出流,用于向屏幕输出出错信息,
  • cerr和clog的区别在于cerr不使用缓冲区,直接向显示器输出信息;而输出到clog中的信息先会被存放在缓冲区,缓冲区满或者
    刷新时才输出到屏幕。

判断输入流结束:

可以用如下方法判输入流结束:

int x;
while( cin>>x ){
    …..
} }
return 0;

其实现的原理是:

 istream &operator >>(int & a)
{
…….
return *this ;
}

  • 如果是从文件输入,比如前面有freopen(“some.txt”,”r”,stdin);那么,读到文件尾部,输入流就算结束。
  • 如果从键盘输入,则在单独一行输入 Ctrl+Z 代表输入流结束

istream类的成员函数

istream & getline(char * buf, int bufSize);
从输入流中读取bufSize-1个字符到缓冲区buf,或读到碰到‘\n’为止(哪个先到算哪个)。
istream & getline(char * buf, int bufSize,char delim);
从输入流中读取bufSize-1个字符到缓冲区buf,或读到碰到delim字符为止(哪个先到算哪个)。

两个函数都会自动在buf中读入数据的结尾添加\0’。,‘\n’或delim都不会被读入buf,但会被从输入流中取走。如果输入流中
‘\n’或delim之前的字符个数达到或超过了bufSize个,就导致读入出错,其结果就是:虽然本次读入已经完成,但是之后的读入就
都会失败了。
可以用 if(!cin.getline(…)) 判断输入是否结束

bool eof(); 判断输入流是否结束
int peek(); 返回下一个字符,但不从流中去掉.
istream & putback(char c); 将字符ch放回输入流
istream & ignore( int nCount = 1, int delim = EOF );从流中删掉最多nCount个字符,遇到EOF时结束。

输出重定向

#include <iostream>
using namespace std;
int main() {
    int x,y;
    cin >> x >> y;
    freopen("test.txt","w",stdout); //将标准输出重定向到 test.txt文件
    if( y == 0 ) //除数为0则在屏幕上输出错误信息
        cerr << "error." << endl;
    else
        cout << x /y ; //输出结果到test.txt
    return 0;
}

输入重定向

#include <iostream >
using namespace std;
int main() {
    double f;  int n;
    freopen(“t.txt”,“r”,stdin); //cin被改为从 t.txt中读取数据
    cin >> f >> n;
    cout << f << "," <<n << endl;
    return 0;
}

流操纵算子

  •  整数流的基数:流操纵算子dec,oct,hex,setbase
  •  浮点数的精度(precision,setprecision)
  • 设置域宽(setw,width)
  • 用户自定义的流操纵算子

使用流操纵算子需要 #include <iomanip>

  • 整数流的基数:流操纵算子

int n = 10;
cout << n << endl;
cout << hex << n << “\n”<< dec << n << “\n”<< oct << n << endl;
输出结果:
10 

10
12

  • precision, setprecision

 precision是成员函数,其调用方式为:
 cout.precision(5);
 setprecision 是流操作算子,其调用方式为:
 cout << setprecision(5); // 可以连续输出
它们的功能相同。
指定输出浮点数的有效位数(非定点方式输出时)
指定输出浮点数的小数点后的有效位数(定点方式输出时)
定点方式:小数点必须出现在个位数后面

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    double x = 1234567.89,y = 12.34567;
    int n = 1234567;
    int m = 12;
    cout << setprecision(6) << x << endl<< y << endl << n << endl << m;
}

浮点数输出最多6位有效数字

输出:
1.23457e+006
12.3457
1234567
12

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    double x = 1234567.89,y = 12.34567;
    int n = 1234567;
    int m = 12;
    cout << setiosflags(ios::fixed) <<setprecision(6) << x << endl<< y << endl << n << endl << m;
}

以小数点位置固定的方式输出

输出:
1234567.890000
12.345670
1234567
12

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    double x = 1234567.89;
    cout << setiosflags(ios::fixed) <<setprecision(6) << x << endl <<
resetiosflags(ios::fixed) << x ; //取消以小数点位置固定的方式输出
}

输出:
1234567.890000
1.23457e+006

#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    int n = 141;
    //1) 出 分别以十六进制、十进制、八进制先后输出 n
    cout << "1) " << hex << n << " " << dec << n << " " << oct << n << endl;
    double x = 1234567.89,y = 12.34567;
    //2)  保留5 位有效数字
    cout << "2) " << setprecision(5) << x << " " << y << " " << endl;
    //3)  保留小数点后面5 位
    cout << "3) " << fixed << setprecision(5) << x << " " << y << endl ;
    //4)  科学计数法输出,且保留小数点后面5 位
    cout << "4) " << scientific << setprecision(5) <<x << " " << y << endl ;
    //5)  非负数要显示正号,输出宽度为12 字符,宽度不足则用'*' 填补
    cout << "5) " << showpos << fixed << setw(12) << setfill('*') << 12.1
    << endl;
    //6)  非负数不显示正号,输出宽度为12 字符,宽度不足则右边用填充字符填充
    cout << "6) " << noshowpos << setw(12) << left << 12.1 << endl;
    //7)  输出宽度为12 字符,宽度不足则左边用填充字符填充
    cout << "7) " << setw(12) << right << 12.1 << endl;
    //8)  宽度不足时,负号和数值分列左右,中间用填充字符填充
    cout << "8) " << setw(12) << internal << -12.1 << endl;
    cout << "9) " << 12.1 << endl;
    return 0;
} 

1) 8d 141 215
2) 1.2346e+006 12.346
3) 1234567.89000 12.34567
4) 1.23457e+006 1.23457e+001

5) ***+12.10000
6) 12.10000****
7) ****12.10000
8) -***12.10000
9) 12.10000

文件读写

可以将顺序文件看作一个有限字符构成的顺序字符流,然后像对cin, cout 一样的读写。

创建文件

• #include <fstream> // 包含头文件
• ofstream outFile(“clients.dat”, ios::out|ios::binary);
//创建文件
– clients.dat” 要创建的文件的名字
– ios::out  文件打开方式
     • ios:out 输出到文件, 删除原有内容
    • ios::app 输出到文件, 保留原有内容,总是在尾部添加
– ios::binary 以二进制文件格式打开文件

1   也可以先创建ofstream对象,再用 open函数打开
ofstream fout;
fout.open("test.out",ios::out|ios::binary);
2   判断打开是否成功:
if(!fout){
cout << “File open error!”<<endl;
}
3    文件名可以给出绝对路径,也可以给相对路径。没有交代路径信息,就是在当前文件夹下找文件

文件的读写指针

  • 对于输入文件,有一个读指针;
  • 对于输出文件,有一个写指针;
  • 对于输入输出文件,有一个读写指针;
  • 标识文件操作的当前位置, 该指针在哪里,读写操作就在哪里进行。

ofstream fout("a1.out",ios::app); //以添加方式打开
long location = fout.tellp(); //取得写指针的位置
location = 10;
fout.seekp(location);  // 将写指针移动到第10个字节处
fout.seekp(location,ios::beg); //从头数location
fout.seekp(location,ios::cur); //从当前位置数location
fout.seekp(location,ios::end); //从尾部数location

//location 可以为负值

ifstream fin(“a1.in”,ios::ate);
//打开文件,定位文件指针到文件尾
long location = fin.tellg(); //取得读指针的位置
location = 10L;
fin.seekg(location); // 将读指针移动到第10个字节处
fin.seekg(location,ios::beg); //从头数location
fin.seekg(location,ios::cur); //从当前位置数location
fin.seekg(location,ios::end); //从尾部数location
// location 可以为负值

显式关闭文件

ifstream fin(“test.dat”,ios::in);
fin.close();
ofstream fout(“test.dat”,ios::out);
fout.close();

字符文件读写

因为文件流也是流,所以流的成员函数和流操作算子也同样适用于文件流。

写一个程序,将文件 in.txt 里面的整数排序后,输出到out.txt
例如,若in.txt 的内容为:
1 234 9 45 6 879
则执行本程序后,生成的out.txt的内容为:
1 6 9 45 234 879

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
    vector<int> v;
    ifstream srcFile("in.txt",ios::in);
    ofstream destFile("out.txt",ios::out);
    int x;
    while( srcFile >> x )
        v.push_back(x);
    sort(v.begin(),v.end());
    for( int i = 0;i < v.size();i ++ )
        destFile << v[i] << " ";
    destFile.close();
    srcFile.close();
    return 0;
}

二进制文件读写

 二进制读文件:

ifstream 和 fstream的成员函数:
istream& read (char* s, long n);
将文件读指针指向的地方的n个字节内容,读入到内存地址s,然后将文件读指针向后移动n字节 (以ios::in方式打开文件时,文件读指针开始指向文件开头) 。

二进制写文件:

ofstream 和 fstream的成员函数:
istream& write (const char* s, long n);
将内存地址s处的n个字节内容,写入到文件中写指针指向的位置,然后将文件写指针向后移动n字节(以ios::out方式打开文件时,文件写指针开始指向文件开头, 以ios::app方式打开文件时,文件写指针开始指向文件尾部 ) 。

在文件中写入和读取一个整数

#include <iostream>
#include <fstream>
using namespace std;
int main() {
    ofstream fout("some.dat", ios::out | ios::binary);
    int x=120;
    fout.write( (const char *)(&x), sizeof(int) );
    fout.close();
    ifstream fin("some.dat",ios::in | ios::binary);
    int y;
    fin.read((char * ) & y,sizeof(int));
    fin.close();
    cout << y <<endl;
    return 0;
}

从键盘输入几个学生的姓名的成绩,并以二进制文件形式保存

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
    char name[20];
    int score;
};
int main() {
    Student s;
    ofstream OutFile( "c:\\tmp\\students.dat",ios::out|ios::binary);
    while( cin >> s.name >> s.score )
    OutFile.write( (char * ) & s, sizeof( s) );
    OutFile.close();
    return 0;
}

将 students.dat 文件的内容读出并显示

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
    char name[20];
    int score;
};
int main() {
    Student s;
    ifstream inFile("students.dat",ios::in | ios::binary );
    if(!inFile) {
        cout << "error" <<endl;
    return 0;
    }
    while( inFile.read( (char* ) & s, sizeof(s) ) ) {
        int readedBytes = inFile.gcount(); // 看刚才读了多少字节
        cout << s.name << " " << s.score << endl;
    }
    inFile.close();
    return 0;
}

将 students.dat 文件的Jane的名字改成Mike

#include <iostream>
#include <fstream>
using namespace std;
struct Student {
    char name[20];
    int score;
};
int main()
{
    Student s;
    fstream iofile( "c:\\tmp\\students.dat",ios::in|ios::out|ios::binary);
    if( !iofile) {
        cout << "error" ;
        return 0;
    }
    iofile.seekp( 2 * sizeof(s),ios::beg); // 定位写指针到第三个记录
    iofile.write("Mike",strlen("Mike")+1);
    iofile.seekg(0,ios::beg); // 定位读指针到开头
    while( iofile.read( (char* ) & s, sizeof(s)) )
            cout << s.name << " " << s.score << endl;
    iofile.close();
    return 0;
}

文件拷贝程序mycopy 示例

/*用法示例:
mycopy src.dat dest.dat
即将 src.dat 拷贝到 dest.dat 如果 dest.dat 原来就有,则原来的文件会被覆
盖 */

#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char * argv[])
{
    if( argc != 3 ) {
        cout << "File name missing!" << endl;
        return 0;
    }
    ifstream inFile(argv[1],ios::binary|ios::in); // 打开文件用于读
    if( ! inFile ) {
        cout << "Source file open error." << endl;
        return 0;
    }
    ofstream outFile(argv[2],ios::binary|ios::out); // 打开文件用于写
    if( !outFile) {
        cout << "New file open error." << endl;
        inFile.close(); // 打开的文件一定要关闭
        return 0;
    }
    char c;
    while( inFile.get(c)) // 每次读取一个字符
        outFile.put(c); // 每次写入一个字符
    outFile.close();
    inFile.close();
    return 0;
}

二进制文件和文本文件的区别

Linux,Unix下的换行符号:‘\n’ (ASCII码: 0x0a)
Windows 下的换行符号:‘\r\n’ (ASCII码: 0x0d0a) endl 就是 '\n'
Mac OS下的换行符号: ‘\r’ (ASCII码:0x0d)
导致 Linux, Mac OS 文本文件在Windows 记事本中打开时不换行

Unix/Linux下打开文件,用不用 ios::binary 没区别

Windows下打开文件,如果不用 ios::binary,则:
读取文件时,所有的 '\r\n’会被当做一个字符'\n'处理,即少读了一个字
符'\r'。
写入文件时,写入单独的'\n'时,系统自动在前面加一个'\r',即多写了一
个'\r'

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MOOC(大规模开放式在线课程)是一种通过网络平台开设的在线教育课程,可以为广大学习者提供方便灵活的学习机会。人工智能实践:TensorFlow笔记,是由北京大学推出的一门针对人工智能领域的实践课程,旨在帮助学习者掌握使用TensorFlow框架进行深度学习的基本方法和技巧。 该课程的代码提供了一系列丰富的示例和实践项目,通过这些代码我们可以了解和掌握TensorFlow的使用方法。其中包括数据处理、模型构建、模型训练与评估等关键步骤。通过学习和实践,我们可以学会如何搭建神经网络模型,进行图像分类、文本生成等任务。 在这门课程中,北京大学的代码示例主要围绕深度学习的常用库TensorFlow展开,通过给出具体的代码实现,解释了每部分的原理和操作方法,帮助学习者理解基本概念和技术,熟悉TensorFlow框架和编程语言的使用。 此外,这门课程还涵盖了一些实践项目,例如基于TensorFlow的手写数字识别、图像分类与预测、文本生成等。通过完成这些实践项目,我们可以加深对TensorFlow的理解并提高实践能力。 总之,人工智能实践: TensorFlow笔记 - 北京大学代码是一门结合了理论与实践的在线课程,通过教授深度学习的基本概念和TensorFlow的应用方法,帮助学习者掌握人工智能领域的基本技能。通过这门课程,我们可以学习到TensorFlow的使用方法,掌握一定的实践能力,并将这些知识应用于实际项目当中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值