如果我有一个std::stringstream变量并且我std::string objects在其中写入了一些变量,并且我希望能够跟踪流位置指针并将它们输出到屏幕上,那么我如何使用,tellp()
然后当我从流中提取时,即使用流对于输入,我如何使用tellg(). 如何再次以输入模式打开流?另外,当我再次打开它进行输入时,我应该将位置指针设置回 0seekg()吗?seekp()
这是我的代码
std::string word;
std::stringstream ss;
while (word != "n") {
std::cout << "Enter a word, ( n to stop) : ";
std::cin >> word;
std::cin.ignore();
if (word == "n")
ss << std::endl;
else {
ss << word;
ss << " ";
}
}
std::cout << "The content in stringstream is : " << ss.str() << std::endl;
std::cout << "The StreamPositionPointer is"
<< ss.tellp(); // is this correct way of outputting streampointer
// how should I open the stream to get input from it to store it in a variable?
/* how should I switch the position pointer to a position when I use an
input/output stream like sstream with seekg(), seekp(), tellg(),tellp() */
Run Code Online (Sandbox Code Playgroud)
你已经有了基本的想法。std ::basic_stringstream允许使用std::basic_istream::tellg和std::basic_istream::seekg。有一些注意事项:
.str()成员函数,则在临时对象中返回基础字符串的副本,字符串流中的seekpos不会发生变化,因为您正在操作副本;rdbuf()成员函数,它将返回一个指向底层字符串设备的指针。用设备输出会输出内容,并且seekpos会提前到末尾,但eofbit不设置;>>读取字符串流集中最后一项的正常提取eofbit,clear()必须在进一步查找之前在字符串流上调用。如果在tellg()字符串流时调用,则返回流状态不是good,的任何内容。-1通过这个简短的示例练习seekg(),并在需要时tellg()与 一起clear()提供您正在寻找的解释。这是上面链接中提供的各种示例的混合体:
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
int main (void)
{
std::string str = "Hello, world"; /* initial string */
std::istringstream in(str); /* initialized stringstream */
std::string word1, word2; /* two string variables used below */
std::cout << "string: " << in.str() << "\n\ntellg "
<< std::setw(2) << in.tellg() << " - reading into word1\n";
in >> word1; /* read into word1 from beginning */
std::cout << "tellg " << std::setw(2) << in.tellg() << " - after reading \""
<< word1 << "\", rewinding\n";
in.seekg (0); /* seekg beginning (rewind) */
std::cout << "tellg " << std::setw(2) << in.tellg() << " - reading into word2\n";
in >> word2; /* read into word2 from beginning */
std::cout << "tellg " << std::setw(2) << in.tellg() << " - after reading \""
<< word2 << "\", reading final word\n";
in >> word2; /* read into word2 to end of stringstream, eofbit set */
std::cout << "tellg " << std::setw(2) << in.tellg() << " - after reading \""
<< word2 << "\", eofbit set, tellg() fails, must .clear()\n";
in.clear(); /* clear required before further stringstring operations */
in.seekg (0, std::ios_base::beg); /* reposition to beginning, 2nd form */
std::cout << "tellg " << std::setw(2) << in.tellg() << " - rdbuf() -> \""
<< in.rdbuf()
<< "\"\ntellg " << std::setw(2) << in.tellg() << " - reversing: \"";
while (in.tellg() != 0) { /* playing tell & seek back to beginning */
in.seekg (-1, std::ios_base::cur); /* seek -1 from current */
std::cout << (char)in.get(); /* output character */
in.seekg (-1, std::ios_base::cur); /* seek -1 from current */
}
std::cout << "\"\ntellg " << std::setw(2) << in.tellg() << " - all done.\n";
}
Run Code Online (Sandbox Code Playgroud)
示例使用/输出
$ ./bin/streambuf_seektellg
string: Hello, world
tellg 0 - reading into word1
tellg 6 - after reading "Hello,", rewinding
tellg 0 - reading into word2
tellg 6 - after reading "Hello,", reading final word
tellg -1 - after reading "world", eofbit set, tellg() fails, must .clear()
tellg 0 - rdbuf() -> "Hello, world"
tellg 12 - reversing "dlrow ,olleH"
tellg 0 - all done.
Run Code Online (Sandbox Code Playgroud)
上面的示例显示了如何处理 stringstring 中的streambuf位置的操作。从简单的倒回,到处理具有读取状态的streambuf,goodbit以及如何使用tellg()和的组合seekg()来迭代streambuf中的每个字符,从末尾到开头有效地反转输出。
使用seekp()On 的附加示例std::stringstream
根据您的评论,实际上没有太大区别,除了为了使用tellp()并且seekp()对象streambuf必须能够将输出发送给它。这意味着tellp()和只与和seekp()相关,但与 无关。因此,为了定位上例中的写入位置,您只需将类型更改为允许输出的两种变体之一。使用很好,例如std::stringstreamstd::ostringstreamstd::istringstreamstd::stringstream
std::stringstream in(str); /* stringstrem use both seek&tell (gp) */
Run Code Online (Sandbox Code Playgroud)
tellp()现在您可以使用和移动 get 并设置其中的写入位置seekp()。例如,以下内容通过in再次读取来获取当前读取位置word1并保存报告的位置in.tellg()。然后使用该位置来定位afterseekp()的写入,例如"big wide world!""Hello, "
std::cout << "\"\ntellg " << std::setw(2) << in.tellg()
<< " - seeking with seekp() - add \"big wide world!\"\n";
in >> word1; /* move past "Hello," */
size_t pos = in.tellg(); /* save offset from beginning */
in.seekp (pos + 1); /* seekp() past "Hello, " */
in << "big wide world!"; /* replace remaining content */
std::cout << "\nstring: " << in.str() << '\n'; /* output result */
Run Code Online (Sandbox Code Playgroud)
输出变化
更改上面输出的最后一行,然后添加新文本将导致:
...
tellg 0 seeking with seekp() - add "big wide world!"
string: Hello, big wide world!
Run Code Online (Sandbox Code Playgroud)
seekg()/tellg()和 seekp()/tellp()是独立的偏移量
为了回应您的进一步评论,重要的是要了解...g()和...p()成员函数提供对从 Streambuf 对象开头开始的两个独立偏移量的访问。seekg()和与缓冲区中的读取位置tellg()相关联。(认为 和)相反,和与缓冲区中的写入位置相关联。(思考和)seek...get()tell...get()seekp()tellp()seek...put()tell...put()
对示例最终输出的额外更改将使这一点变得清晰。仅将与关联的行更改/* output results */为:
/* output result */
std::cout << "\nstring: " << in.str() << "\ntellg : " << in.tellg()
<< "\ntellp : " << in.tellp() << '\n';
Run Code Online (Sandbox Code Playgroud)
输出变化
现在的输出显示了最终写入后in.tellg()报告的独立偏移量,例如in.tellp()in
...
string: Hello, big wide world!
tellg : 6
tellp : 22
Run Code Online (Sandbox Code Playgroud)
wherein.tellg()报告缓冲区中下一次读取(例如in >> word1;)将开始的位置,而in.tellp()报告缓冲区中下一次写入将发生的位置(例如in << " ... of code";)。添加 后in << " ... of code";,从当前tellg()位置输出std::cout << '\n' << in.rdbuf() << '\n'; 会导致:
big wide world! ... of code
Run Code Online (Sandbox Code Playgroud)
检查一下,如果您还有其他问题,请告诉我。