如何在 C++ 中正确获取 input/output 流的 file/stream 位置指针?
How to correctly get the file/stream position pointers in C++ for an input/output stream?
如果我有一个std::stringstream
变量并且我在里面写了一些std::string objects
,我希望能够跟踪流位置指针并将它们输出到屏幕上,我该如何使用tellp()
然后当我从流中提取时,即使用流作为输入,我如何使用 tellg()
。
如何再次以输入模式打开流?另外,当我再次打开它输入时,我应该用 seekg()
或 seekp()
将位置指针设置回 0 吗?
这是我的代码
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() */
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 StreamPositionPosition is: "
<< ss.tellp() << std::endl; // Yes this is correct, it will give you the position of the current position where you are outputting.
// how should i open the stream to get input from it to store it in a variable?
// If you want to convert it to string simply
std::string str = ss.str();
// If you know the order of the data, you can simply extract it
std::string wordOutput;
ss >> wordOutput;
/* how should I switch the position pointer to a position when I use an
input/output stream like sstream with seekg(), seekp(), tellg(),tellp() */
/*
seekg sets the position of input
tellg gets the position of input
seekp sets the position of output
tellp gets the position of output
*/
long length = s.tellp(); // gives you the length of the string stream
// If you want the first position do,
ss.seekp(0);
ss >> wordOutput;
// If you want the third last, do
ss.seekp(length - 3);
ss >> wordOutput;
// Examples for inputs
stringstream example;
example.write ("This is an apple",16);
long pos = example.tellp();
example.seekp (pos-7);
example.write (" sam",4);
// Will result in This is a sample
你有基本的想法。 std::basic_stringstream allows use of both std::basic_istream::tellg and std::basic_istream::seekg。有几点注意事项:
- 如果使用
.str()
成员函数,底层字符串的副本被 returned 在一个临时对象中,stringstream 中的 seekpos 没有变化,因为你正在操作一个复制;
- 如果使用
rdbuf()
成员函数,它将return一个指向底层字符串设备的指针。 output with the device 会输出with的内容,seekpos会前进到最后,但是eofbit
没有设置;
- 对于使用
>>
读取字符串流集合中最后一项的正常提取 eofbit
和 clear()
必须在进一步查找之前在字符串流上调用。如果在 stringstream 时调用 tellg()
,streamstate 不是 good
,-1
是 returned.
通过一个简短的例子,练习 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";
}
示例Use/Output
$ ./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.
上面的示例显示了如何处理 stringstring 中 streambuf 位置的操作。从简单的倒带,到使用 goodbit
以外的读取状态处理 streambuf,以及如何使用 tellg()
和 seekg()
的组合从末尾迭代 streambuf 中的每个字符到开始有效地反转输出。
在 std::stringstream
上使用 seekp()
的其他示例
回应您的评论,除了要使用 tellp()
和 seekp()
,streambuf
对象必须能够发送输出外,确实没有太大区别给它。这意味着 tellp()
和 seekp()
仅与 std::stringstream
和 std::ostringstream
相关,而不与 std::istringstream
相关。因此,为了在上面的示例中定位写入位置,您只需将类型更改为允许输出的两个变体之一。使用 std::stringstream
没问题,例如
std::stringstream in(str); /* stringstrem use both seek&tell (gp) */
现在您可以使用 tellp()
和 seekp()
移动 get 并在其中设置写入位置。例如,以下通过再次读取 word1
获取 in
中的当前读取位置,并保存 in.tellg()
报告的位置。然后 seekp()
使用该位置在 "Hello, "
之后定位 "big wide world!"
的写入,例如
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 */
输出变化
更改以上输出的最后一行然后添加新文本将导致:
...
tellg 0 seeking with seekp() - add "big wide world!"
string: Hello, big wide world!
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';
输出变化
输出现在显示 in.tellg()
和 in.tellp()
在最终写入 in
后报告的独立偏移量,例如
...
string: Hello, big wide world!
tellg : 6
tellp : 22
其中in.tellg()
报告缓冲区中下一次读取(如in >> word1;
)开始的位置,而in.tellp()
报告缓冲区中下一次写入的位置将发生,(例如 in << " ... of code";
)。添加 in << " ... of code";
后,从当前 tellg()
位置输出 std::cout << '\n' << in.rdbuf() << '\n';
将导致:
big wide world! ... of code
检查一下,如果您还有其他问题,请告诉我。
如果我有一个std::stringstream
变量并且我在里面写了一些std::string objects
,我希望能够跟踪流位置指针并将它们输出到屏幕上,我该如何使用tellp()
然后当我从流中提取时,即使用流作为输入,我如何使用 tellg()
。
如何再次以输入模式打开流?另外,当我再次打开它输入时,我应该用 seekg()
或 seekp()
将位置指针设置回 0 吗?
这是我的代码
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() */
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 StreamPositionPosition is: "
<< ss.tellp() << std::endl; // Yes this is correct, it will give you the position of the current position where you are outputting.
// how should i open the stream to get input from it to store it in a variable?
// If you want to convert it to string simply
std::string str = ss.str();
// If you know the order of the data, you can simply extract it
std::string wordOutput;
ss >> wordOutput;
/* how should I switch the position pointer to a position when I use an
input/output stream like sstream with seekg(), seekp(), tellg(),tellp() */
/*
seekg sets the position of input
tellg gets the position of input
seekp sets the position of output
tellp gets the position of output
*/
long length = s.tellp(); // gives you the length of the string stream
// If you want the first position do,
ss.seekp(0);
ss >> wordOutput;
// If you want the third last, do
ss.seekp(length - 3);
ss >> wordOutput;
// Examples for inputs
stringstream example;
example.write ("This is an apple",16);
long pos = example.tellp();
example.seekp (pos-7);
example.write (" sam",4);
// Will result in This is a sample
你有基本的想法。 std::basic_stringstream allows use of both std::basic_istream::tellg and std::basic_istream::seekg。有几点注意事项:
- 如果使用
.str()
成员函数,底层字符串的副本被 returned 在一个临时对象中,stringstream 中的 seekpos 没有变化,因为你正在操作一个复制; - 如果使用
rdbuf()
成员函数,它将return一个指向底层字符串设备的指针。 output with the device 会输出with的内容,seekpos会前进到最后,但是eofbit
没有设置; - 对于使用
>>
读取字符串流集合中最后一项的正常提取eofbit
和clear()
必须在进一步查找之前在字符串流上调用。如果在 stringstream 时调用tellg()
,streamstate 不是good
,-1
是 returned.
通过一个简短的例子,练习 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";
}
示例Use/Output
$ ./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.
上面的示例显示了如何处理 stringstring 中 streambuf 位置的操作。从简单的倒带,到使用 goodbit
以外的读取状态处理 streambuf,以及如何使用 tellg()
和 seekg()
的组合从末尾迭代 streambuf 中的每个字符到开始有效地反转输出。
在 std::stringstream
seekp()
的其他示例
回应您的评论,除了要使用 tellp()
和 seekp()
,streambuf
对象必须能够发送输出外,确实没有太大区别给它。这意味着 tellp()
和 seekp()
仅与 std::stringstream
和 std::ostringstream
相关,而不与 std::istringstream
相关。因此,为了在上面的示例中定位写入位置,您只需将类型更改为允许输出的两个变体之一。使用 std::stringstream
没问题,例如
std::stringstream in(str); /* stringstrem use both seek&tell (gp) */
现在您可以使用 tellp()
和 seekp()
移动 get 并在其中设置写入位置。例如,以下通过再次读取 word1
获取 in
中的当前读取位置,并保存 in.tellg()
报告的位置。然后 seekp()
使用该位置在 "Hello, "
之后定位 "big wide world!"
的写入,例如
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 */
输出变化
更改以上输出的最后一行然后添加新文本将导致:
...
tellg 0 seeking with seekp() - add "big wide world!"
string: Hello, big wide world!
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';
输出变化
输出现在显示 in.tellg()
和 in.tellp()
在最终写入 in
后报告的独立偏移量,例如
...
string: Hello, big wide world!
tellg : 6
tellp : 22
其中in.tellg()
报告缓冲区中下一次读取(如in >> word1;
)开始的位置,而in.tellp()
报告缓冲区中下一次写入的位置将发生,(例如 in << " ... of code";
)。添加 in << " ... of code";
后,从当前 tellg()
位置输出 std::cout << '\n' << in.rdbuf() << '\n';
将导致:
big wide world! ... of code
检查一下,如果您还有其他问题,请告诉我。