how can i use (!(cin>>a)) twice times? - c++

enter image description here
i have used code ( if (!(cin >> arr[i])) ) to check if input from user is different with type int (like string, char) to stop reading into array (arr1), and then i can't use it twice with the second array (arr2), it didn't read input and go straight to cin.clear and return... Can you help me? Thank you very much from it^^
enter image description here

It seems you mean the following
#include <limits>
//...
if ( not ( std::cin >> arr[i] ) )
{
//...
std::cin.clear();
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}

Below is the complete working example in 2 ways. The program given read as many integers as the user enters on the console. For example the user can enter 30 or 300 inputs some which may be integer types and other may be of some other types like string. The array/vector will add only integer type input inside itself as you require.
Solution 1: Using built in array
#include <iostream>
#include <sstream>
#include <string>
int main()
{
std::string line;
//in case of using array, size must be fixed and predetermined
int arr[4] = {0}; //all elements are initialzed to zero. Also you can choose array size according to your needs
int i = 0;//this variable will be used to add element into the array
int count = 0;
getline(std::cin, line);
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
arr[count] = i;
++count;
if(count>=4)
{
break;//break the loop so that you don't go beyond array size
}
}
}
//print out the elements of the array
for(int i: arr)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
Solution 1 can be checked here.
Solution 2: Using std::vector
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
int main()
{
std::string line;
std::vector<int> vec;
int i = 0;//this variable will be used to add element into the array
getline(std::cin, line);
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof())
{
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
vec.push_back(i);
}
}
//print out the elements of the array
for(int i: vec)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
Solution 2 can be checked here.
Important Note
The advantage of using std::vector over built in array(in this case) is that you don't have know the size of the vector beforehand. That is std::vector's size is not fixed as opposed to built in arrays. So it is preferable because you don't know how many input the user is going to enter. std::vector can handle this accordingly and add only valid(integer type) input. But when using built in arrays you must know/specify the size of the array beforehand. This in turn means you must know beforehand how many integers the user is going to enter, which is not practical.

Related

Stop input loop when input is done | std::cin

I want to write a function that gets a set of integers and saves them to a vector.
To get the integers I'm using a while loop.
Enter the vector elements: 1 2 3 4 5
I want the loop to stop looking for input after the last element is inputted or until a non-numberis inputted, however I'm having trouble with it.
It is an assignment, so it needs to read input from std::cin.
This is my code:
#include <iostream>
#include <vector>
bool NumInVect(int num, std::vector<int> vect)
{
bool numInVect = false;
for (int i = 0; i < vect.size(); i++)
{
if (vect[i] == num)
{
numInVect = true;
}
}
return numInVect;
}
int main() {
std::vector<int> tempVect;
std::vector<int> finalVector;
std::cout << "Enter the vector elements: ";
int currVal;
while (std::cin >> currVal)
{
std::cout << "-\n";
if (!NumInVect(currVal, tempVect))
{
tempVect.push_back(currVal);
}
std::cout << currVal << std::endl;
}
//the code never reaches this loop, since its stuck in the while loop
std::cout << "knak\n";
for (int i = 0; i < tempVect.size(); i++)
{
std::cout << tempVect[i];
}
}
I've tried doing multiple things like using std::cin.eof()/.fail(), std::cin >> currVal in the while loop, a do-while loop, but I can't seem to figure out how to get this to work. Does anyone have any tips on what to look into or how to approach this?
If your intention is to get all the input from a given line, and add individual numbers to the vector, then you want to read a line of input into a string, then use an istringstream to process that line of input.
A simplified example:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::vector<int> tempVect;
std::string line;
std::getline( std::cin, line );
std::istringstream iss( line );
int curVal;
while ( iss >> curVal ) {
tempVect.push_back( curVal );
}
}
You should add a condition in your while loop so that it breaks when you want like:
if (temptVect.size() >= 5)
break;
I want the loop to stop looking for input after the last element is inputted or until a non-numberis inputted,
This loop should do exactly that.
while (std::cin >> currVal)
{
std::cout << "-\n";
if (!NumInVect(currVal, tempVect))
{
tempVect.push_back(currVal);
}
std::cout << currVal << std::endl;
}
This test while (std::cin >> currVal) will fail if read does not work and exit the loop. Since currVal is an integer, it will fail as soon as it tries to read something that is not an integer (note space and new lines are completely ignored).
What may be the issue is that std::cin is buffered. You can type a long time before filling up the buffer and causing the operator>> to do anything. To force this operator to read you have to force a flush this is usually done by hitting <enter> on the keyboard.
After the buffer is flushed it will read all the numbers on the input and exit the loop if a read fails. So you need to explicitly type not a number before hitting the <enter>.
eg:
1 2 3 4 5 X<enter>
or:
1<enter>
2<enter>
3<enter>
4<enter>
5<enter>
X<enter>
You need that non number to force the read to fail and the loop to exit.
Alternatively, you could say I want to read all the numbers on one line then exit the loop.
In that case: You should read a line and the processes the line. This is only a slight change from your above code.
std::string line; // Hold a line of text
std::getline(std::cin, line); // Read a line of text.
std::stringstream lineStream(line); // Convert string into stream
while (lineStream >> currValue) // Read each integer from the stream.
{ // Exits when the read fails to read
// a number becuase it is empty.
// The other stuff like before.
}

