I have a couple of problems, that I think are closely connected, but I couldn't get them fixed following what I previously found on the website.
My problems are related to the double use of cin in my main function. I need to read numbers from keyboard in order to either build small vectors or store single coefficients. I cannot know in advance the length of the vectors that I am going to build.
Here are the lines involved:
#include <vector>
#include <iostream>
#include <limits>
int main() {
...
double a=0;
std::vector<double> coefficients;
while (std::cin>>a) {
coefficients.push_back(a);
}
...
std::vector<double> interval;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
while(std::cin>>a) {
interval.push_back(a);
}
std::cout<<interval.size()<<std::endl;
std::cout<<*interval.cbegin()<<" "<<*(interval.cend()-1)<<std::endl;
...
}
I am using both macOS with g++ 6.3.0 and Linux with g++ 5.3.0. The flags I send to the compiler are -Wall -std=c++14 -o.
On the macOS machine the second cin is completely skipped, while on the Linux one the second reading process does not behave like it is expected to. I mean that if i give -1 1 at the second cin, the printed vector size is 0 and, obviously, the program stops because of a segmentation fault.
At each cin I enter the requested numbers in a single line, like 1 0 0 1, then press enter and then ctrl+D.
Thanks in advance to all! :)
Your call of std::cin.ignore(...) set the fail bit of the stream. This makes it impossible to enter the loop. You need to move the std::cin.clear() call right before the loop, in order to make it run. Also you have an out-of-bound read when there are no data in the second container.
#include <vector>
#include <iostream>
#include <limits>
#include <string>
int main() {
double a=0;
std::vector<double> coefficients;
while (std::cin>>a) {
coefficients.push_back(a);
}
std::cout << coefficients.size() << '\n';
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'X');
std::cin.clear();
char c;
std::cin>>c;
if(c != 'X')
{
std::cerr << "Invalid separator\n";
return 1;
}
std::vector<double> interval;
while(std::cin >> a) {
interval.push_back(a);
}
std::cout<< interval.size()<<std::endl;
if(interval.size())
std::cout<<*interval.cbegin()<<" "<<*(interval.cend()-1)<<std::endl;
return 0;
}
With the following data file,
$ cat data.txt
12 23
42
X
1 2
3 4 5
this output is generated:
$ ./a.out < data
3
5
1 5
You need to add a linefeed '\n' as a second parameter to cin.ignore() so it kills the ignore on an enter press
Related
Before, when I was writing C++, I often used getch() for validation. However, now I am turning into competitive programming, I cannot use getch(); I had to use cin or getline. Thus, today, I replicated an instance of splitting a string using stringstream:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main() {
string line;
getline(cin, line);
cout << line << endl;
stringstream reader;
reader.clear();
reader.str(line);
vector<long long int> list;
while (true) {
reader.clear();
if (reader.str().size() == 0) {
break;
}
long long int value;
reader >> value;
list.push_back(value);
}
}
Then, I ran the program, typed 1 2 3 4 5 6 7 8 9 and pressed enter. The program successfully displayed line, 1 2 3 4 5 6 7 8 9, but the program just didn't terminate. It never approached the end of the main() function. I tried to print reader.str(), but it just print 1 2 3 4 5 6 7 8 9 continually. I was confused. Why reader >> value didn't run and did not read any value? Why was the program running an infinite loop? How can I fix the issue? I appreciate any solution.
The reading operator >> does not change the underlying string. It uses an inner position of a next char to read.
int main() {
int n;
std::istringstream in; // could also use in("1 2")
in.str("1 2");
in >> n;
std::cout << "after reading the first int from \"1 2\", the int is "
<< n << ", str() = \"" << in.str() << "\"\n";
}
Outputs
after reading the first int from "1 2", the int is 1, str() = "1 2"
The loop may be terminated by replacing reader >> value; with
if (!(reader >> value))
break;
... but the program just didn't terminate.
This means that ...
while (true)
true is never false, or ...
reader.str().size() == 0
is never true.
true, in fact, is never false, and you never change the size of the reader's string object. Why would you expect this loop to break?
Please edit your question to make it more clear what you are trying to accomplish.
One of my simple CPP file is taking so much f memory . Any suggestions? I use a macbook air 2017 model for coding
The code is :
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> v;
int x = 0, y, i;
while (1) {
cin >> x;
if (x == 42) {
break;
}
v.push_back(x);
}
for (auto it = v.begin(); it != v.end(); it++) {
if (*it < 42) {
cout << *it << endl;
}
}
return 0;
}
Here's what I get inside the activity monitor
Apparently input file has invalid contents and you do not handle errors well.
Scenario 1:
Input has something what can't be read as int.
1 2 2.0 42 2
Here when 2.0 trying to read int wyo will get value 2. In next iteration attempt to read .0 will fail. std::cin is set to error state and any other read attempts are ignored.
Scenario 2:
Input do not contain termination value 42:
1 2 3 44 55 10
In this case you reach end of file std::cin is set to error state and any other read attempts are ignored.
In both cases x is never set to value 42 and you have infinitive loop which inserts last successful value read as log there is enough memory. When memory is consumed program terminates with std::bad_alloc exception.
To fix it just handle input errors.
I was working on a school project with my friend and we want our program to take integer values from user and store it in a vector as long as the user enter some value and exit the loop for input when user stops inputting numbers.
This was my first sample code which goes on infinitely:
while(cin>>x){
v.push_back(x);
}
There is a condition that the numbers must be greater than one but enter is greater than 0 in integer value so my second code is but it is not working and it also goes on infinitely.
This is my sample code:
while(cin>>x){
if(x<0){
break;
}
else{
v.push_back(x);
}
}
Kindly suggest me a solution thanks in advance :)
Most important part for you is to clearly describe what you want. The program has to have some condition under which it terminates.
Two ideas:
The user enters integer values separated by spaces and then pushes enter
The user enters an integer, presses enter and continues. As soon as he presses enter twice, it terminates.
How to do it:
Simple use cin with a string, delimit by space and then convert to integers.
Use cin with a string but otherwise as you do right now, ask whether the string is "", if not convert to integer.
Not entirely sure but I think you mean something like read the line then extract integers? If so, try something like this - there is no error checking, it will simply discard the everything from the first non-integer. I have left out exceptions and not used and for_each or lambdas or anything fancy. Hopefully will be useful to get you started.
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
std::vector<int> getUserInput(){
std::vector<int> result;
std::string s;
std::getline(std::cin, s);
std::istringstream is(s);
while(is){
int value;
is >> value;
if(is) result.push_back(value);
}
return result;
}
int main(int,char**){
std::vector<int> userValues = getUserInput();
std::cout << "User input values:\n";
for(int value : userValues) std::cout << value << '\n';
return 0;
}
After using Aziuth's suggestion and doing some research on websites like Topcoder and Codechef and other competitive programming websites I think i found a solution without needing to use a string. It takes all the input values until a newline is entered. Thanks a lot everyone for their time and knowledge for this question.
The code is:
while(1){
cin>>x;
v.push_back(x);
char ch = getchar();
if(ch=='\n')
break;
}
This is what I have done to read integers with std::cin and store them in a vector:
int number;
vector<int>ivec;
while (cin>>number)
{
ivec.push_back(number);
}
for (auto v: ivec){
cout << v;
}
Then, I am stuck with the problem that how to stop entering integers and move to the next process of printing the vector out. Any pointer will be appreciated.
It depends on the terminal in use and the precise mechanism varies quite a lot but, conventionally, typing Ctrl+D (Linux) or Ctrl+Z (Windows) will result in an end-of-file "signal" being transmitted along the pipe, causing the EOF bit to be set on cin, and thus the next cin >> number attempt to fail.
That will break the loop.
Conveniently, the same will happen if you ran your executable with redirected input from a file. Which is kind of the point.
The code you posted reads numbers from cin as long as it succeeds. There are two ways to have it stop succeeding: If you enter something that is not a number, reading data still succeeds, but converting it to number fails. This puts cin into the bad state. It can be recovered from using the clear methode. The other way is making the reading of characters from cin fail (for example the end of a file that gets used as input). This puts cin into the failed state. Usually, recovering from a failed state is impossible.
To produce the you can no longer read state at end of file when entering data at the keyboard, operating system specific methods have to be used (likely Control-D or Control-Z). This is final for the invocation of your program.
If you need a way for the user to signal: "Please go on, but let me enter other stuff later", the most clean way is likely reading cin line-by-line and parse the input using strtol or a stringstream, and comparing for a magic stop-token (e.g. empty line, "end") to exit the loop.
You can do it the following way
#include <vector>
#include <iterator>
//...
vector<int> ivec( std::istream_iterator<int>( std::cin ),
std::istream_iterator<int>() );
for ( auto v: ivec ) std::cout << v << ' ';
std::cout << std::endl;
In Windows you have to press key combination Ctrl + z and in UNIX system Ctrl + d
Or you can introduce a sentinel. In this case the loop can look like
int number;
const int sentinel = SOME_VALUE;
for ( std::cin >> number && number != sentinel ) vec.push_back( number );
Please find a simple solution to your problem, let me know if you see any issue with this solution.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> va;
int x;
while ( cin >> x ) {
va.push_back(x);
if ( cin.get() == '\n' ) break;
}
//Vector output
for ( int i = 0; i < va.size(); i++ ) {
cout << va[i] <<" ";
}
return 0;
}
When I write every C++ program, such as that one:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cout << "Tell me where to start: ";
cin >> n;
while (n>0) {
cout << n << "\n";
n = n-1;
}
cout << "FIRE!";
return 0;
}
I compile it with G++ and, when I run it, it works well, but when it finishes it displays the "logout" word after the program's last word, like this:
Tell me where to start: 10
10
9
8
7
6
5
4
3
2
1
FIRE!logout
[Process completed]
Why? And how can I remove it?
It's not from your program. It's because the terminal is opened with the sole purpose of running your program, and as such when it exits, the terminal shuts down.
If you open a shell and manually run your executable, instead of this message, you'll simply get another command prompt.