End array input with a newline? - c++

Not sure if the title is properly worded, but what I am trying to ask is how would you signify the end of input for an array using newline. Take the following code for example. Not matter how many numbers(more or less) you type during the input for score[6], it must take 6 before you can proceed. Is there a method to change it so that an array can store 6 or 100 variables, but you can decide how many variables actually contain values. The only way I can think of doing this is to somehow incorporate '\n', so that pressing enter once creates a newline and pressing enter again signifies that you don't want to set any more values. Or is something like this not possible?
#include <iostream>
using namespace std;
int main()
{
int i,score[6],max;
cout<<"Enter the scores:"<<endl;
cin>>score[0];
max = score[0];
for(i = 1;i<6;i++)
{
cin>>score[i];
if(score[i]>max)
max = score[i];
}
return 0;
}

To detect "no input was given", you will need to read the input as a input line (string), rather than using cin >> x; - no matter what the type is of x, cin >> x; will skip over "whitespace", such as newlines and spaces.
The trouble with reading the input as lines is that you then have to "parse" the input into numbers. You can use std::stringstream or similar to do this, but it's quite a bit of extra code compared to what you have now.
The typical way to solve this kind of problem, however, is to use a "sentry" value - for example, if your input is always going to be greater or equal to zero, you can use -1 as the sentry. So you enter
1 2 3 4 5 -1
This would reduce the amount of extra code is relatively small - just check if the input is -1, such as
while(cin >> score[i] && score[i] >= 0)
{
...
}
(This will also detect end-of-file, so you could end the input with CTRL-Z or CTRL-D as appropriate for your platform)

Related

while loop running for every digit/character from input