trying to read data file, store in array and print all the elements but it isnt working

not sure what i'm doing wrong but this is my code
int main (){
int marks [100];
int i=0;
ifstream inputfile;
ofstream outputfile;
inputfile.open("data.txt");
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
return 0;
}
cout<<"Marks in File:"<<endl;
while (marks [i] != -1)
{
inputfile>>marks[i];
cout << marks[i] <<endl;
i++;
}
return 0;
}
the output is messed up and returns stuff that was never in the data file to begin with
Here is the minimal code for reading data from a file and write it to console. Description is added as comments
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
ifstream configrecord("D:\\Temp\\temp.txt"); // opening the file named temp for reading.
if(configrecord.good()) // check whether the file is opened properly.
{
string line;
while (getline(configrecord, line)) // reading a line from file to std::string
{
cout << line; // printing the line, if you want it to store in an array, you can use the std::string::data() api to get the character pointer.
}
configrecord.close(); // closing the file after reading completed
}
}
If we translate your code to English, we get:
Check if the current array element is -1, if it is, break the loop.
Read the value into the current array element.
Output the value.
Move to the next array element and repeat.
Notice a big problem: We're checking if the value is -1 before we actually read it. We need to reverse the order of steps 1 and 2 so that we get:
Read the value into the current array element.
Check if the current array element is -1, if it is, break the loop.
Output the value.
Move to the next array element and repeat.
We can do this by using true as our loop condition and then using an if statement to check if the inputted value is -1 later in the loop, using break to break the loop if it is.
#include <fstream>
#include <iostream>
//using namespace std; is considered bad practice
int main()
{
std::ifstream inFile("input.txt");
int marks[100];
//check if file is open stuff...
for(int i = 0; true; i++)
{
inFile >> marks[i];
if(marks[i] == -1) break;
std::cout << marks[i] << '\n'; //endl flushes the buffer, unnecessary here.
}
}
Of Note: it is good practice that if you use an if statement, you also include an else statement. Also, your while loop is confusing, because it stops if it encounters negative one, so I am assuming you know that integer -1 is not in the file.
int n = -1;
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
}
else
{
cout<<"Marks in File:"<< endl;
while(!inputfile.eof()){ // .eof is bad practice, but for this instance it works.
File >> marks[n];
n++; // Essentially the size of the array (Number of values), keeping track of how many values there are will assist you in the output process.
}
}
When you are done reading the file, you should close it and then use the data in the array.
inputfile.close();
Lastly, in order to output an array of data, you must use a for loop or some type of iterator to access the values stored in the array.
for(int i=0; i < n ; i++) // Output array. Where array size is less than n.
{
cout << marks[i] << " "; // " " inputs a space in between each word.
}

Elegant solution to take input to a vector<int>

I am trying to create an vector <int> whose size is not pre-defined. It should take in numbers as long as there are numbers in the input terminal and should stop reading when I hit Enter. I tried many solutions including the ones given here and here. In the second case, I can enter a non-integer to terminate the input to the vector. If I use the first solution (code added below), it listens to the input indefinitely.
Code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
using std::cout;
using std::cin;
using std::vector;
using std::string;
using std::istringstream;
int main()
{
//cout << "Enter the elements of the array: \n";
//vector <int> arr ( std::istream_iterator<int>( std::cin ), std::istream_iterator<int>() );
vector <int> arr;
string buf;
cout << "Enter the elements of the array: \n";
while(getline(cin, buf))
{
istringstream ssin(buf);
int input;
while(ssin >> input)
{
arr.push_back(input);
}
}
cout << "The array: \n";
for(size_t i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
}
return 0;
}
1) I don't feel that typing in a character or a very large number to end listening to input is very elegant. However, the solution with istringstream seems to be the way to go. I am not sure why it doesn't work.
2) Is there any way to detect the Enter from keyboard to terminate listening to input? I tried using cin.get(), but it changed the numbers in the vector.
3) Any other methods or suggestions?
Let's take things one step at a time.
We want to read up until enter is pressed. That means you probably want to use std:getline to read a line.
Then you want to parse it, so you want to put the line into an istringstream.
Then you want to read numbers. While you're reading them, you apparently want to ignore anything other than digits, and you want to keep reading even if you get to a group of digits that can't be converted to a number.
That leaves a few things that aren't entirely clear, such as what to do with that input that's too large to convert? Do you want to just skip to the next? Do you want to read some digits as a number, then read remaining digits as another number?
Likewise, what do you want to do if you get something like "123a456"? Should it be skipped completely, read as "123" (and the "a456" ignored)? Should it be read as "123" and "456", and just the "a" ignored?
For the moment let's assume that we're going to read space-separated groups of characters, and convert all those to numbers that we can. If something is too big to convert to a number, we'll ignore it (in its entirety). If we have a group like "123a456", we'll read the "123" as a number, and ignore the "a456".
To achieve this, we can do something like this:
std::string line;
std::getline(infile, line);
std::istringstream input(line);
std::string word;
std::vector<int> output;
while (input >> word) {
try {
int i = std::stoi(word);
output.push_back(i);
}
catch (...) {}
}
For example, given input like: "123a456 321 1111233423432434342343223344 9", this will read in [123, 321, 9].
Of course, I'm just taking a guess about your requirements, and I haven't worked at making this particularly clean or elegant--just a straightforward implementation of one possible set of requirements.
Please see the comments from #LearningC and #M.M.
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
using std::cout;
using std::cin;
using std::vector;
using std::string;
using std::istringstream;
int main()
{
vector <int> arr;
string buf;
int input;
cout << "Enter the elements of the array: \n";
getline(cin, buf);
istringstream ssin(buf);
while(ssin >> input)
{
arr.push_back(input);
}
cout << "The array: \n";
for(size_t i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
}
return 0;
}

