The input for the program consists of two parts.
The first line of the input is the number of elements, and the second line is all the elements. This is an example input:
5
1 3 23 4 2
Is there a way to deal with this kind of input without using std::string and parsing it to the vector of ints later?
It sounds like this is for a programming competition or some other similar setup where you can trust that the input is properly formatted. If that's the case, yes, you can do this without buffering things through a std::string. Here's one option:
std::size_t size;
std::cin >> size;
std::vector<int> values;
// Could do values.reserve(size); here if you'd like.
for (std::size_t i = 0; i < size; i++) {
std::size_t value;
std::cin >> value;
values.push_back(value);
}
Note that the stream extraction operator operator >> will use any whitespace character as a delimiter, so the newline after the number of elements and the space characters between the numbers themselves will work great as separators. There's no need to pull the entire second line by itself and then parse it apart.
This does no error-checking, which is a real problem if you can't trust the inputs. But if you can, this should do the trick.
Related
I was given a question where the input will be like:
10 8
4 9
6 12
5 4
3
1
Here I don't know the number of lines that contains 2 integers. Those sets of 2 integers will be taken into an array. But when the program encounters "3", it will start taking input in another array.
I have tried this with
while(cin>>a>>b){ //some porcess with a and b }
but it doesn't work because it recognizes 3 and 1 as another set of two integers. Please help me to solve this problem.
cin >> a >> b skips not only spaces, but any delimeter characters too ('\n', '\t', ' ').
Here you actually may want to read input line-by-line and then check if there are two integers or one. Consider use of std::getline for retrieving each line of text. Then you can use read string as std::istream (like in example in the link above) and read from it with counting, how many numbers you read totally.
So think about your problem. Essentially it is, read one line at a time, and if it contains two numbers do one thing, but if it contains one number do something else.
But the code you have written reads numbers not lines. That is where the problem is.
Instead write your code to read only line at a time, analyse that line to see if it contains one or two numbers (or something else) and then proceed from there.
What you need is the ability to read a line of text into a string, and then read from that string into your numbers. To do that you use an istringstream. Something like this
#include <iostream>
#include <sstream>
#include <string>
int a, b;
string s;
getline(cin, s); // read one line from standard input
istringstream line(s); // put that string to a stream we can read from
if (line >> a) // try and read the first number from the stream
{
// got the first number
if (line >> b) // try and read the second number from the stream
{
// got the second number
...
}
else
{
// only one number
...
}
}
else
{
// didn't get any numbers, some sort of error
...
}
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;
}
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)
This is a sort of self-imposed extra credit problem I'm adding to my current programming assignment which I finished a week early. The assignment involved reading in integers from a file with multiple integers per line, each separated by a space. This was achieved easily using while(inFile >> val) .
The challenge I put myself up to was to try and read integers from a file of mixed numbers and letters, pulling out all contiguous digits as separate integers composed of those digits. For examples if I was reading in the following line from a text file:
12f 356 48 r56 fs6879 57g 132e efw ddf312 323f
The values that would be read in (and stored) would be
12f 356 48 r56 fs6879 57g 132e efw ddf312 323f
or
12, 356, 48, 56, 6879, 57, 132, 312, and 323
I've spent all afternoon digging through cplusplus.com and reading cover to cover the specifics of get, getline, cin etc. and I am unable to find an elegant solution for this. Every method I can deduce involves exhaustive reading in and storing of each character from the entire file into a container of some sort and then going through one element at a time and pulling out each digit.
My question is if there is a way to do this during the process of reading them in from a file; ie does the functionality of get, getline, cin and company support that complex of an operation?
Read one character at a time and inspect it. Have a variable that maintains the number currently being read, and a flag telling you if you are in the middle of processing a number.
If the current character is a digit then multiple the current number by 10 and add the digit to the number (and set the "processing a number" flag).
If the current character isn't a digit and you were in the middle of processing a number, you have reached the end of the number and should add it to your output.
Here is a simple such implementation:
std::vector<int> read_integers(std::istream & input)
{
std::vector<int> numbers;
int number = 0;
bool have_number = false;
char c;
// Loop until reading fails.
while (input.get(c)) {
if (c >= '0' && c <= '9') {
// We have a digit.
have_number = true;
// Add the digit to the right of our number. (No overflow check here!)
number = number * 10 + (c - '0');
} else if (have_number) {
// It wasn't a digit and we started on a number, so we hit the end of it.
numbers.push_back(number);
have_number = false;
number = 0;
}
}
// Make sure if we ended with a number that we return it, too.
if (have_number) { numbers.push_back(number); }
return numbers;
}
(See a live demo.)
Now you can do something like this to read all integers from standard input:
std::vector<int> numbers = read_integers(std::cin);
This will work equally well with an std::ifstream.
You might consider making the function a template where the argument specifies the numeric type to use -- this will allow you to (for example) switch to long long int without altering the function, if you know the file is going to contain large numbers that don't fit inside of an int.
I have an text file with binary values in n columns and y rows.
I am using getline to extract every row of the binary values and assign them to vectors:
I am using getline to extract every row of a file, where each row consists of a series of '0' or '1' separated by space, and assign them to a vector.
std::vector< std::vector<int> > matrix; // to hold everything.
std::string line;
while(std::getline(file,line))
{
std::stringstream linestream(line);
int a,b,c,d;
linestream >> a >> sep >> b >> sep >> c >> sep >> d;
std::vector <int> vi;
vi.push_back(a);
vi.push_back(b);
vi.push_back(c);
vi.push_back(d);
matrix.push_back(vi);
}
Now the problem is that I do not know in advance how many columns are there in the file. How can I loop through every line until i reach the end of that line?
The obvious way would be something like:
while (linestream >> temp >> sep)
vi.push_back(temp);
Though this may well fail for the last item, which may not be followed by a separator. You have a couple of choices to handle that properly. One would be the typical "loop and a half" idiom. Another would be a locale that treats your separator characters as white space.
When/if you do that, you can/could also use a standard algorithm:
std::copy(std::istream_iterator<int>(linestream),
std::istream_iterator<int>(),
std::back_inserter(vi));
Why not
while (in1 >> i) row.push_back( i );
Which does not require a separator?
check for a new line character (\n). when you find one, you've completed the line/column.