How to establish a delimiter pattern for input streams

  • Thread starter Generic Usenet Account
  • Start date
G

Generic Usenet Account

I am trying to set up a delimiter character string for the input stream
such that the delimiter string is "skipped over" in the input stream.
Can someone suggest how to do this with some sample code? I am
attaching a "C" code snippet that does the same thing. The problem is
that I don't know how to realize this using "cin"


Thanks,
Lee

/****************************/
#include <stdio.h>

int
main()
{
int abc, xyz;

printf("Enter the values: ");

scanf("%d Step over this text %d", &abc, &xyz);

printf("VAR1: %d\n", abc);
printf("VAR2: %d\n", xyz);
}
 
J

John Ratliff

Generic said:
I am trying to set up a delimiter character string for the input stream
such that the delimiter string is "skipped over" in the input stream.
Can someone suggest how to do this with some sample code? I am
attaching a "C" code snippet that does the same thing. The problem is
that I don't know how to realize this using "cin"


Thanks,
Lee

/****************************/
#include <stdio.h>

int
main()
{
int abc, xyz;

printf("Enter the values: ");

scanf("%d Step over this text %d", &abc, &xyz);

printf("VAR1: %d\n", abc);
printf("VAR2: %d\n", xyz);
}

Here is one possibility:

--------------------------------------------------
#include <iostream>
#include <string>

int main(int, char **) {
std::string ignore;
int abc, xyz;

std::cout << "Enter the values: ";
std::cin >> abc >> ignore >> ignore >> ignore >> ignore >> xyz;

std::cout << "VAR1: " << abc << '\n';
std::cout << "VAR2: " << xyz << '\n';

return 0;
}

$ ./a.exe
Enter the values: 5 skip over this text 10
VAR1: 5
VAR2: 10
--------------------------------------------------

Though it requires you to know how many words you're skipping. There is
probably a better way. I might use a regex, but that would require some
system-dependent library which is not part of C++.

If you know how many words you have to skip, then this would probably
work fine.

--John Ratliff

P.S. Please don't cross-post. If you have a C++ question, post to
comp.lang.c++, if you have a D question, post to whatever newsgroup
handles the D language.

See http://www.parashift.com/c++-faq-lite/ for more information.
 
B

Bob Hairgrove

[cross-posting snipped]

I am trying to set up a delimiter character string for the input stream
such that the delimiter string is "skipped over" in the input stream.
Can someone suggest how to do this with some sample code? I am
attaching a "C" code snippet that does the same thing. The problem is
that I don't know how to realize this using "cin"


Thanks,
Lee

/****************************/
#include <stdio.h>

int
main()
{
int abc, xyz;

printf("Enter the values: ");

scanf("%d Step over this text %d", &abc, &xyz);

printf("VAR1: %d\n", abc);
printf("VAR2: %d\n", xyz);
}

I would use the std::getline function which takes an istream &, a
string &, and optionally a delimiter character as arguments.

The first overload, taking just the first two arguments, reads an
entire line up to the new line character or EOF, whichever comes
first. The second overload will use the character you give it as a
delimiter. It is quite flexible as you don't have to know ahead of
time exactly how many elements between delimiters there might be ...
but 99% of the time you'll probably need to know, anyway.

One caveat ... I think the Borland 5 compiler (i.e. the RogueWave STL
libraries it uses) has troubles with this particular getline
function...if that's what you are using, you can fall back on
std::istream::getline which takes a buffer (i.e. char*) and a length
and an optional delimiter as arguments. Works just fine on my other
compilers, though...
 
V

Valentin Samko

John said:
I might use a regex, but that would require some
system-dependent library which is not part of C++.

You could use boost::regex. It is not system dependent, and it is included in the draft of
the next STL.
 
U

usenet

John said:
Here is one possibility:

--------------------------------------------------
#include <iostream>
#include <string>

int main(int, char **) {
std::string ignore;
int abc, xyz;

std::cout << "Enter the values: ";
std::cin >> abc >> ignore >> ignore >> ignore >> ignore >> xyz;

std::cout << "VAR1: " << abc << '\n';
std::cout << "VAR2: " << xyz << '\n';

return 0;
}

