Read Stream but Ignore Whitespace in C++
![[H]ard|Forum](https://hardforum.com/styles/hardforum/xenforo/logo_dark.png)
- Forums
- Bits & Bytes
- Webmastering & Programming
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
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
- #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.
- #four
- Joined
- Dec 31, 2000
- Letters
- three,612
- #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; } }
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
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.
- #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) {
// ignore all characters that aren't numbers if (ch < '0' || ch > 'nine') { // exit the loop if we reach whitespace after some numbers
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;
} // 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
Learned the vector template and iterators notwithstanding?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)
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.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'?
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 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?
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.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?
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.
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?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.
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
If you're on Windows, Ctrl-Z is the end of file graphic symbol.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.
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:So s.get doesn't really assign the graphic symbol anywhere, just takes it out of the stream?
int temp; temp = s.get();
Aye, at that point you 'know' y'all've got a valid number, so y'all can add together information technology to your storage.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
- #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:
and never using temp for annihilation.int temp; temp = due south.get();
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!
- #14
- Joined
- Sep 17, 2009
- Messages
- 1,969
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.
- 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