目录
C++ cout.tellp()和cout.seekp()方法详解
cin.getline():C++读入一行字符串(整行数据)
入门
cin 就是 istream 类的对象,cout 是 ostream 类的对象,它们都声明在 <iostream> 头文件中,这也解释了“为什么在 C++ 程序中引入 <iostream> 就可以使用 cin 和 cout”(当然使用 cin 和 cout,还需要声明 std 命名空间)。
除此之外,<iostream> 头文件中还声明有 2 个 ostream 类对象,分别为 cerr 和 clog。它们的用法和 cout 完全一样,但 cerr 常用来输出警告和错误信息给程序的使用者,clog 常用来输出程序执行过程中的日志信息(此部分信息只有程序开发者看得到,不需要对普通用户公开)。
cout、cerr 和 clog 之间的区别如下:
- cout 除了可以将数据输出到屏幕上,通过重定向(后续会讲),还可以实现将数据输出到指定文件中;而 cerr 和 clog 都不支持重定向,它们只能将数据输出到屏幕上;
- cout 和 clog 都设有缓冲区,即它们在输出数据时,会先将要数据放到缓冲区,等缓冲区满或者手动换行(使用换行符 '\n' 或者 endl)时,才会将数据全部显示到屏幕上;而 cerr 则不设缓冲区,它会直接将数据输出到屏幕上。
除了以上 2 点特性上的不同之外,cerr、clog 和 cout 没有任何不同。之所以我们常用 cout,是因为 cerr 和 clog 有各自不同的适用场景。以 cerr 为例,一旦程序某处使用 cerr 输出数据,我们自然而然地会认为此处输出的是警告或者错误信息。
- istream:常用于接收从键盘输入的数据;
- ostream:常用于将数据输出到屏幕上;
- ifstream:用于读取文件中的数据;
- ofstream:用于向文件中写入数据;
- iostream:继承自 istream 和 ostream 类,因为该类的功能兼两者于一身,既能用于输入,也能用于输出;
- fstream:兼 ifstream 和 ofstream 类功能于一身,既能读取文件中的数据,又能向文件中写入数据。
例子:
#include <iostream>
using namespace std;
int main() {
char url[30] = {0};
//读取一行字符串
cin.getline(url, 30);
//输出上一条语句读取字符串的个数
cout << "读取了 "<<cin.gcount()<<" 个字符" << endl;
//输出 url 数组存储的字符串
cout.write(url, 30);
return 0;
}
程序执行结果为:
http://c.biancheng.net
读取了 23 个字符
http://c.biancheng.net
C++ cout.put():输出单个字符
put() 方法专用于向输出流缓冲区中添加单个字符,其语法格式如下:
ostream&put(char c);
其中,参数 c 为要输出的字符。
可以看到,该函数会返回一个 ostream 类的引用对象,可以理解返回的是 cout 的引用。
#include <iostream>
#include <string>
using namespace std;
int main(){
string str = "ten.gnehcnaib.c//:ptth";
for (int i = str.length() - 1; i >= 0; i--) {
cout.put(str[i]); //从最后一个字符开始输出
}
cout.put('\n');
return 0;
}
运行结果:
http://c.biancheng.net
除了使用 cout.put() 函数输出一个字符外,还可以用 putchar() 函数输出一个字符。putchar() 函数是C语言中使用的,在 <stdio.h> 头文件中定义,C++保留了这个函数,在 <iostream> 头文件中定义。
C++ cout.write():输出字符串
write() 成员方法专用于向输出流缓冲区中添加指定的字符串,初学者可以简单的理解为输出指定的字符串。其语法格式如下:
ostream&write(const char * s,streamsize n);
其中,s 用于指定某个长度至少为 n 的字符数组或字符串;n 表示要输出的前 n 个字符。
可以看到,该函数会返回一个 ostream 类的引用对象,可以理解返回的是 cout 的引用。
#include <iostream>
using namespace std;
int main() {
cout.write("http://", 7).write("c.biancheng.net", 15).write("/cplus/", 7);
return 0;
}
程序执行结果为:
http://c.biancheng.net/cplus/
C++ cout.tellp()和cout.seekp()方法详解
无论是使用 cout 输出普通数据,用 cout.put() 输出指定字符,还是用 cout.write() 输出指定字符串,数据都会先放到输出流缓冲区,待缓冲区刷新,数据才会输出到指定位置(屏幕或者文件中)。
值得一提的是,当数据暂存于输出流缓冲区中时,我们仍可以对其进行修改。ostream 类中提供有 tellp() 和 seekp() 成员方法,借助它们就可以修改位于输出流缓冲区中的数据。
C++ tellp()成员方法
tellp() 成员方法用于获取当前输出流缓冲区中最后一个字符所在的位置,其语法格式如下:
streampos tellp();
tellp() 不需要传递任何参数,会返回一个 streampos 类型值。事实上,streampos 是 fpos 类型的别名,而 fpos 通过自动类型转换,可以直接赋值给一个整形变量(即 short、int 和 long)。也就是说,在使用此函数时,我们可以用一个整形变量来接收该函数的返回值。
#include <iostream> //cin 和 cout
#include <fstream> //文件输入输出流
int main() {
//定义一个文件输出流对象
std::ofstream outfile;
//打开 test.txt,等待接收数据
outfile.open("test.txt");
const char * str = "http://c.biancheng.net/cplus/";
//将 str 字符串中的字符逐个输出到 test.txt 文件中,每个字符都会暂时存在输出流缓冲区中
for (int i = 0; i < strlen(str); i++) {
outfile.put(str[i]);
//获取当前输出流
long pos = outfile.tellp();
std::cout << pos << std::endl;
}
//关闭文件之前,刷新 outfile 输出流缓冲区,使所有字符由缓冲区流入test.txt文件
outfile.close();
return 0;
}
输出结果为 1~29。
这意味着,程序中每次向输出流缓冲区中放入字符时,pos 都表示的是当前字符的位置。比如,当将 str 全部放入缓冲区中时,pos 值为 29,表示的是最后一个字符 '/' 位于第 29 个位置处。
C++ seekp()成员方法
seekp() 方法用于指定下一个进入输出缓冲区的字符所在的位置。
seekp() 方法有如下 2 种语法格式:
//指定下一个字符存储的位置
ostream& seekp (streampos pos);
//通过偏移量间接指定下一个字符的存储位置
ostream& seekp (streamoff off, ios_base::seekdir way);
其中,各个参数的含义如下:
- pos:用于接收一个正整数