C++的输入、输出与文件

1、

C++的输入、输出分为基于控制台的输入/输出、基于文件的输入/输出和基于字符串的输入/输出。


在输入操作中,字节从设备(如键盘、磁盘)流向内存,称为输入流。

在输出操作中,字节从内存流向设备(如显示器、打印机、磁盘等)称为输出流。

C++还提供了无格式输入/输出和格式化输入/输出两种操作,无格式的传输速度快,格式化的按不同类型、不同格式对数据进行处理,不适合大容量的数据传输。

在C++中:iostream 定义了基于控制台的输入/输出类型,fstream定义了基于文件的输入/输出类型;sstream定义了基于字符串的输入/输出类型



2、输出输出的缓冲

当用户在键盘上输入数据时,在按了回车键后,输入的数据及回车键被传送到cin对象的缓冲区中,

当执行>>操作时,从cin对象缓冲区中取数据存入变量,如果缓冲区无数据,程序暂停,等待外围设备传送数据到cin缓冲区,<<操作时将数据放入输出缓冲区,如

os<<"please enter the value";

下面几种情况导致缓冲区的内容被刷新:

(1)、程序正常结束,main函数结束会清空所有的输出缓冲区

(2)、当缓冲区已满,在写入下一个值之前,会刷新缓冲区

(3)、用标准的操作符,如行结束符endl,显式地刷新缓冲区

(4)、可将输出流与输入流关联起来,在这种情况下,读输入流时刷新其相关联的输出缓冲区,在标准库中,将cout和cin关联在一起,因此每个输入操作都将刷新cout关联的缓冲区

基于控制台的输入输出

1、在C++中,如果输出的指针变量是一个指向字符的指针时,C++并不输出该指针中保存的地址,而是输出该指针指向的字符串,如果确实像输出这个指向字符的指针变量中保存的地址,可以用强制类型转换,将它转换成void *类型,事实上,如果程序员想输出地址,最好都把指针转换成void *类型。

#include<iostream>
using namespace std;
int main(void)
{
char *ptr="abcdef";
cout<<"ptr指向的内容为:"<<ptr<<endl;
cout<<"ptr中保存的地址为:"<<(void *)ptr<<endl;

return 0;
}


结果:

abcdef
0x440000

2、通过put成员函数进行字符输出

字符型数据还可以通过成员函数put来输出,put函数有一个字符类型的形式参数,它的返回值是调用put函数对象的引用。例如:

cout.put('A');

将字符A显示在屏幕上,而

cout.put(65);

输出ASCII码值为65的字符,输出也是字符A。

由于put函数的返回值是当前对象的引用,因此可以连续调用put函数:

cout.put('A').put('\n');

3、通过write成员函数进行无格式的输出

它有两个参数:第一个参数是一个指向字符的指针,表示一个字符数组;第二个参数是一个整型值,表示输出的字符的个数

例如:

char buffer[]="HAPPY BIRTHDAY";

cout.write(buffer,10);

输出buffer中的10个字节,函数调用

cout.write("adsfjlkl;weio",10);

显示了字母表中前10个字母

write函数在控制台输入/输出中的应用非常有限,它主要被用于文件访问。

4、通过get和getline成员函数进行字符和字符串的输入

get函数有3中格式,即不带参数、带1个参数和带3个参数

i;不带参数的个体函数从当前的输入流对象读入一个字符,包括空白字符以及表示文件结束的EOF,并将读入值作为函数的返回值返回如:

while((ch=cin.get())!=EOF) cout<<ch;

ii、get函数带一个参数它将输入流中的下一个字符存储在参数中,他的返回值是当前输入流对象的引用如:

cin.get(ch[0]);

for(i=0;ch[i]!='\n';i++)

cin.get(ch[i+1]);

ch[i]='\0';

iii、get函数有3个参数,即字符数组、数组规模和表示输入结束的结束符(结束符默认‘\n’)

get(ch,80,'\n'); 也可以用get(ch,80);

