Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Looking for some suggestions on how to input values from text file

46 views
Skip to first unread message

Bob Langelaan

unread,
Nov 13, 2016, 2:04:27 PM11/13/16
to
I am helping a student with an assignment (not writing the solution for him!!!).

I can implement a doubly linked list in my sleep but when it comes to some forms of input I'm not nearly as strong. I'm just looking for hint(s) here and NOT SOLUTIONS.

The assignment specifies that each line of input will basically look like this:

nnnnn nnnnnn string string <newline>
<newline>
nnnnn nnnnnn string string <newline>
<newline>
...

- Note - nnnnn simply represents an integer value. The strings will not contain any white-space.

But input needs to handle error cases:

nnnnn <newline> <-- missing last 3 values

nnnnn nnnnn <newline> <-- missing last 2 string values

nnnnn nnnnn string <newline> <-- missing last string value

nnnnn nnnnn string string <extra_unwanted_values> <newline>

This is the first assignment for this class and their first use of the string class and therefore I would be surprised if they are required to use istringstream as part of their solution. And another possibility is to use a function like getchar() to read in each character, one by one, and manufacture the int and string values character by character.

My question is there a better/easier way? This "better/easier way" would, I assume, need to be aware when a '\n' is encountered in the input stream.

Thanks in advance :)

Vir Campestris

unread,
Nov 13, 2016, 4:42:38 PM11/13/16
to
On 13/11/2016 19:04, Bob Langelaan wrote:
> My question is there a better/easier way? This "better/easier way" would, I assume, need to be aware when a '\n' is encountered in the input stream.

getline and sscanf?

I think perhaps they _should_ be taught streams now. They'll probably
need it a lot in their early careers, and it's better than the bad
habits people like me have.

Andy

woodb...@gmail.com

unread,
Nov 13, 2016, 5:59:36 PM11/13/16
to
Streams are untidy.
I use getline sometimes.

Brian
Ebenezer Enterprises
http://webEbenezer.net

K. Frank

unread,
Nov 14, 2016, 10:48:35 PM11/14/16
to
Hi Bob!

On Sunday, November 13, 2016 at 2:04:27 PM UTC-5, Bob Langelaan wrote:
> ...
> The assignment specifies that each line of input will basically look like this:
>
> nnnnn nnnnnn string string <newline>
> <newline>
> nnnnn nnnnnn string string <newline>
> <newline>
> ...
>
> - Note - nnnnn simply represents an integer value. The strings will not contain any white-space.
>
> But input needs to handle error cases:
>
> nnnnn <newline> <-- missing last 3 values
> ...
> This is the first assignment for this class and their first use of the string class and therefore I would be surprised if they are required to use istringstream as part of their solution. And another possibility is to use a function like getchar() to read in each character, one by one, and manufacture the int and string values character by character.
>
> My question is there a better/easier way? This "better/easier way" would, I assume, need to be aware when a '\n' is encountered in the input stream.

Well, if this is the first assignment, it's a bit hard to
know what tools the students are expected / allowed to use.
But part of the point of c++ is to use the standard tools,
rather than write all of the low-level stuff from scratch.

So one suggestion that doesn't use too much machinery, is
pretty straightforward, and doesn't involve unnecessary
low-level coding runs as follows:

Use getline. This is perfectly appropriate because the input
format is explicitly line oriented.

Split the line into white-space-separated tokens. Count
the tokens. In your case, n != 4 is an error.

Parse / validate the tokens. In your case, tokens 3 and
4 are arbitrary (non-white-space-containing) strings, so
they are automatically valid. Tokens 1 and 2 are (decimal?)
integers, so parse them as such, and flag an error if they
are not.

I find it convenient to write a little helper function that
takes a std::string (obtained from getline) and returns a
std::vector<std::string> that contains the white-space-separated
tokens.

If tokens 1 and 2 are supposed to parse into a value that
fits into an unsigned int or unsigned long, you could use,
e.g., std::stoul. If they are supposed to parse into an
arbitrary length integer, then it's probably simplest to
write your own validation function that checks that each
character in the token is a (decimal) digit.

(I have used schemes like this frequently when writing
smallish programs that need to parse line-oriented input.)

> Thanks in advance :)


Happy Hacking!


K. Frank

Jorgen Grahn

unread,
Nov 20, 2016, 4:01:50 AM11/20/16
to
On Tue, 2016-11-15, K. Frank wrote:
> Hi Bob!
>
> On Sunday, November 13, 2016 at 2:04:27 PM UTC-5, Bob Langelaan wrote:
>> ...

>> The assignment specifies that each line of input will basically
>> look like this:
>>
>> nnnnn nnnnnn string string <newline>
...
> Use getline. This is perfectly appropriate because the input
> format is explicitly line oriented.
>
> Split the line into white-space-separated tokens. Count
> the tokens. In your case, n != 4 is an error.
>
> Parse / validate the tokens. In your case, tokens 3 and
> 4 are arbitrary (non-white-space-containing) strings, so
> they are automatically valid. Tokens 1 and 2 are (decimal?)
> integers, so parse them as such, and flag an error if they
> are not.
>
> I find it convenient to write a little helper function that
> takes a std::string (obtained from getline) and returns a
> std::vector<std::string> that contains the white-space-separated
> tokens.

That's how I would do it, too. And I tend to have it in my toolbox:

vector<string> split(const string&, size_t limit);

Splits on whitespace, trims whitespace, and splits at most 'limit'
times. It's pretty much the split() function in Python and Perl.

It's surprisingly useful, especially with the optional limit. And I
guess you can build it from the regex parts of the standard library.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

JiiPee

unread,
Nov 20, 2016, 5:01:41 AM11/20/16
to
I would say streams can be slow.


JiiPee

unread,
Nov 20, 2016, 5:04:38 AM11/20/16
to
On 20/11/2016 09:01, Jorgen Grahn wrote:
> That's how I would do it, too. And I tend to have it in my toolbox:
>
> vector<string> split(const string&, size_t limit);


me also (if super speed it not required). what is the purpose of limit?


Jorgen Grahn

unread,
Nov 20, 2016, 6:45:29 AM11/20/16
to
On Sun, 2016-11-20, JiiPee wrote:
> On 20/11/2016 09:01, Jorgen Grahn wrote:
>> That's how I would do it, too. And I tend to have it in my toolbox:
>>
>> vector<string> split(const string&, size_t limit);
>
> me also (if super speed it not required).

For super speed, I can imagine a version which lets you iterate
through the parts. IIRC, the regex parts of the standard library has
something like that (haven't used it myself).

> what is the purpose of limit?

In my experience, and with the file formats I parse, most of the time
you know how many columns you want to split out. And others seem to
find it useful too, since the feature is there in Perl and Python.

The OP's example syntax was

number number text text

I'd split that with limit=3, and allow whitespace in the last piece of
text:

10 4811 A foo
11 802 B hello, world!
0 new messages