文章目录
一、输入输出流的插入和提取运算符
题目描述
首先建立文本文件digit.txt,然后向文件写入个以空格分开的数字字符,最后再将10个字符从文件上读出到屏幕上
C++代码实现
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//opent the file with way writing
fstream testfile("file.txt",ios::out | ios::in);
if(!testfile.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
//start to write
for(int i = 0; i <10;i ++)
{
testfile<<i<<endl;
}
//start to read the information
int num;
testfile>>num;
cout<<num;
while(!testfile.eof())
{
cout<<num<<" ";
testfile>>num;
}
cout<<endl;
testfile.close();
return 0;
}
实际运行结果
问题分析
- 打开失败,“ios::out ”不是说明文件不存在会自动创建吗?虽然“ios::in”要求文件必须存在。最终妥协了,既然整合了,还是一个文件必须存在为基础
修改
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//opent the file with way writing
fstream testfile("file.txt",ios::out);
if(!testfile.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
//start to write
for(int i = 0; i <10;i ++)
{
testfile<<i<<endl;
}
testfile.close();
fstream infile("file.txt",ios::in);
int num;
infile>>num;
while(!infile.eof())
{
cout<<num<<" ";
infile>>num;
}
cout<<endl;
infile.close();
return 0;
}
分析与总结
- 写入的时候明明指明的是数字与数字之间是以换行符为分割的,但是读入的时候,就啥都没了。
- ">> " 读入的时候,会自动忽略换行、空格、制表等空白字符
偶然间的困惑,我想去证明
1、一个IO流对象打开时制定了读写两种方式,会有两个指针
- 即使指定文件的打开方式为“ios::in | ios::out”,写已经到达了尾指针,如果还继续输出,那就移动指针到文件的头部,继续输出
- 证明如下:
- 注意:这里的文件已经提前创建过了
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
//opent the file with way writing
fstream testfile("file.txt",ios::out|ios::in);
if(!testfile.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
//start to write
for(int i = 0; i <10;i ++)
{
testfile<<i<<endl;
}
int num;
testfile>>num;
if(!testfile.eof())
{
cout<<"two pointers"<<endl;
cout<<num<<" ";
testfile>>num;
}
else
{
cout<<"only one pointer!"<<endl;
}
cout<<endl;
testfile.close();
return 0;
}
分析
- 这里将读写两个模式综合到一块,该文件指针同时是读指针也是写指针,将内容写完之后,写指针自动的在文件的末尾,然后再开始读。
- 如果可以读出来,那就说明有两个的指针
- 如果读不出来,就说明读写指针是同一个指针,同时到达末尾
移动指针后
- 运行结果
二、get函数和put函数
get()函数
- 用于从输入设备中获取一个字符型数据
- 特点:可以读取任何类型的数据,包括空格、回车、制表符等空白字符
- 函数类型
- 有参函数get(char ch):
- 将获取到的字符保存到对应的ch中
- 返回值为bool型,如果读取成功,就返回true;如果读取失败,就返回false
- 无参函数get():
- 将读取的字符型数值作为返回值返回,char ch = get()
- 有参函数get(char ch):
程序实例一——可以读取任何类型的数据
#include <iostream>
using namespace std;
int main()
{
//4-4
int n = 0;
char ch;
cout<<"please input some chars ,ending with enter!"<<endl;
while((ch = cin.get())!= '\n')
{
cout<<ch;
n ++;
}
cout<<endl;
cout<<"the number od the chars is "<<n<<endl;
cout << "Hello world!" << endl;
return 0;
}
无参版本
#include <iostream>
using namespace std;
int main()
{
//4-4
int n = 0;
char ch;
cout<<"please input some chars ,ending with enter!"<<endl;
while(1)
{
cin.get(ch);
if(ch == '\n')
{
break;
}
cout<<ch;
n ++;
}
cout<<endl;
cout<<"the number od the chars is "<<n<<endl;
cout << "Hello world!" << endl;
return 0;
}
程序实例二——文件类读入和读出
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int n1 = 0;
char ch1;
fstream outfile("filetest.txt",ios::out);
outfile<<"Microsoft\nVisual\nC++";
outfile.close();
fstream infile("filetest.txt",ios::in);
while(!infile.eof())
{
ch1 = infile.get();
cout<<ch1;
n1 ++;
}
cout<<endl;
cout<<"the numnber of the characters of the file is "<<n1<<endl;
infile.close();
return 0;
}
分析总结
- 使用get函数逐个读取字符,可以很好的根据输入的结果进行的判定程序的是否进行读取
- 判定是否已经到达文件的末尾的方式
- 使用无参函数,(ch = in.get()) == EOF; 判定是否等于EOF,默认的文件输出的末尾
- 使用有参函数,if(in.get(ch)),到达文件的末尾一定数读取失败,返回值为false
put()函数
知识点
- 用于输出单个字符型的数据
- 特点:
- 返回类型:是指向的该函数输出流对象。便于连续调用进行输出
- 对<<的重定义方式为:outstream& operator<<(char)
输入流的getline()函数
基本介绍
C++实例实现
标准输入和输出
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
int main()
{
int len , maxlen = 0;
char s[8],t[8];
cout<<"please input some arrays of characters:"<<endl;
while(cin.getline(s,8))
{
len = (int)strlen(s);
if(len>maxlen)
{
maxlen = len;
strcpy(t,s);
}
}
cout<<endl;
cout<<"the longest array of the characters is:"<<t<<endl;
cout<<"the length is "<<maxlen<<endl;
return 0;
}
- 文件输入和输出
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
int main()
{
int len, maxlen = 0;
char s[80],t[90];
fstream outfile;
outfile.open("filetest1.txt",ios::out);
if(!outfile.is_open())
{
cout<<"open the file with writing is wrong!"<<endl;
return 0;
}
outfile<<"Windows Xp"<<endl;
outfile<<"Visual Studio "<<endl;
outfile<<"Microsoft Office"<<endl;
outfile.close();
fstream infile("filetest1.txt",ios::in);
if(!infile.is_open())
{
cout<<"reading the file error!"<<endl;
return 0;
}
while(infile.getline(s,sizeof(s)))
{
len = (int)strlen(s);
if(len>maxlen)
{
maxlen = len;
strcpy(t,s);
}
}
cout<<"the longest array of characters is:"<<t<<endl;
cout<<"the length of the array is:"<<maxlen<<endl;
infile.close();
return 0;
write函数
功能描述
- 向输出设备输出指定个数的多个字符的操作
- out.write(字符型的指针,字节数);
- 返回类型:io流的具体的对象,可以连续的调用
- 参数列表:注意第一个参数是字符型指针,要进行强制类型转换
C++代码相关实验
文本输入和二进制输入的方式对比
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
int main()
{
int a = 123445;
fstream outascii("file.txt",ios::out);
fstream outbinary("file2.txt",ios::out | ios::binary);
outascii<<a;
outbinary.write((char*)&a,sizeof(a));
outascii.close();
outbinary.close();
return 0;
}
分析与总结
- 采用二进制进行数据保存,是将数据按照在内存中的保存形式进行保存。“int a = 1;”整型数据a占用四个字节,1翻译成32位的数据“0000 0000 0000 0000 0000 0000 0001”,保存到对应内存中
- 采用文本表示,会将的1按照ASCII码表进行的转换,转成对应的数字进行保存。程序中是5个数字,总共占用5个char型的内存空间,5个字节
read函数
功能描述
-
功能:用于获取多个字符的输出
-
使用:in.read(字符型指针,字符个数); 从输入设备中读取n个字符,存入到字符型指针所指的内存空间中
- 返回值:bool型,读取失败,返回false,读取成功,返回true
-
注意: *如果是以二进制文件的方式进行的输入,要写入对应的数据的内存中,大小为该数据的所占用的内存空间大小
C++相关实验的代码
- 从标准输入和输出中读取相关的数据
int main()
{
char *ch = new char[8];
cin.read(ch,7);
cout<<ch<<endl;
return 0;
}
- 从文件中读取相关的数据
int main()
{
char *ch = new char[8];
fstream infile("file.txt",ios::in);
if(!infile.is_open())
{
cout<<"open the file abortively!"<<endl;
}
infile.read(ch,4);
cout<<ch<<endl;
infile.close();
return 0;
}
分析总结
- read函数是可以读取空白字符地,其返回地特定数量的单个字符,不是字符串,末尾不会加上’\0’
- 其第一个参数是字符型地址,如果要将一个二进制文件写入其中,需要将地址进行强制类型转换。将数据写入到特定的内存空间中
write和read函数的总结
知识点
- read和write函数一般结合使用,进行二进制文件的读/写
- 使用write()函数生成二进制文件中的数据
- 使用read()函数来读取二进制文件中的数据
C++程序实例一
- 先向二进制文件中写入整型数据1~10,再将10个数据从文件读出并输出到屏幕上
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
int main()
{
//write ten number in the memory!
fstream outbin("binary.txt",ios::out|ios::binary);
if(!outbin.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
for(int i = 1;i < 11;i ++)
{
outbin.write((char*)&i,sizeof(i));
}
outbin.close();
//read the data from the memory
fstream inbin("binary.txt",ios::in|ios::binary);
if(!inbin.is_open())
{
cout<<"open the file abortively!"<<endl;
}
//problem:how to read one num or all num?
for(int i = 0;i < 10;i ++)
{
inbin.read((char*)&i,sizeof(4));
cout<<i<<endl;
}
return 0;
}
分析与总结
- 最后的从文件中读入数据,直接根据返回值判定是否已经读取完毕,毕竟计数不是很方便
C++程序实例二
- 首先将3名学生的学号、姓名和成绩写入二进制文件studentinfo.dat中,然后在将该文件中的数据读到结构体数组中,并将其输出到屏幕上
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
typedef struct Student
{
char num[10];
char name[20];
int score;
};
int main()
{
//write the data into the file
Student stu[3] = {
{
"1210101","gray",618},
{
"1608205","linux",746},
{
"1564789","installman",789}
};
fstream outfile("studentinfo.txt",ios::out | ios::binary);
if(!outfile.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
for(int i = 0;i < 3; i++)
{
outfile.write((char*)&stu[i],sizeof(stu[i]));
cout<<"import the data triumphantly!"<<endl;
}
outfile.close();
cout<<"complete the importation of the data!"<<'\n'<<endl;
//read the data from the file
Student stu1[3];
fstream infile("studentinfo.txt",ios::in|ios::binary);
if(!infile.is_open())
{
cout<<"open the file abortively !"<<endl;
return 0;
}
int i = 0;
while(infile.read((char*)&stu1[i],sizeof(stu1[i])))
{
cout<<"name:"<<stu1[i].name<<endl;
cout<<"num:"<<stu1[i].num<<endl;
cout<<"score:"<<stu1[i].score<<endl;
cout<<endl;
i ++;
}
infile.close();
return 0;
}
分析与总结
- 注意,当我们以二进制直接写入文件地时候,是可以直接以一个完整的文件为单位进行读出和写入的,没有必要一个一个的单独写入。但是要注意将之转换成的对应的字符指针型的数据格式
文件随机读写概述和相关函数
知识点
-
通过非顺序地移动指针实现对文件地随机读写
-
seekg和seekp
-
tellg和tellp
文件随机读写的实例
- 描述:将三名学生的学号、姓名和成绩写入二进制文件studentinfo.txt中,再将第二名学生的成绩改为627,最后从文件中读取第num个元素(用户从键盘上获取对应的输入)信息并将其输入到屏幕上
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
typedef struct Student
{
char num[10];
char name[20];
int score;
};
int main()
{
//write the data into the file
Student stu[3] = {
{
"1210101","gray",618},
{
"1210102","linux",746},
{
"1210103","installman",789}
};
fstream outfile("studentinfo.txt",ios::out | ios::binary);
if(!outfile.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
for(int i = 0;i < 3; i++)
{
outfile.write((char*)&stu[i],sizeof(stu[i]));
cout<<"import the data triumphantly!"<<endl;
}
outfile.close();
cout<<"complete the importation of the data!"<<'\n'<<endl;
//read the data from the file
Student stu1[3];
fstream infile("studentinfo.txt",ios::in|ios::binary|ios::out);
if(!infile.is_open())
{
cout<<"open the file abortively !"<<endl;
return 0;
}
stu[1].score = 627;
//move the pointer of the file out stream to the position of the second element
infile.seekp(1*sizeof(Student),ios::beg);
//rewrite the data to the same position.Cover the old one!
infile.write((char*)&stu[1],sizeof(Student));
infile.close();
//test whether write the message into the file!
int num;
cout<<"the number of the student you want to check!"<<endl;
cin>>num;
if(num>3|num<1)
{
cout<<"the student you want to check is inexistence!"<<endl;
return 0;
}
//open the file to show the message of the student!
fstream infile1("studentinfo.txt",ios::in|ios::binary);
if(!infile1.is_open())
{
cout<<"open the file abortively!"<<endl;
return 0;
}
Student test;
//move the pointer of the file to the correct position!
infile1.seekg((num - 1)*sizeof(Student),ios::beg);
//read the information of the appointed student
infile1.read((char*)&test,sizeof(Student));
cout<<"No:"<<num<<"student:"<<endl;
cout<<"no:"<<test.num<<endl;
cout<<"name:"<<test.name<<endl;
cout<<"score:"<<test.score<<endl;
infile1.close();
return 0;
}
分析与总结
- 一般不在文件中的进行非顺序的插入和移动指针操作,因为比较耗时
自定义类型数据的标准输入输出和文本文件的输出输入
概述
- 通过对"<<“和”>>"的运算符重载,实现用户可以通过调用直接输出自定义类型的数据
- 注意上述的两个运算符是双目运算符,需要两个参数,一个是调用该函数的输入和输出流,一个数需要输出的数据
程序实例
typedef struct Student
{
char num[10];
char name[20];
int score;
};
//the overload of <<
ostream& operator<<(ostream& out,Student stu)
{
out<<"name:"<<stu.name<<endl;
out<<"num:"<<stu.num<<endl;
out<<"score:"<<stu.score<<endl;
return out;
}
//the overload of >>
istream& operator>>(istream& in,Student stu)
{
in>>stu.num>>stu.name>>stu.score;
return in;
}
- 剩余部分参见之前的代码