get(ch,80,'.');当遇到输入结束符“.”或输入字符数达到79时,函数执行结束,输入结束符没有放在字符数组中,而是保留在了输入流中,下一个和输入相关的语句会读入这个输入结束符get(ch,80,'.');

输入

abcdef.回车

则ch中存放字符串“abcdef”,而“.“仍保留在输入缓冲区中,如果继续调用cin.get(ch1)或cin>>ch1;则字符变量ch1中保存的是”.“

getline()函数功能和第三种形式的get函数类似,它也有3个参数,参数类型和作用与第三种形式的get函数完全相同,这两个函数的唯一区别是对输入结束符的处理,get函数将输入结束符留在输入流中,而getline函数将输入结束符从输入流中删除

5、通过read函数进行无格式的输入

char buffer[80];

cin.read(buffer,10);

不管输入缓冲区有多少个字节,都只读入10个字节,放入buffer。

#include<iostream>
using namespace std;
int main(void)
{
char buffer[80];
cout<<"enter a sentence:\n";
cin.read(buffer,20);
cout<<"\nThe crsentence entered was :\n";
cout.write(buffer,cin.gcount());
cout<<endl;
cout<<"一共输入了"<<cin.gcount()<<"个字符\n";
return 0;
}


结果:

enter a sentence:
erwwer
asdfsdf
sadf


The sentence entered was :
erwwer
asdfsdf
sadf


一共输入了20个字符
请按任意键继续. . .


格式化的输入、输出

输入、输出流中的整型默认为十进制表示,为了使流中的整形数不局限与十进制,可以插入hex操纵符将基数设为十六进制,插入oct操纵符将基数设为八进制,也可以插入dec操纵符将基数重新设为十进制。

改变输入输出流中整形数的基数也可以通过流操纵符setbase来实现,该操纵符有一个整形参数,它的值可以是16、10、8

#include<iostream>
#include<iomanip>
using namespace std;
int main(void)
{
int n;
cout<<"enter a octal number";
cin>>n;
cout<<"octal"<<oct<<n<<" in hexdecimal is :"<<hex<<n<<'\n';
cout<<"hexdecimal"<<n<<" in decimal is :"<<dec<<n<<'\n';
cout<<setbase(8)<<"octal"<<n<<"in octal is:"<<n<<endl;
return 0;
}


结果:

enter a octal number30
octal36 in hexdecimal is :1e
hexdecimal1e in decimal is :30
octal36in octal is:36
请按任意键继续. . .


设置浮点数的精度可以用precision来实现

设置域宽:cin>>sew(n)>>n

打印一个区域的操作:  cout<<n1<<tab<<n2<<endl;

文件和流:

C++文件没有记录,它只是把文件看成是字节序列,每一个文件以文件结束符(EOF)结束,这种文件称为流式文件,可以把将C++的文件看成一个字符串,只不过这个字符串不是放在内存中而是存放在外村中,不是以'\0'结束,而是用EOF结束。

C++文件又被分为ASCII文件和二进制文件,ASCII文件也被称为文本文件。二进制文件是指将每个字节仅看成是一个二进制位串,

ifstream是输入文件流类,当要从文件读取数据时,必须定义一个ifstream类的对象与之关联,ofstream是输出文件流类,当要向文件写数据时,必须定义一个ofstream类的对象与之关联。fstream类的对象即可以读也可以写,如:

ifstream in;

infile>>x; //可以将这个对象像cin一样使用。

文件打开模式:

in                      打开文件,做读操作

out                    打开文件,做写操作

app                   在文件尾后面添加

ate                    打开文件后,立即将文件定位在文件尾

trunc                 打开文件,清空文件

binary               以二进制模式进行输入、输出操作,默认为ASCII文件

========================================================

ifstream流对象默认以in模式打开,该模式只允许对文件执行读操作;与ofstream流关联的文件则以out模式打开,使文件可写,以out模式开始文件时,如果文件不存在,会自动创建一个空文件,否则将被打开的文件清空,丢弃该文件原有数据;对于fstream流关联的对象,默认打开方式是in|out,表示同时以in|out的方式打开,使文件即可读又可写,当同时以in 和out方式打开时,文件不会清空,如果ofstream的对象在打开时想要保存源文件中的数据,可以指定app模式打开,这样写入文件的数据将被添加到被添加到源文件数据后面。

