I was trying to write a code in C++ in Windows using MinGW compiler, my code counts and prints the number of consecutive times a number occurs in a given set of input. The code is as follows:
#include <iostream>
int main()
{
int c_val = 0,val = 0,cnt = 1;
std::cin>>c_val;
while(std::cin>>val){
if(val==c_val)
cnt++;
else{
std::cout<<c_val<<" occurs "<<cnt<< " times"<<std::endl;
c_val = val;
cnt = 1;
}
}
std::cout<<val<<" occurs "<<cnt<<" times";
}
INPUT: 42 42 42 12 13 13 ^Z (press Enter)
OUTPUT:
42 occurs 3 times
12 occurs 1 times
0 occurs 2 times
But if I press Enter before ^Z then it looks like:
INPUT: 42 42 42 12 13 13 (press Enter) ^Z (press Enter)
OUTPUT:
42 occurs 3 times
12 occurs 1 times
13 occurs 2 times
I want to know why the variable val in my code stores 13, when I use ^Z key after pressing my return key and why does it store 0 if I give the ^Z key along with my input.
Here is what happens. I observed this using MinGW-w64 4.9.2. The behaviour was the same whether running the executable in a Windows console, or under Cygwin (but not using cygwin-mingw).
Pressing ^Z at the beginning of a line sets the end-of-file condition
Pressing ^Z anywhere else actually sends ASCII 26 character to the stream
I also observed:
cin >> val sets val to 0 if it fails due to the input not containing a number.
cin >> val leaves val unchanged if input fails due to end-of-file.
According to this thread that is the correct behaviour specified by C++11.
So your results can be explained. When you input 42 42 42 12 13 13^Z, it is the same as if you had written 42 42 42 12 13 13x. The first six numbers are read, and then when x is encoutered, cin >> val fails and sets val to 0.
But when you press Enter and then ^Z, it is as if you were reading from a file and you reached the end of the file. cin >> val leaves val unchanged and it is still holding the value that it had after the last successful cin >> val.
If you make the change suggested by Gautam Jha suggested then you will get 13 in both cases. This is because he effectively reads into a temporary int, and then only stores the temporary int into the real val if the read succeeded, thereby avoiding the behaviour where a failed read sets val to 0.
This is probably the desired behaviour although you might also want to check cnt > 0 to avoid a weird output in the case of totally empty input.
See the difference
#include <iostream>
int main()
{
int c_val = 0,val = 0,cnt = 1;
std::cin>>c_val;
int curr_val = 0;
while(std::cin>>val){ // in case of no value cin will set val =0
curr_val = val;
if(curr_val == c_val)
cnt++;
else{
std::cout<<c_val<<" occurs "<<cnt<< " times"<<std::endl;
c_val = curr_val;
cnt = 1;
}
}
std::cout<<curr_val<<" occurs "<<cnt<<" times";
}
Related
We were asked to write a simple C++ program by our teacher to add two numbers in the following format:
input: 12 14
output: m+n = 26
The program must also work for other inputs in the form:
input: Hello please add 12 and 14 !
output: m+n = 26
The solution that was given was:
#include <iostream>
using namespace std;
int main(){
int m,n;
char ch;
while(cin.get(ch)){
if(isdigit(ch))
{
cin.putback(ch);
cin>>m;
break;
}
}
//cin.putback() restores the last character
//read by cin.get() back to the input stream
while(cin.get(ch)){
if(isdigit(ch))
{
cin.putback(ch);
cin>>n;
break;
}
}
cin.ignore(80,'\n');
cout<<"m + n = "<<m+n<<endl;
return 0;}
But now I need to know why this program also works for numbers that are not single digits. Shouldn't cin.get(char) just read one digit and cin.putback() return the same? Please help me I am a beginner.
Yes, cin.get() will read only one character at a time.
The important part, where the number is actually read, is 4 lines below: cin>>m;. This will consume as many digits as possible and store the resulting integer in m.
Some more details:
// example with input 524 42
while(cin.get(ch)) // extract one character at a time
{ // ch='5', remaining input="24 42"
if(isdigit(ch)) // if it's a digit (0-9), then:
{
cin.putback(ch); // Put it back into the stream, "unread" it
// remaining input="524 42"
cin >> m; // extract an integer from stream
// m=524, remaining input="42"
break;
}
}
The reason for the loops seems to be to skip over any non-numeric input before a number appears. Note that there is a little bug here, since it will also ignore leading signs. (e.g. input -4 4 will output m + n = 8)
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 const double yen_to_euro=0.007215;
7 const double euro_to_dollar=1.12;
8 char currency;
9 double x;
10
11 while(currency!='q')
12 {
13 cout << "enter currency and unit(y , e, or d)";
14 cin >> x >>currency;
15
16 switch(currency){
17
18 case 'y':
19 cout <<"euro:"<< x*yen_to_euro<<" dollar:"<<x*yen_to_euro*euro_to_dollar<<'\n';
20 break;
21 case 'e':
22 cout <<"yen:"<< (x*(1.0/yen_to_euro))<<" dollar:"<<(x*euro_to_dollar)<<'\n';
23 break;
24 case 'd':
25 cout <<" yen:"<< x*(1.0/yen_to_euro)*(1.0/euro_to_dollar)<<" euro:"<<x*(1.0/euro_to_dollar)<<'\n';
26 break;
27 case 'q':
28 currency='q';
29 break;
30 default:
31 cout << "invalid";
32 break;
33
34 }
35
36 }
37
38
39 }
~
The intended function of the code above is to convert a selected currency( y for Japanese Yen, e for Euro , and d for US dollar) into the other currencies.
For instance, if I want to convert to 12 Japenese Yen, I would enter:
12y
which then the program would output
euro:0.08658 dollar:0.0969696
However, if I were to input 12e, I would receive an infinite loop. Double checking the code, there doesn't seem to be any logical errors.
Nevertheless, I sense the source of the trouble has to do with the cin at line 14 because if I take the amount x and the currency type separately like this:
cin>> x;
cin>> currency;
The code works fine, but I need to input the amount , followed by pressing enter, and then pressing the character that represents the currency-type. Is there a way to just enter all in one line, no spaces?
Furthermore, why is it behaving this way? This unusual behavior of going through infinite loop only happens when I enter e for Euro and q for quit.
12e is interpreted as the begin of a floating point number like 12e03. But the end is missing, so your stream is put on error (failbit). This state causes all subsequent input to fail until the failstate is cleared.
You could have an inner loop that checks such formatting errors:
while (...) {
...
while ( (cin >> x >> currency).fail() && !cin.eof()) { // loops as long as there's input and it's invalid
cout << "invalid format";
cin.clear();
}
if (cin.eof()) // if there's no longer input stop looping
break;
...
}
live demo
Note that you should initialize currency to something different than 'q' if you want to make sure that your loop is executed in every circumstance.
By the way, if you enter 12 e (with a space), 12 will be interpreted as the number and put to x and e to currency, as you expect.
As explained by other answers 12e refers to the scientific notation of floating point numbers and hence currency does not store 'e'.
To get the input in a single line without space, you should use std::getline and then parse the input string.
Since you know that the last character is always indicative of currency, the front characters can be converted to a number using std::stoi.
Replace cin >> x >>currency;
with
try{
std::string myLine;
std::getline (std::cin, myLine); // store line into myLine.
currency = myLine.back(); // get last character from line.
myLine.pop_back(); // remove last character from myLine.
x = std::stod(myLine); // try to conver the rest of the string to a double.
}
catch (...) {
//The user typed in something invalid.
currency= 'i';
}
Also, make sure to #include <string>
Note this solution assumes you are using C11.
I'm a beginner of C++,while reading the book 《C++ Primer》 5th,I'm a little confused in chapter 1.4.4.
when I run the program in 1.4.4,here is the step in my computer:
#include <iostream>
int main()
{
// currVal is the number we're counting; we'll read new values into val
int currVal = 0, val = 0;
// read first number and ensure that we have data to process
if (std::cin >> currVal)
{
int cnt = 1; // store the count for the current value we're processing
while (std::cin >> val)
{ // read the remaining numbers
if (val == currVal) // if the values are the same
++cnt; // add 1 to cnt
else
{ // otherwise, print the count for the previous value
std::cout << currVal << " occurs " << cnt << " times" << std::endl;
currVal = val; // remember the new value
cnt = 1; // reset the counter
}
} // while loop ends here
// remember to print the count for the last value in the file
std::cout << currVal << " occurs " << cnt << " times" << std::endl;
} // outermost if statement ends here
return 0;
}
type the numbers:42 42 42 42 42 55 55 62 100 100 100
type Ctrl+D
the program run by itself(not waitting me to input Enter)
output the answer:
42 occurs 5 times
55 occurs 2 times
62 occurs 1 times
secondly type Ctrl+D
output the remained answer
100 occurs 3 times
my question is why I have to input second times of Ctrl+D,my code environment is Ubuntu+GCC,I also run it in VS2013,it only needs to input once Ctrl+D.
I've searched in stackoverflow,but I didn't got my answer.
Incorrect output. C++ primer 1.4.4
confused by control flow execution in C++ Primer example
C++ Primer fifth edtion book (if statement) is this not correct?
In Linux Ctrl+D does not unconditionally mean "end-of-file" (EOF). What it actually means is "push the currently pending input to whoever is waiting to read it". If the input buffer in non-empty, then hitting Ctrl+D does not create EOF condition at the end of the buffer. Only if you hit Ctrl+D when the input buffer is empty, only then it will produce EOF condition. (See here for a more technical explanation: https://stackoverflow.com/a/1516177/187690)
In your case you are inputting your data as a single line and then hitting Ctrl+D at the end. This pushes your input to your program and makes your program to read and process the data. But it does not produce EOF condition at the end of your input.
For this reason, once all input data is read by the cycle, your program does not see it as EOF. The cycle keeps waiting on empty input buffer for additional data. If at this point you press Ctrl+D again, it will be recognized as EOF and your program will exit the cycle and print the last line.
This is why you have to hit Ctrl+D twice: the first hit works pretty much as Enter key would. And only the second hit creates EOF condition.
It is possible that the program you have provided was not intended to accept input all at once as you have shown.
The reason it does not provide the output you expect is due to the fact that the program is still expecting input, because the >> operation's return value is still logically true/error-free. (It's blocked at: while (std::cin >> val)) This is so, because you have not provided an EOF to the input stream after the last 100. Said another way, your first Ctrl+D gets past the if (std::cin >> currVal). Your second Ctrl+D gets past the while (std::cin >> val).
See the accepted answer to this question for why the first Ctrl+D does not result in a eofbit error on your input stream: Why do I have to type ctrl-d twice? The bottom line is that Ctrl+D does not necessarily mean EOF; it results in a flush of the input stream.
Entering the numbers one at a time would provide the output you expect.
Alternatively, you could provide: 42 42 42 42 42 55 55 62 100 100 100\n.
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
**EDIT: I got it to work by changing the 'inStream >> next' to 'inStream >> skipws >> next'. In one of my earlier functions (to pull the last and first name) I had toggled noskipws. Apparently that toggle lasts between functions?
I have a program that is part of an assignment that is supposed to read a text file that is set up in the format of: "lastname firstname 1 2 3 4 5 6 7 8 9 10" (where each of the 10 numbers are integer scores).
I am able to read in the lastname and firstname fine, but when I go to start reading in the numbers, I am only able to read in the first one and then all the rest get set to 0.
Below is the function that is supposed to read the scores in. inStream has already had the lastname and firstname taken off. The textfile I am using has one line:
Tosis Halley 85 23 10 95 43 12 59 43 20 77
When run the program and print out the student.score values from 0 to 9, the first one displays correctly as '85' but all the reset show as '0'. Thoughts?
void GetScores (ifstream& inStream, record& student)
{
int score[10] = {-1, -1, -1, -1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1};
int next;
int counter = 0;
string test;
for (int i = 0; i < 10; i++)
{
inStream >> next;
student.score[i] = next;
}
}
Assuming the input is indeed all numbers, the function should actually work. However, you should always verify that inputs were indeed read correctly:
for (int i = 0; i != 10 && inStream >> next; ++i) {
student.score[i] = next;
}
if (!inStream) {
std::cout << "an input error occured\n";
}
so I'm trying to write a program that would take an input character between 0 and 127 and then output a string of numbers in the following form:
- If I input a 0, the output should be a 0
- If I input a 5, the output should be 012345
- If I input a 9, the output should be 0123456789
- If I input a 14, the output should be 012345678901234
- If I input a 27, the output should be 0123456789012345678901234567
So, I'm looking for increments of 10 characters from 0 to 9 at most and then repeat the sequence until the last number is reached. So in 27, there's actually 28 characters output due to the first 0, but the last one is still a 7.
I know I want to use for loops, but I'm having a bit of a trouble figuring out how to make this happen. I can probably use the the ASCII 48 through 57 for the output, but my problem is how I make the input work... should I static cast it to an integer and then work with that? I'm kind of hitting a wall here.
Try the following:
#include <iostream>
int main() {
char input;
std::cin >> input;
if (input >= 0 && input <= 127) {
for (int i = 0; i <= n; i++) std::cout << i % 10;
}
}