Hmm, looking back, I'm not sure I get my point either... maybe I was responding to something else I read.
No, if you are just supposed to write a manipulator, stick to that. (But there is no EOF manipulator --I think you are talking about the end of input: whitespace for cin >> string, and newlines for getline( cin, string ).)
I think
Scipio understood your problem right away. For example, given
This is a test
file. $ The end.
|
If the delimiter is to be the '$', you can use getline() directly:
getline( inf, s, '$' );
However, getline() only delineates on a single character --not useful if you need to break on a set of characters.
For that, you can either write a direct function (like getline()), or you can write a special data type. From what you wrote I think you want the first. (A stream manipulator is a function.)
Firstly, there are plenty of
bad examples of simple manipulators. Here's one I found near the top of Google:
http://www.java2s.com/Tutorial/Cpp/0100__Development/Createaninputmanipulator.htm
Don't ever use other streams in a manipulator. It breaks all structure and is antithetical to the design of C++ iostreams.
A manipulator should only work on the argument stream, and should avoid side effects as much as possible. If that is not the case, use a regular function instead of a manipulator. (That example fails in other ways too.)
Simple Manipulators
A simple, no-argument manipulator is just a function that takes a single stream class as argument:
1 2 3 4 5 6 7 8 9 10 11 12
|
#include <cctype>
#include <iostream>
...
istream& skipdigits( istream& ins )
{
// While the next available character is a digit, read it.
while (ins.good() && isdigit( ins.peek(), ins.getloc() ))
ins.get();
// If any kind of read error occurred, we'll let it propagate back.
// (Hence, we don't need to cin.clear() at any time in this function.)
return ins;
}
|
Thereafter, we can skip lists of numbers in input, exactly like we can skip whitespace with the
skipws manipulator:
1 2 3 4 5
|
istringstream ss( "123.456" );
double d;
// Get only the fractional part
ss >> skipdigits >> d;
// Now d == 0.456
|
Manipulators will typically return the stream passed as argument. However, they don't have to. More on this in a moment.
Alas, you have now reached the end of most manipulator tutorials.
Parameterized Manipulators
Now for the stuff hard to find on the internet: manipulators with additional arguments. How to do it has actually changed
somewhat. Before C++ had templates, you needed to #include <iomanip> and use some of the macros in that file to create a
manipulator.
However, these days you can just use some template magic. Here is a manipulator that lets you skip any set of characters, and an
example of how to use it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
struct skipthese
{
const string& s;
skipthese( const string& s ): s( s ) { }
};
template <typename CharType, typename TraitsType>
inline
basic_istream <CharType, TraitsType> &
operator >> (
basic_istream <CharType, TraitsType> & ins,
const skipthese& s
) {
while (ins.good() && (s.s.find( ins.peek() ) != string::npos))
ins.get();
return ins;
}
int main()
{
string skip, input, result;
cout << "Enter string of chars to skip> ";
getline( cin, skip );
cout << "Enter string beginning with any sequence of chars to skip\n> ";
getline( cin, input );
istringstream iss( input );
iss >> skipthese( skip );
getline( iss, result, '\0' );
cout << "The string, sans chars to skip, is: " << result << endl;
return 0;
}
|
Hope this helps.
[edit] cin.getline() is different than the getline() function that you get by #including <string> [/edit]