CC++中的输⼊与输出及如何读取⼀⾏⽂本
在使⽤C/C++进⾏编程的过程中,经常会遇到输⼊输出的问题。
对于C语⾔中,
1. 格式化输⼊输出。
在C语⾔中,最常⽤的格式化输⼊输出是scanf和printf函数。
和这两个函数对应的更安全的函数是fscanf和fprintf:指定⽂件指针
对于字符串的处理还有sscanf和sprintf:指定字符串
声明如下:
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
2. 字符输⼊输出
出了这些格式化输⼊输出函数之外,还有很多针对字符输⼊输出的函数:
包括getc,getchar,gets,fgetc,fgets,putc,putchar,puts,fputc,fputs。
⾸先单个字符输⼊/输出函数对应的声明如下:
int fgetc(FILE *stream); int getc(FILE *stream);
从⽂件中读⼊⼀个字符,返回值就是读⼊的字符,如果错误返回EOF。
这两个函数具有相同的效果,但是getc是宏,⽽fgetc是函数。程序员常⽤这个宏,因为它⽐调⽤函数更快。
int fputc(int c,FILE*stream); int putc(int c,FILE*stream);
输出字符到⽂件。返回输出的字符(转化为int型),如果错误返回EOF。
putc也是宏实现的。
int getchar(void),int putchar(int c)
这两个也是宏实现,主要是从标准输⼊输出读取或输出字符。等同于getc(stdin)和putc(c,stdout)
其次是多个字符/字符串的输⼊/输出函数对应的声明:
char *fgets(char *s, int size, FILE *stream);char *gets(char *s);
读⼊字符串,fgets适合取代gets,因为gets⽆法限制读取字符的个数。gets是直接从标准输⼊读取。
fgets从流中读⼊最多n-1个字符,最后加⼀个空字符作为字符串结尾标记。如果在读到最⼤个数的字符之前遇到了⼀个换⾏字符或者⽂件结尾,那么只有⽬前所读⼊的字符会被放⼊到缓冲区中,如果读到换⾏符'\n',那么此字符也会被放⼊到缓冲区中。
返回值为读⼊的字符串,如果出错,返回值为NULL
int fputs(const char *s,FILE*stream); int puts(const char*s);
返回输出的字符的个数,如果出错,返回EOF。
需要注意的是fgets保留换⾏符'\n',⽽gets是从stdin输⼊,在读取字符串时会删除结尾的换⾏符'\n';
同样,fputs写⼊时不包括换⾏符,⽽puts在写⼊字符串时会在末尾添加⼀个换⾏符。
3. ⼆进制输⼊输出
对于⼆进制的输⼊输出,主要采⽤fread和fwrite函数,这个⽐较单⼀。
声明如下:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
其中ptr是缓冲区指针,size是读取的元素的个数,nmemb是元素的⼤⼩(sizeof)
返回值是正确读写的字节数,如果出错或达到⽂件末尾eof,返回⼀个⼩的值或0
必须⾃⼰判断⽂件结尾还是出错,分别使⽤feof函数和ferror函数
对于C++语⾔,
采⽤的是输⼊输出流来进⾏的。由于C++是⾯向对象语⾔,所以C++中采⽤的是流类。
下图是C++的⼀个类继承⽅式:
可以看到cin,cout,ifstream,ofstream,istringstream,ostringstream是对应的输⼊输出类。⽽fstream和stringstream类是可以同时进⾏输⼊和输出。
1. cin,ifstream和istringstream都是从istream继承⽽来,所以,我们可以分析⼀下istream类的成员函数:
对于istream,可以分为格式化输⼊和⾮格式化输⼊两种形式:
(1)格式化输⼊
采⽤的时候对操作符>>的重载。并且操作符>>在对待输⼊上遇到空格就停⽌。
(2)⾮格式化输⼊
分为对于字符/字符串的输⼊和对于字节的输⼊,包括的函数主要有get,getline,read,readsome,peek等。
其中get是获取⼀个字符,getline是获取⼀⾏字符。read和readsome是读⼊字节。
get函数的声明如下:
int get();
istream& get ( char& c );
istream& get ( char* s, streamsize n );
istream& get ( char* s, streamsize n, char delim );
istream& get ( streambuf& sb);
istream& get ( streambuf& sb, char delim );
可以从输⼊设备获得⼀个字符,也可以读取字符串。默认采⽤'\n'作为分隔符。
使⽤get函数时,get函数与getline接受的参数相同,解释参数的⽅式也相同,并且都读取到⾏尾,但是get不再读取并丢弃换⾏符,⽽是将其留在输⼊队列中。所以经常出问题。由于第⼀次调⽤后,换⾏符留在队列中,因此第⼆次调⽤时看到第⼀个字符边是换⾏符,因此get认为已经到达队尾,⽽没有发现任何可读取的内容。如果不借助于帮助,get将不能跨过该换⾏符。可以采⽤get的另⼀种重载的形式来读取这个换⾏符,然后为下⼀⾏的输⼊做好准备。
但是对于空⾏get经常出问题。当get读取空⾏后将设置失效位(failbit),这意味着接下来的输⼊将被阻断,但可以⽤下⾯的命令来恢复输⼊。
cin.clear();
getline函数的声明如下:
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
从输⼊读⼊字符串到s中,n是缓冲区最⼤容量。默认采⽤'\n'作为分隔符。
read和readsome函数的声明如下:
istream& read ( char* s, streamsize n );
streamsize readsome ( char* s, streamsize n );
这两个函数不是很熟悉。之前很少遇到过。
read()⽅法从缓冲区或设备读取指定长度的字节数,返回对⾃⾝的引⽤.
⽽readsome()⽅法只能从缓冲区中读取指定长度字节数,并返回实际已读取的字节数.
⽐如:
const int LEN = 20;
char chars[ LEN + 1 ] = {0};
ifstream in( fileName );
cout << chars << endl;
cout << chars << endl;
⽽有时候想要从设备读取指定长度的数据,但⼜要知道实际读取的长度,这时候就要⽤另⼀个⽅法: gcount()
它返回⾃上次读取以来所读取的字节数,因此可以这样得到实际读取的长度.
int count = 0;
count = in.gcount();
write的返回值cout << "Read in " << count << " chars : " << chars << endl;
实际上,readsome()也是调⽤read()和gcount()来实现的.
C++为了采⽤string类⽽引⼊了⼀个全局的输⼊函数getline,其参数是string类型的:
istream& getline ( istream& is, string& str, char delim );
istream& getline ( istream& is, string& str );
这个函数还是⾮常有⽤的。为什么会出现这个getline函数呢?原因:cin是istream的⼀个对象,line()中的getline()也就是istream的⼀个成员函数,在string被加⼊到c++很久以前,istream就已经存在了,所以,参数针对的是数组类型的存储,⽽没有string。
2. cout,ofstream和ostringstream都是从ostream继承⽽来,所以,我们可以分析⼀下ostream类的成员函数:
ostream也是分为格式化和⾮格式化输出,与istream对应的。
(1)格式化输出
采⽤对操作符<<;重载的⽅式。
(2)⾮格式化输出
主要包括put函数和write函数两个。put函数输出⼀个字符,write函数输出字节。
相⽐输⼊istream,输出ostream中的相关函数少了很多,其实主要是因为输出相⽐输⼊更简单,输出操作符<<;可以解决到⼤部分情况。put函数
ostream& put ( char c );
write函数
ostream& write ( const char* s , streamsize n );
3. 在使⽤这些函数的时候,⼀个主要的问题是如何判断输⼊是否完成,即循环的控制条件该怎么写?
C++中是通过判断输⼊流的状态来得到输⼊是否完成或出错的。
下⾯的就是⼏个相关的函数:good,eof,fail,bad
(1) good函数
bool good ( ) const;
检查输⼊流是否良好,可否继续进⾏输⼊。主要检查流的3个状态标志:eofbit, failbit 和badbit
(2) eof函数
bool eof ( ) const;
检查eofbit标志。⽤于测试是否达到⽂件末尾(EOF)
(3) fail函数
bool fail ( ) const;
检查failbit和badbit。测试是否出现输⼊错误。
(4) bad函数
bool bad ( ) const;
检查badbit。检查是否出错。
所以在具体的使⽤中,可以使⽤good函数来作为循环的判断条件。
所以,我们总结⼀下在C/C++中读取⼀个字符或字符串可以采⽤的⽅式。
1. ⾸先,读取⼀个字符:
C语⾔⽅式:
(1).采⽤getchar从stdin输⼊
while((c=getchar())!=EOF)
putchar(c);
(2). 采⽤fgetc/getc输⼊
while((c=fgetc(stdin))!=EOF)
fputc(c,stdout);
或
while((c=getc(stdin))!=EOF)
putc(c,stdout);
C++语⾔⽅式:
(1).采⽤重载操作符>>
while(cin>>c)
cout<<c<<endl;
这种形式会跳过所有的空⽩符,包括空格,换⾏,制表符
(2). 采⽤get函数
char c;
d())
{
();
d())//这⼉就是判断是否读⼊了有效的字符
cout<<c;
}
这⼉可以读⼊任何字符。
或者
char c;
while((())!=-1)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论