Hey guys beginner in C++ and coding in general. I am currently making a tictactoe program. For the part of the program I am validating user input. Since it is a 3x3 table, I want to make sure their input is an integer and that they choose a number between 1~9.
To do this I wrote
//Validating user input
void move() {
std::cout << "It's Player" << player << "'s turn!\n";
while(!(std::cin >> position)){
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(board[position - 1] != " ") {
std::cout << "Already filled please choose another number between 1~9!\n";
std::cin >> position;
}
}
It works but for some reason when I put in an input like 10, it would print Please choose a number BETWEEN 1~9! twice (for each digit) and if I input in for example "apple" it would print Please choose a NUMBER between 1~9! four times (for each character). How do i make it just print out the statement once?
Thank you!
Let me try to explain to you the problem. It is a little bit subtle and not that easy to understand. Both other answers adress only the obvious part.
Then, let us first recap that:
The boolean condition in the while statement is loop invariant. Meaning, it will not be modified within the loop. Whatever it was before the loop, will be the same after the loop body has been executed. The condition will never change.
So, for the case where you enter a wrong number:
If the input number is correct (1..9) and the while statement starts to evaluate the boolean expression, it will be false in this case and the loop will not be entered.
If the number is out of your selected bounds (<1 or >9), then the boolean condition is true. The while loop starts, but the condition relevant variable will not be changed in the loop boody and hence, the boolean expression is always true. The loop will run forever.
Additionally, and now comes the answer to your first question, the following will happen:
The text "Please choose a number BETWEEN 1~9!\n" will be shown (first time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is an unformatted input function. It will actively read the next character from the input buffer, which is the end of line `'\n' character.
We enter again the while statement. The condition is still true (position was not modified in the loop body), and we enter the loop again.
The text "Please choose a number BETWEEN 1~9!\n" will be shown (second time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is a formatted input function. It will actively read the next character from the input buffer. But there is none. So it will wait until a key is pressed. For example "enter". After that, it would go back to number 5.
By the way. If you would now enter "abc" then you would see the text 4 times for a,b,c and enter.
So, please remember: ignore is an input function!
Next. It is important to understand, that if you enter an unexpected value, like "apple" instead of "3", the formatted input function >> can do no conversion and sets the failbit. It will also not extract further wrong characters from the input stream (std::cinis a buffered stream). The characters that could not be converted are still in the buffer and wil be read next time.
Please read here about formatted/unformatted input. And especially read about the extraction operatpr >> here..
There you can read the following:
If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set.
OK, understood. Then, what is going on here, if you enter "abc". Basically, the same as above.
Enter abc
The boolean condition !(std::cin >> position)will be evaluated to true, because an 'a' was read and cannot be converted to a number.
The std::cin's failbit will be set. The variable positionwill be set to 0.
"Please choose a NUMBER between 1~9!\n" will be shown
The failbit will be reset
Ignore will extract exactly the one wrong character and discard it
std::cin >> position`` will be called again and extract the next wrong character 'b'. 3., 4., 5., 6. will be done again. Until the last charcter in the buffer, the newline '\n' will be extracted. Then you may enter the next number.
The fix for that problem is simple:
ignore has a parameter, where you can specify, how many characters shall be ignored. So, not only one, but all until the end of line.
You should write:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will ignore all bad input.
And to fix your whole program, you could write at the top:
while (!(std::cin >> position) or (position < 1 ) or ( position > 9)) {
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
while(position < 1 || position > 9){
This while loop will continue running as long as position is less than 1 or greater than 9, that's what this says.
But there's nothing in the while loop itself that changes the value of position. For that simple reason, if position's value at this point is outside of the range of 1-9, this while loop will execute forever.
You always need to keep in mind The Golden Rule Of Computer Programming: your computer always does exactly what you tell it to do instead of what you want it to do. Here, you told your computer to execute this while loop as long as position is less than 1 or greater than 9, so this is what your computer will do until this is no longer the case.
You can change your code as this. With this you run your while loop ones for every input. Until you get the value as you like. If the value is as you wish, you get out of the loop with break
std::cout << "Please choose a NUMBER between 1~9!\n";
while(std::cin >> position){
std::cin.clear();
std::cin.ignore();
if(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
}else{
break;
}
}

Find out the average value of inputted integers

I managed to get this program to work. If the user types an unfixed amount of integers, the program will calculate the average value of it. But I need to end it with <Ctrl-D> in my terminal (end of file) in order for it to work. Why can I not just press enter for it to work?
I also believe that I've used an unnecessary amount of variables. Can it be narrowed down to maybe 2 variables?
#include <iomanip>
#include <iostream>
using namespace std;
int main ()
{
int digit {};
int res {};
int counter {};
cout << "Type in integers: ";
while (cin >> digit)
{
counter ++;
res += digit;
}
cout << "The mean was " << setw(1) << setprecision(1) << fixed << static_cast<double>(res) / static_cast<double>(counter) << endl;
return 0;
}
Why can I not just press enter for it to work?
Because that's not how the overloaded >> formatted extraction operator works. This operator skips over an unlimited amount of whitespace characters, including newline characters, until it reads the integer. It's simply how it works: it will read newlines and spaces, after newlines, and spaces, until it sees a digit. That's its mission in life: read and skip over spaces and newlines until it reads at least one digit. It never gets tired of reading newlines and spaces, and will keep going as long that's the case.
To handle input in the fashion you describe requires a completely different approach: using std::getline to read a single line of input into a std::string, up until the next newline character. Then, once that's done, you can check if the std::string is empty, which means that no input was entered, and then terminate; otherwise take the input in std::string and convert it to an int value (using std::stoi, std::from_chars, or a std::istringstream -- take your pick), and then proceed with the existing algorithm.
Can it be narrowed down to maybe 2 variables?
How do you expect to do that? Hard, immutable logic dictates that you must keep track of at least two discrete values: the total sum and the number of values read. But then you just ran out of variables. You have no more variables to use for storing the next read value (if there is one), using whatever approach you chose to use. So, you can't do it. Rules of logic require the use of at least three variables, possibly more depending on how fancy and robust you want your input validation to work.

C++ string calculator

I have been doing exercises on some online judges, and I encounter this question with this default answer.
Question description:
Finally, Hansbug has finally reached the moment to do the last math problem, and there are a bunch of messy addition and subtraction equations in front of him. Obviously success is at hand. But his brain cells have been exhausted, so this important task is left to you.
Input format:
One line, containing a string of addition and subtraction polynomials (the range of each item is 0-32767).
Output format:
An integer, which is the result of the calculation (guarantee that the result of the calculation will not exceed the range of the long integer).
Input and output sample:
Enter #1:
1+2-3
Output #1:
0
And the default answer is :
#include<bits/stdc++.h>
using namespace std;
int ans;
int c;
int main() {
while (cin >> c)
ans += c;
cout << ans;
return 0;
}
How is this even possible!?
All right, let's try it, let's put there some expression with addition and subtraction of ints only, after that press Return, then ctrl+D (end of input):
$ ./a.out
111-222+1
-110$
The loop while (cin >> c) will parse integers including the sign one by one using iostream capabilities until an end of input (you also have to terminate the last number by pressing Return, effectively putting the newline there and triggering the last cin >> c).

Time limit exceeded on test 10 code forces

hello i am a beginner in programming and am in the array lessons ,i just know very basics like if conditions and loops and data types , and when i try to solve this problem.
Problem Description
When Serezha was three years old, he was given a set of cards with letters for his birthday. They were arranged into words in the way which formed the boy's mother favorite number in binary notation. Serezha started playing with them immediately and shuffled them because he wasn't yet able to read. His father decided to rearrange them. Help him restore the original number, on condition that it was the maximum possible one.
Input Specification
The first line contains a single integer n (1⩽n⩽105) — the length of the string. The second line contains a string consisting of English lowercase letters: 'z', 'e', 'r', 'o' and 'n'.
It is guaranteed that it is possible to rearrange the letters in such a way that they form a sequence of words, each being either "zero" which corresponds to the digit 00 or "one" which corresponds to the digit 11.
Output Specification
Print the maximum possible number in binary notation. Print binary digits separated by a space. The leading zeroes are allowed.
Sample input:
4
ezor
Output:
0
Sample Input:
10
nznooeeoer
Output:
1 1 0
i got Time limit exceeded on test 10 code forces and that is my code
#include <iostream>
using namespace std;
int main()
{
int n;
char arr[10000];
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
for (int i = 0; i < n; i++) {
if (arr[i] == 'n') {
cout << "1"
<< " ";
}
}
for (int i = 0; i < n; i++) {
if (arr[i] == 'z') {
cout << "0"
<< " ";
}
}
}
Your problem is a buffer overrun. You put an awful 10K array on the stack, but the problem description says you can have up to 100K characters.
After your array fills up, you start overwriting the stack, including the variable n. This makes you try to read too many characters. When your program gets to the end of the input, it waits forever for more.
Instead of putting an even more awful 100K array on the stack, just count the number of z's and n's as you're reading the input, and don't bother storing the string at all.
According to the compromise (applicable to homework and challenge questions) described here
How do I ask and answer homework questions?
I will hint, without giving a code solution.
In order to fix TLEs you need to be more efficient.
In this case I'd start by getting rid of one of the three loops and of all of the array accesses.
You only need to count two things during input and one output loop.

how to ignore n integers from input

I am trying to read the last integer from an input such as-
100 121 13 ... 7 11 81
I'm only interested in the last integer and hence want to ignore all
previous integers.
I thought of using cin.ignore but that won't work here due to
unknown integers (100 is of 3 digits, while 13 is of 2 digits & so on)
I can input integer by integer using a loop and do nothing with them. Is there a better way?
It all depends on the use case that you have.
Reading a none specified number of integers from std::cin is not as easy at it may seem. Because, in contrast to reading from a file, you will not have an EOF condition. If you would read from a file stream, then it would be very simple.
int value{};
while (fileStream >> value)
;
If you are using std::cin you could try pressing CTRL-D or CTRL-Z or whatever works on your terminal to produce an EOF (End Of File) condition. But usually the approach is to use std::getline to read a complete line until the user presses enter, then put this line into a std::istringstream and extract from there.
Insofar, one answer given below is not that good.
So, next solution:
std::string line{};
std::getline(std::cin, line);
std::istringstream iss{line};
int value{};
while (iss >> value)
;
You were asking
Is there a better way?
That also depends a little. If you are just reading some integers, then please go with above approach. If you would have many many values, then you would maybe waste time by unnecessarily converting many substrings to integers and loose time.
Then, it would be better, to first read the complete string, then use rfind to find the last space in the string and use std::stoi to convert the last substring to an integer.
Caveat: In this case you must be sure (or check with more lines of code) that there are no white space at the end and the last substring is really a number. That is a lot of string/character fiddling, which can most probably avoided.
So, I would recommend the getline-stringstream approach.
You can try this simple solution for dynamically ignoring rest of the values except the last given in this problem as shown:
int count = 0;
int values, lastValue; // lastValue used for future use
std::cout << "Enter your input: ";
while (std::cin >> values) {
lastValue = values; // must be used, otherwise values = 0 when loop ends
count++;
}
std::cout << lastValue; // prints
Note: A character must be required to stop the while(), hence it's better put a . at last.
Output example
Enter your input: 3 2 4 5 6 7.
7
Try this:
for( int i=0; i<nums_to_ignore; i++) {
int ignored;
std::cin >> ignored;
}