This is not quite the same thing. The suggested approach does not
distinguish between "Step over this text" and any other four-word
string. Is there no easy way to realize this using the streaming
library of C++?

Thanks,
Lee
 
N

Neil Cerutti

I am trying to set up a delimiter character string for the
input stream such that the delimiter string is "skipped over"
in the input stream. Can someone suggest how to do this with
some sample code? I am attaching a "C" code snippet that does
the same thing. The problem is that I don't know how to
realize this using "cin"


Thanks,
Lee

/****************************/
#include <stdio.h>

int
main()
{
int abc, xyz;

printf("Enter the values: ");

scanf("%d Step over this text %d", &abc, &xyz);

printf("VAR1: %d\n", abc);
printf("VAR2: %d\n", xyz);
}

C++ doesn't come bundled with that functionality, that I know of.

Here's a quick implementation that more or less matches the scanf
functionality, and a tiny test program. If the ignored string is
not matched, it sets ios::failbit for the input stream.

#include <iostream>
#include <istream>
#include <cctype>
using namespace std;

class ignore
{
const char* s_;
public:
explicit ignore(const char* s): s_(s) { }
friend istream& operator>>(istream&, const ignore&);
};

istream& operator>>(istream& is, const ignore& ig)
{
is >> ws;
for (const char* p = ig.s_; *p; ++p) {
char ignore_c = *p;
if (isspace(static_cast<unsigned char>(ignore_c))) {
is >> ws;
} else {
char input_c = is.get();
if (input_c != ignore_c) {
is.setstate(ios::failbit);
return is;
}
}
}
return is;
}

int main()
{
int v1, v2;
cin >> v1 >> ignore("this text") >> v2;
if (cin) {
cout << "VAR1: " << v1 << "\nVAR2: " << v2;
} else {
cout << "Input error.\n";
}
return 0;
}
 
N

Nimmi Srivastav

Generic said:
I am trying to set up a delimiter character string for the input stream
such that the delimiter string is "skipped over" in the input stream.
Can someone suggest how to do this with some sample code? I am
attaching a "C" code snippet that does the same thing. The problem is
that I don't know how to realize this using "cin"


Thanks,
Lee

The correct way to handle this is to define an input stream manipulator
that accepts the "delimiter string" as an argument. This manipulator
should intelligently handle optional delimiter characters. If the
manipulator encounters the "delimiter string", it steps over it. If
not, it stores the value read into a "shared buffer", as described in
K&R Section 4.3. During reading, attempt is made to first read from
the "shared buffer" and then the input stream. Of course, this
requires changing the way the extraction operator works, which will not
happen unless this idea makes it to the standard.

We all know that manipulators that accept arguments are a little tricky
(The C++ Programming Language, Bjarne Stroustrup, 3rd Edition, Section
21.4.6.1) The way it is done is to define a class/structure that has
the overloaded operator >> friend function. This overloaded function
accepts the reference to the input stream and the reference to an
object of the aforementioned class/structure as arguments, and returns
the reference to the input stream. Here's an example:

struct skipDelimiter
{
const char* delimPattern;
skipDelimiter(const char* str): delimPattern(str){}
friend istream& operator>>(istream&, const skipDelimiter&);
};

istream& operator>>(istream& istrm, const skipDelimiter& sd)
{
// IF delimiter pattern found
// THEN
// skip over it
// ELSE
// push the pattern found into a shared buffer
// (as described in K&R Section 4.3)
// ENDIF
// return
return istrm;
}



For completeness, here's a code snippet for a manipulator that does not
take arguments. All that is needed here is a function that accepts the
reference to the input stream as an argument, and returns the reference
to the input stream.

istream& printdate(istream& istrm)
{
// Meaningless example, for illustrative
// purposes only
time_t lt;
time(&lt);
cout << ctime(&lt);
return istrm;
}


Regards,
Nimmi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top