Input file checking using getline an >> operator in c++

I have written a code here which reads a input file line by line and creates a vector of vectors which I then use as a matrix, later on, in my homework. This is the code:
vector<vector<int>> inputMatrix;
string line;
while(!file.eof())
{
getline(file, line);
stringstream ss(line);
int num;
vector<int> temp;
while(ss >> num)
{
temp.push_back(num);
}
inputMatrix.push_back(temp);
}
However, some input files may contain non-integer values. I would like to integrate a input check feature for the matrix creation so that when there is a non-integer value in the input file, my program would quit.
How can I achieve this? Would it be possiple to write somewhere in this while loop or somewhere else in the code?
thank you very much in advance.
From cppreference.com:
If extraction fails, zero is written to value and failbit is set. If
extraction results in the value too large or too small to fit in
value, std::numeric_limits::max() or std::numeric_limits::min()
is written and failbit flag is set.
So you could simply add an if clause after your while loop:
while (ss >> num)
{
temp.push_back(num);
}
if (ss.fail()) // explicitly check for failbit
{
expected_integer_error();
}
I would like to integrate a input check feature for the matrix creation so that when there is a non-integer value in the input file, my program would quit.
The stringstream already does this check for you. You can simply test its state after the while loop. If it failed to parse a non integer value, the failbit will be set to true.
Here's a working demo (with some small improvements):
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
vector<vector<int>> inputMatrix;
string line;
while(getline(cin, line))
{
istringstream iss(line);
int num;
vector<int> temp;
while(iss >> num)
{
temp.push_back(num);
}
if(!iss) {
cout << "Bad input detected!" << endl;
return 1;
}
inputMatrix.push_back(temp);
}
return 0;
}
Input
12 13 46 3
42 2.6 5
Output
Bad input detected!

How to stop recursion if nothing is inputed in cin?

I am writing a program that must print numbers at first which was entered at last.
So here is my code:
#include <iostream>
using namespace std;
void recursive()
{
long long n;
if((cin>>n)&&(!cin.eof())) // Dont work because enter is ignored in cmd window os
recursive();
cout<<n<<endl;
return;
}
int main()
{
recursive();
return 0;
}
Any idea how to stop function when nothing is input? Or how to solve problem in another way?
Thanks
As your program is right now it will read the long long's until cin's operator void* indicates that the value read was not compatible (but still prints the n , filled with garbage,that it failed to read), as you notice it ignores the blank lines.
If I understand correctly, what you want is that when the user inputs a blank line the program should output the numbers read, a simple way to do this would be to read the input as a string, then check the string's length, and use a stringstream to convert it to the appropriate type.
#include <iostream>
#include <sstream>
#include <string>
void recursive()
{
std::string input;
long long n;
if ( std::getline(std::cin,input) && input.length() > 0 )
{
std::istringstream ss(input);
if (ss >> n)
{
recursive();
std::cout << n << std::endl;
}
}
}
int main ()
{
recursive();
return 0;
}
edit
Here's another way, if your input comes in the form 46 798 4163 4654 32132, it uses std::cin.peek() that returns the next character in the input without extracting it, the result of peek() is compared to '\n' to test if the user pressed enter, and if that's the case it prints the number it just read without waiting for the next number
#include <iostream>
#include <sstream>
#include <string>
void recursive_in_a_line ()
{
long long n;
if (std::cin >> n)
{
if (std::cin.peek() != '\n')
{
recursive();
}
std::cout<< n << std::endl;
}
}
int main ()
{
recursive_in_a_line();
return 0;
}
Do you have to implement the program in a recursive way?
An alternative solution that does not use recursion would be to read the numbers in a while loop and add them to a container (a list or a vector), then display the content of the container.