Read Stream but Ignore Whitespace in C++

  • Forums
  • Bits & Bytes
  • Webmastering & Programming
You are using an out of date browser. Information technology may not display this or other websites correctly.
You should upgrade or use an alternative browser.

C++ Homework problem... frustrating

  • Thread starter Shadowssong
  • Beginning date
  • #i
Joined
Sep 17, 2009
Messages
1,969
And so every bit I'm sure all of y'all have washed this assignment in your educational background, I'm on an consignment in which I create a class, myInt, which basically tin can store integers larger than what integers can store, storing a single digit of a number as an element of an assortment. Ok I've been working on this for most two weeks and I'm really trying my hardest (professor and TA both told me this was the hardest assignment) simply I am merely having the roughest time on the extraction operator overloading. Here is what I have then far (and aye I accept worked on this for a while and trying to attack it from dissimilar angles).
Instructions:
"Create an overload of the extraction operator >> for reading integers from an input stream. This operator should ignore any leading white space earlier the number, and then read sequent digits until a non-digit is encountered (this is the same manner that >> for a normal int works, so nosotros want to make ours work the same way). This operator should only extract and store the digits in the object. The "first non-digit" encountered after the number may be function of the next input, so should not be extracted. You lot may assume that the first non-whitespace grapheme in the input will be a digit. i.e. you practise not have to mistake check for entry of an inappropriate blazon (like a letter) when you have asked for a number.

Instance: Suppose the following code is executed, and the input typed is " 12345 7894H".

MyInt x, y;
char ch;
cin >> ten >> y >> ch; "

This is my all-time attempt:

                              istream& operator >> (istream& southward, MyInt& 1000) {           m.Create(1);           char ch;           int i,x = 0;           while((ch = cin.peek()) >= '0' && ch <= 'ix')           {                   cin.get(ch);                   cout << "ch = " << m.char2Int(ch) << endl;                   s >> ch;                   if( m.char2Int(ch) != -1 )                           k.intList[i] = m.char2Int(ch);                   i++;                   if(i > grand.arrSize)                           m.Resize(1);           }           return s; }                            