*读入数据:

ifstream infile;

infile.open("file1");

也可以利用构造函数直接打开:

ifstream infile("file1");

ifstream infile("file1",ifstream::in);

*写入数据:

ofstream outfile;

outfile.open("file2");

也可以利用构造函数直接打开:

ofstream outfile("file1");

ofstream outfile("file1",ofstream::out);

*即可以读也可以写:

fstream iofile("file3");

显示打开:fstream iofile ("file3",fstream::in | fstream::out);  //这样不会清空数据

如果打开文件时定义了trunc模式,则无论是否指定in模式都会清空文件


如果文件打开成功,流对象会得到一个非0值,如果打开不成功,流对象将会得到值0,在打开文件后检查文件打开是否成功是一个良好的程序设计习惯;

当文件访问结束时,应该断开文件与文件流对象的关联,用  file.close();

文件的顺序访问

在读文件操作中,经常要判断文件是否结束,如果是使用>>或get函数读文件,可以通过检查>>的返回值是否为false或get函数读入的字符是否为EOF来判断,如果是使用read函数读文件,可以通过基类ios的成员函数eof来实现,eof不需要参数,返回一个整型值,当读操作遇到文件结束时,该函数返回true,否则返回false;

 #include<iostream>
#include<fstream>
using namespace std;
int main(void)
{
ofstream out("d:\\11.txt");//定义输出流,并与file关联
ifstream in;  //定义一个输入流
int i;
if(!out)
{
cerr<<"create file error\n";
return 1;
}
for(i=1;i<=10;i++)
{
out<<i<<' ';    //将1到10写到输出流对象
}
out.close();
in.open("d:\\11.txt");  //重新以in的方式打开文件file
if(!in)
{ 
cerr<<"open file error\n";
return 1;
}
while(in>>i)              //读文件,直到遇到文件结束
{
cout<<i<<' ';
}
in.close();
return 0;
}


1 2 3 4 5 6 7 8 9 10 请按任意键继续. . .

读取一个包含各种类型数据的文件操作的实例程序

#include<iostream>
#include<fstream>
using namespace std;
int main(void)
{
ifstream  fin("d:\\11.txt");
char s[80];
int i;
float x;

if(!fin)
{
cout<<"cannot open input file\n";
return 1;
}
fin>>i>>x>>s;
cout<<i<<" "<<x<<s<<endl;
fin.close();
return 0;
}


11.txt中内容:10 12.56"this is a file"

输出为:10 12.56"this

结果之所以这样,是因为在用流提取运算符读字符时是以空白字符作为结束符的,所以读到了“this”

如果要读入这个完整的字符串,可以其他的成员函数,如getline()----->fin>>i>>x>>getline(s,80,'\n')


文件随机处理

文件定位指针是一个long类型的数据,表示当前读写的是文件的第几个字节,ifstream和ofstream分别提供了成员函数tellg和tellp返回文件定位指针的当前位置,其中g表示get,p表示put,tellg返回读文件定位指针,tellp返回写文件定位指针。

当文件以in方式打开时,文件定位指针指向文件头,所以读文件是从头开始读的,当以out方式打开时,写文件定位指针也是定位在文件头,所以新写入的内容覆盖了文件原有信息。

ifstream和ofstream都提供了成员函数来重新设置文件定位指针,在ifstream,这个函数为seekg,在ofstream,这个函数为seekp,seekp和seekg函数有两个参数,第一个参数为long类型的整数,表示偏移;第二参数指定指针移动的参考的,ios::beg(默认)相对于流的开头,ios::cur相对于文件定位指针的当前位置,ios::end 相对于流结尾;如in.seekg(0)表示将读文件指针定位到输入流in的开始处,in.seekg(10,ios::cur)表示定位到输入流in当前位置后面的第10个字节。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值