Now delight don't TELL Me what code to change, simply what concept needs to exist changed. I want to figure this out on my own simply when I do this it prompts for my input I do this:
                              Enter first number: -Create: South= 1 1234 ch = ane *** Bespeak 11 - core dumped brand: Fatal error: Control failed for target `run'                            

At present, if I annotate out:
                                                              if( m.char2Int(ch) != -ane )                         m.intList[i] = m.char2Int(ch);                            

I don't get a core dump, but the items are non read correctly (and evidently non assigned into my array)
Example:
                              Enter first number: -Create: S= 1 1234 ch = 1 ch = 3 Yous entered:   ten = 15067208                            

When it prints ch: that should say i, 2, 3, 4, but its skipping the 2d and fouth entries. I merely don't get this part at all. I am guessing that the value stored in x is only random gibberish or just char'south that didnt convert to ints.

Basically my understanding of this extraction is that I need to peek to see each grapheme, if that character is a number ( >= '0' && <= '9') so I want to get that character. Simply from there I desire to convert that char into an int which I tin shop as an detail in the object's array. Can someone point me in the right direction? I've been working hard but this seems to be my road block. I've built everything else in the form except the multiplication (likewise very hard). <3 for any [H]elp.

If you need definitions for whatsoever of the other functions let me know, they are basic (you could judge what they do).

  • #2
Joined
Aug 5, 2009
Letters
two,695
You should exist operating on istream &s, not cin.
  • #3
Joined
Sep 17, 2009
Messages
1,969
You should be operating on istream &s, not cin.

Huzzah good bespeak, thanks I'll update it tomorrow.

Updated: I got it to work!!! Cheers keenan! But for some reason I don't get prompted to input a second time, despite main calling cin >> ten, so cin >> y. Kind of only skips it and goes right to displaying what I input. I shalt work on information technology more.

Last edited:
  • #four
Joined
Dec 31, 2000
Letters
three,612
Your trouble could be a newline sitting in the buffer. Look upward std::cin.ignore();
  • #5
Joined
Sep 17, 2009
Letters
1,969
Your problem could be a newline sitting in the buffer. Look up std::cin.ignore();

So you lot are saying when I am doing due south.get() it is getting the newline even though it isn't included in the >= '0' && <= '9'?

I will wait into cin.ignore. I saw that somewhere, difficult to find examples that I can apply that are meaningful. I will check my text as well. Thanks!

  • #6
Joined
Aug v, 2009
Messages
2,695
So you are proverb when I am doing s.go() it is getting the newline even though it isn't included in the >= '0' && <= 'nine'?

Exactly, the while() test fails, so the loop ends and you drop out of it before reading anything. You should probably read, but ignore, whitespace before the number. I'd structure this with just a while(ch = cin.peek() != EOF) and handle all three cases inside the loop with an if/else.

Also I'k not sure why you're reading with s.get() then afterwards reading from it with the extraction operator, or possibly you've fixed this part?

  • #seven
Joined
Sep 17, 2009
Letters
1,969
Exactly, the while() test fails, so the loop ends and you drib out of it before reading annihilation. You should probably read, just ignore, whitespace before the number. I'd structure this with simply a while(ch = cin.peek() != EOF) and handle all iii cases inside the loop with an if/else.

Also I'chiliad not sure why yous're reading with s.get() and so afterwards reading from it with the extraction operator, or maybe you've stock-still this office?


This is my current function for information technology:
                              istream& operator >> (istream& s, MyInt& m) {         m.Create(1);         char ch;         int num = 0;         int i = 0;         int x = 0;         while((ch = s.peek()) >= '0' && ch <= '9')         {                 s.get(ch);                 cout << "ch = " << ch << endl;                 if(i == grand.arrSize)                         m.Resize(1);                 if( (num = m.char2Int(ch)) != -1 )                         m.intList[i] = num;                 i++;         }         render s; }                            

If i input like 1234567 it works fine. It seems if I put a number too big in it gives me the core dump error.

And yes you are right about the white space (I hadn't tested with that).

                              Enter first number:    332432 Yous entered:   10 = 12345                            

Then you are saying instead of checking for between 0 & 9 in the while, I move that into the inside in an if statement and put != EOF.

Within that I desire to ask If(betwixt 0 && 9), if char2Int != -1 and also if it is whitespace ignore information technology?

So would that be like
(if s.peek() == ' ')
south.ignore();

?

Or is information technology just
southward.ignore(' ');
s.get();

What about this:

                                                              m.Create(1);         char ch;         int num = 0;         int x = 0; 	for(int i = 0; (ch = s.peek()) != EOF; i++) 	{ 		s.ignore(' '); 		if(i == thousand.arrSize) 			1000.Resize(1); 		if(ch >= '0' && ch <= 9) 		{ 			if((num = g.char2Int(ch)) != -1) 				m.intList[i] = num; 		} 	}                            
Switch to a for loop (saves a couple lines)

Should I use south.ignore(number, delimiter) or just s.ignore(delimiter)

Thanks and then much for your aid btw.

  • #eight
Joined
Aug five, 2009
Messages
ii,695
I'm personally not a fan of doing everything in the loop construct. Saving lines shouldn't be your goal; being articulate should exist. You're iterating over input, and if you tin can't cram merely that into the for loop, you shouldn't utilise for, IMO, information technology takes some actress mental parsing to figure out what'south going on.

Anyway, you're getting pretty shut. I'd do it something like this:

                                bool break_on_ws = imitation; while (ch = south.peek() != EOF) {   // ignore all characters that aren't numbers   if (ch < '0' || ch > '9') {     // go out the loop if we reach whitespace afterwards some numbers     if (break_on_ws) break;     // advance the input stream     s.get();     keep;   }    // it's a number so read information technology in and store it   break_on_ws = true;   ... }                              

Also just a minor thing that probably won't go you lot marks but will save you fourth dimension in the real earth - you might want to refactor this so that the istream operator just reads the input, skips whitespace, and passes it along as a cord to a 'fromStr' method. Both methods volition exist simpler and more useful.

Edit: Oops a problems.

Last edited:
  • #9
Joined
Sep 17, 2009
Letters
1,969
I'yard personally not a fan of doing everything in the loop construct. Saving lines shouldn't be your goal; being clear should be. You're iterating over input, and if you can't cram just that into the for loop, you shouldn't use for, IMO, it takes some actress mental parsing to effigy out what'due south going on.

Anyway, y'all're getting pretty close. I'd do it something similar this:

                                  bool break_on_ws = false; while (ch = due south.peek() != EOF) {   // ignore all characters that aren't numbers   if (ch < '0' || ch > '9') {     // exit the loop if nosotros attain whitespace after some numbers     if (break_on_ws) intermission;     // advance the input stream     due south.get();     continue;   }    // it'south a number so read it in and store it   break_on_ws = truthful;   ... }                                

As well simply a small thing that probably won't get you lot marks only volition save you lot time in the real world - y'all might want to refactor this then that the istream operator just reads the input, skips whitespace, and passes it along every bit a string to a 'fromStr' method. Both methods volition be simpler and more useful.

Edit: Oops a bug.


Ok I'll effort that. I just saw my professor about the issues with my multiplication role, turns out I did have a few problems in other functions (seg faults, extending over boundaries etc)
                              bool break_on_ws = false;                            
                              while (ch = s.peek() != EOF) {                            
So this means if the character is not EOF continue, and so does EOF include newline? Or should I do something like ch = s.peek() ! = '\n'?
                                                              // ignore all characters that aren't numbers   if (ch < '0' || ch > 'nine') {     // exit the loop if we reach whitespace after some numbers                            
Ok sympathise that part
So that is saying, if break_on_ws is truthful, break out of the loop? How exactly practice I know when information technology is breaking on a whitespace?
                                                              // advance the input stream     s.get();     continue;                            
And then go on means keep going through the loop? So I get the char and then I assign what it got into my array. should I say ch = due south.go(); so continue; then put ch into the array slot later converting it?
                                                              }    // it's a number so read it in and shop information technology   break_on_ws = true;   ... }                            

How exactly practise I know when whitespace is there, I am kind of dislocated with the whole break_on_ws variable affair. Care to elaborate more? I'm going to go along working at it in the hateful time. Again, many thanks for helping me.
  • #x
Joined
Aug 5, 2009
Messages
two,695
Ok I'll attempt that. I but saw my professor about the problems with my multiplication function, turns out I did have a few bug in other functions (seg faults, extending over boundaries etc)
Learned the vector template and iterators notwithstanding?
Then this ways if the graphic symbol is not EOF proceed, then does EOF include newline? Or should I exercise something like ch = southward.peek() ! = '\northward'?
EOF is a macro that evaluates to -1, it's a special value that the stream will return when the file is closed. On stdin equally y'all're using it, it will occur when the input stream is concluded with the finish of file character (^Z on Windows, ^D on *nix) is received, or the program directing input to it is terminated.
So that is proverb, if break_on_ws is true, break out of the loop? How exactly practice I know when it is breaking on a whitespace?
It'due south just a flag that gets set up once yous've received a number character. At the start information technology's simulated, then y'all just ignore whitespace (or in this example any non-number character), but once you receive a number character you want to finish on whitespace instead of just ignoring information technology (which would mash two numbers into one if they were separated by a space). So you start with it skipping whitespace, and and so once y'all get i proper graphic symbol, arrive break out of the loop (or you could just return immediately hither if you wanted to). Yous could acheive the same event with a big if {} else {} clause around the ii cases, but that looks ugly and it gets worse when y'all've got more than 2 cases, then instead you finish early with 'continue'.
So continue means proceed going through the loop? And so I get the char then I assign what it got into my assortment. should I say ch = s.become(); then go on; then put ch into the array slot later on converting information technology?
This part is the whitespace example, you don't want to do anything with the graphic symbol, but calling s.get() will advanced the input stream past ane character so you've moved on to the adjacent one for the next go-around. You could use s.ignore() instead, but south.get() is simpler and has the same effect. go along is a language keyword, whereas 'interruption' terminates the entire loop, 'proceed' ends the current iteration and takes you right back to the loop exam without executing the remainder of the loop showtime. Then once you've skipped the whitespace you've dealt with that character and its time to go along to the adjacent 1.

Basically the idea is that each time over the loop you lot first examination if the input is what you're looking for. If information technology's not *and* you lot haven't received any valid input notwithstanding, and so just ignore it, skip over the processing y'all'd normally practice and get to the next character. Once yous get a valid character, keep reading characters until yous hitting one that'south non a number, in which example y'all cease completely since the end of the number has been reached. break_on_ws is just a flag for you to keep runway of where you are - earlier the number is reached it will exist false, and once you reach the number you will set it to true so you end as before long as you reach a non-number graphic symbol.

  • #eleven
Joined
Sep 17, 2009
Letters
1,969
Learned the vector template and iterators nonetheless?

Nope, not yet.
EOF is a macro that evaluates to -1, it's a special value that the stream will return when the file is closed. On stdin as you're using information technology, it will occur when the input stream is concluded with the stop of file grapheme (^Z on Windows, ^D on *nix) is received, or the plan directing input to it is terminated.

I am using this:
                              istream& operator >> (istream& s, MyInt& thousand) {         1000.Create(1);         char ch;         int num = 0;         int x = 0;         int i = 0;         bool break_on_ws = false;         while (ch = s.peek() != EOF)         {                 if(ch < '0' || ch > '9')                 {                         if (break_on_ws)                                 break;                         due south.get();                         continue;                 }                 break_on_ws = true;                 s.get(ch);                 if(i == m.arrSize)                         1000.Resize(1);                 if((num = m.char2Int(ch)) != -1)                         m.intList[i] = num;         }         return s; }                            

When it runs I can never end the input, it just keeps going (I accept to ctrl C out of it). If I utilize while (ch = s.peek() != '\n') it volition cease the input simply it does not return the right value.

Enter starting time number: 12355
You lot entered:
x = 151392

Information technology'due south just a flag that gets prepare once you've received a number graphic symbol. At the start it'south false, then you just ignore whitespace (or in this example any non-number character), but in one case you receive a number character you want to stop on whitespace instead of just ignoring it (which would mash ii numbers into one if they were separated by a space). So yous start with it skipping whitespace, and then one time you get 1 proper character, get in break out of the loop (or you could just return immediately here if yous wanted to). You could acheive the aforementioned effect with a big if {} else {} clause around the two cases, but that looks ugly and it gets worse when you've got more than 2 cases, and then instead you terminate early with 'continue'.

Ok I understand the use of it at present.
This part is the whitespace case, you don't want to do anything with the grapheme, but calling due south.get() volition advanced the input stream past one character so you've moved on to the next one for the next go-around. You could utilise southward.ignore() instead, but s.get() is simpler and has the same consequence. continue is a language keyword, whereas 'intermission' terminates the entire loop, 'go along' ends the current iteration and takes you right back to the loop exam without executing the remainder of the loop first. So once you lot've skipped the whitespace y'all've dealt with that graphic symbol and its time to go on to the next i.
So s.become doesn't actually assign the grapheme anywhere, only takes information technology out of the stream? And then if I have ("_"= space) "_ _ _1234123_". It would peek space ->s.go(), peek space -> s.get, peek infinite -> s.get, peek 1 -> break_on_ws = truthful -> south.get(ch). I am kind of confused how this actually gets the character. I added the southward.get(ch) after the b_o_w = true to go the graphic symbol? Is that not where I should go it?
Basically the idea is that each time over the loop you lot first test if the input is what you're looking for. If information technology's not *and* you oasis't received any valid input yet, then only ignore it, skip over the processing you'd unremarkably exercise and go to the next character. Once you get a valid character, keep reading characters until you lot hit ane that'southward non a number, in which instance you end completely since the end of the number has been reached. break_on_ws is just a flag for you to keep rails of where you are - before the number is reached it volition be fake, and once y'all reach the number you will gear up it to true and then you end as shortly every bit you reach a non-number character.

I think I understand it, withal slightly dislocated about where I should actually go the character to put into my array though. Basically once I flag suspension to true, if I get a non digit character information technology will break the loop correct? So should I accept the s.go(ch); right subsequently the break_on_ws = truthful; argument? Thanks again
  • #12
Joined
Aug v, 2009
Letters
2,695
When information technology runs I can never end the input, information technology just keeps going (I take to ctrl C out of it). If I use while (ch = south.peek() != '\northward') it will end the input only it does not return the correct value.
If you're on Windows, Ctrl-Z is the end of file graphic symbol.
So s.get doesn't really assign the graphic symbol anywhere, just takes it out of the stream?
It'south calling 'int istream::become()', which returns the next character as an integer. Since you don't assign it to anything, it just pulls information technology out of the stream and discards it. If it makes things more clear, it'due south the aforementioned as doing:
                              int temp; temp = s.get();                            
and never using temp for anything.
I call up I empathise information technology, notwithstanding slightly confused about where I should really get the grapheme to put into my array though. Basically one time I flag break to true, if I get a non digit character it will intermission the loop correct? So should I take the due south.go(ch); correct afterwards the break_on_ws = true; argument? Thanks over again
Aye, at that point you 'know' y'all've got a valid number, so y'all can add together information technology to your storage.
  • #xiii
Joined
Sep 17, 2009
Messages
1,969
If you're on Windows, Ctrl-Z is the stop of file graphic symbol.

Information technology'southward calling 'int istream::become()', which returns the side by side character every bit an integer. Since yous don't assign information technology to anything, it just pulls information technology out of the stream and discards it. If information technology makes things more articulate, it'southward the same as doing:

                                    int temp; temp = due south.get();                                  
and never using temp for annihilation.

Yep, at that point yous 'know' y'all've got a valid number, so you can add it to your storage.


Ok swell I go it now. I am using != '\n' because I want it to stop at newline. But for some reason I am still getting garbled results.
                                Enter beginning number: 12345 Enter second number: You lot entered:   x = ,152056                              

The , indicates that 152056 is a single number because I utilize something to suspension up each digit when I print anything.
                                                                  for(int i = 0; i < m.arrSize; i++)                 s << "," << m.intList[i];                              

And so working numbers impress like this:
y = ,ix,8,7,6,5,4,3,2,ane,0,1,2,three,4,5,vi,seven,8,ix

This is my full extraction overload:

                                istream& operator >> (istream& south, MyInt& k) {         m.Create(i);         char ch;         int num = 0;         int x = 0;         int i = 0;         bool break_on_ws = faux;         while (ch = s.peek() != '\n')         {                 if(ch < '0' || ch > 'ix')                 {                         if (break_on_ws)                                 pause;                         southward.get();                         proceed;                 }                 break_on_ws = truthful;                 s.get(ch);                 cout << "Char: " << ch << endl;                 if(i == m.arrSize)                         m.Resize(1);                 if((num = chiliad.char2Int(ch)) != -1)                         m.intList[i] = num;                 i++;         }         render s; }                              

Whatsoever idea why it is nonetheless garbling the results? Also I am programming in unix and compiling on yard++. Thank you once again!
Terminal edited:
  • #14
Joined
Sep 17, 2009
Messages
1,969
Figured it out

Needed to add together a set of parenthesis on the while:
while ((ch = south.peek()) != '\n')

Working fine now, thanks then much keenan!

Ps- I also figured out why my second input would not announced, just like Eloj said, the newline was yet in the buffer. I added a s.get() before returning s and it works great.

Last edited:
  • Forums
  • $.25 & Bytes
  • Webmastering & Programming

Read Stream but Ignore Whitespace in C++

Source: https://hardforum.com/threads/c-homework-problem-frustrating.1464018/

0 Response to "Read Stream but Ignore Whitespace in C++"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel