So I have written a program that runs as intended when taking input from a file, but throws a "runtime exceeded" error (I'm using onlinegdb). The input in both cases is separated like so:
```
input
```
I copied this into a text file and it worked, but entering the input as standard input at the bottom of the screen does not work. I can also input to console, which also works fine. My readFromFile function is the same function but with file I/O functions instead of cin. This is my first time really experimenting with input/output. Please help!!
void readFromInput() {
string Word;
int count = 0;
while (cin >> Word) {
if (Word == "```") {
count++;
}
if (count == 2) {break;} //exit after recieving opening and closing ```
if (Word == "Add") {
//do stuff
}
if (Word == "Charge") {
//do stuff
}
if (Word == "Credit") {
//do stuff
}
}
return;
}
There are a couple of special features of the standard input/output that don't apply to normal file streams:
The C++ std::cin and std::cout is linked to the C streams by default. To keep these in sync is expensive. If you are not using C streams this is not necessary. To remove this cost unlink them:
int main()
{
std::ios::sync_with_stdio(false);
}
If your code uses input and output streams. Reading from std::cin forces std::cout to be flushed (to make sure user questions reflect the input question). This can be inefficient if the two are not linked. So untie them,
int main()
{
std::cin.tie(nullptr);
}
Prefer to use '\n' over std::endl to avoid extra flushes.
Related
I want to read a line of integers from the user. I'm not sure how to check to see if the input has ended. For example I want to be able to do something like
int x[MAX_SIZE];
int i = 0;
while(cin.hasNext())
{
cin >> x[++i];
}
Example input: 2 1 4 -6
how can I check to see if there's any more for cin to take?
Yo have to do the following
int temp;
vector<int> v;
while(cin>>temp){
v.push_back(temp);
}
also you can check for end of input using
if(cin.eof()){
//end of input reached
}
If cin is still interactive, then there's no notion of "no more input" because it will simply wait for the user to provide more input (unless the user has signaled EOF with Ctrl+D or Ctrl+Z as appropriate). If you want to process a line of data, then get a line from the user (with, say, getline) and then deal with that input (by extracting out of a stringstream or similar).
It is very straightforward. All you need to do is perform the extraction as the condition:
while (i < MAX_SIZE && std::cin >> x[i++])
if the extraction fails for any reason (no more characters left, invalid input, etc.) the loop will terminate and the failure will be represented in the stream state of the input stream.
Considering best practices, you shouldn't be using static C-arrays. You should be using the compile-time container std::array<T, N> (or std::vector<T> if the former is not supported).
Here is an example using std::vector. It also utilizes iterators which does away with having to explicitly create a copy of the input:
std::vector<int> v{ std::istream_iterator<int>{std::cin},
std::istream_iterator<int>{}};
You might want something like this:
int inp;
while(cin >> inp){
....
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
....
}
The while loop runs as long as the I/O is successful. Assuming you want to end input when the line of integers ends, you set the eofbit manually when a \n is encountered. This is checked with the condition if(cin.peek() == '\n'). When the condition is true the while loop terminates. In the example below, I demonstrate how to read a line of integers separated by space into a vector and then print it separated by space
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
int main(){
vector<int> coll;
int inp;
while(cin >> inp){
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
coll.push_back(inp);
}
copy(
coll.cbegin(),
coll.cend(),
ostream_iterator<int>(cout, " ")
);
cout << endl;
}
using fstream you can do something like this
ifstream ifile("input.txt");
while(!ifile.eof())
{
/* do something */
}
you can also use this
if(!ifile.is_open())
{
/* do something */
}
The idea is silimar with this code below so you can try :
int tmp;
while(cin >> tmp != NULL){ // C++ or while(scanf("%d", &tmp) != -1) {} for C
// do something
}
I usually detect end of cpp stream below:
while (cin.peek() != EOF) {
// To do your stuff...
// NOTE: peek() will set failbit when peeking end of stream and return EOF(-1).
}
So i'm trying to read in a string of characters twice using cin.get(). The input is being redirected as "program < input". So it is valid to use seekg().
As the titel says, I thought I would be able to use seekg() to save the beginning position of the string, so I could come back to use the starting position of the same string again.
Here is my attempt:
char c;
while (cin.get(c))
{
//do stuff
}
cin.seekg(0, ios::beg);
while (cin.get(c))
{
//do stuff with the string a second time
}
The second while loop isn't doing anything, so I'm obviously not using seekg correctly. Could someone tell me what I'm doing incorrectly?
Thanks for any help!
You can't seek on streams/pipes. They don't continue to exist in memory. Imagine the keyboard is directly connected to your program. The only operation you can do with a keyboard is ask for more input. It has no history.
If it's just a keyboard you can't seek, but if it's redirected with < in the shell seeking works fine:
#include <iostream>
int main() {
std::cin.seekg(1, std::ios::beg);
if (std::cin.fail())
std::cout << "Failed to seek\n";
std::cin.seekg(0, std::ios::beg);
if (std::cin.fail())
std::cout << "Failed to seek\n";
if (!std::cin.fail())
std::cout << "OK\n";
}
Gave:
user#host:/tmp > ./a.out
Failed to seek
Failed to seek
user#host:/tmp > ./a.out < test.cc
OK
You can't do that. std::cin is usually connected to a terminal, and so random access is out of the question.
You could do that if the stream you were using was a std::istringstream or an std::ifstream.
My advice is to read all the characters from std::cin into a single std::string, then create a std::istringstream from that string, and then try your techniques on that std::istringstream instead of std::cin.
You cannot seek on streams. You must unget the characters.
You can't seek on streams, but you can use either std::cin.peek() or std::cin.unget().
1) By using cin.peek()
char c;
while (c = cin.peek())
{
//do stuff
}
while (cin.get(c))
{
//do stuff with the string a second time
}
2) By using cin.unget()
char c;
while (cin.get(c))
{
//do stuff
}
cin.unget();
while (cin.get(c))
{
//do stuff with the string a second time
}
int main()
{
if (cin)
{
(...)
}
else
{
cerr << "No Data!!!" << endl;
}
}
I want to check if the input has any data, but the error message won't be displayed even if I only input Ctrl+Z at the beginning.
Before you attempted to read, the stream won't know whether there is any useful data. At the very least you'll need to look at the first character, e.g., using
if (std::cin.peek() != std::char_traits<char>::eof()) {
// do something with the potentially present input.
}
else {
// fail
}
More likely you'll depend on some non-space data to be available. If so, you could see if there is something other than space in the file:
if (!(std::cin >> std::ws).eof())
...
The manipulator std::ws will skip leading whitespace. It will stop when either a non-whitespace character or the end of file is reached. If the end of file is reached, std::cin.eof() will be true.
In general, I wouldn't bother but rather try to read the first item. If nothing at all is read it would still be viable to fail:
bool hasData = false;
while (std::cin >> some >> data) {
hasData = true;
// do something with the input
}
if (!hasData) {
// report that there was no data at all
}
The no data case may be implicitly testable, e.g., by looking at the size of a read data structure.
I want to read a line of integers from the user. I'm not sure how to check to see if the input has ended. For example I want to be able to do something like
int x[MAX_SIZE];
int i = 0;
while(cin.hasNext())
{
cin >> x[++i];
}
Example input: 2 1 4 -6
how can I check to see if there's any more for cin to take?
Yo have to do the following
int temp;
vector<int> v;
while(cin>>temp){
v.push_back(temp);
}
also you can check for end of input using
if(cin.eof()){
//end of input reached
}
If cin is still interactive, then there's no notion of "no more input" because it will simply wait for the user to provide more input (unless the user has signaled EOF with Ctrl+D or Ctrl+Z as appropriate). If you want to process a line of data, then get a line from the user (with, say, getline) and then deal with that input (by extracting out of a stringstream or similar).
It is very straightforward. All you need to do is perform the extraction as the condition:
while (i < MAX_SIZE && std::cin >> x[i++])
if the extraction fails for any reason (no more characters left, invalid input, etc.) the loop will terminate and the failure will be represented in the stream state of the input stream.
Considering best practices, you shouldn't be using static C-arrays. You should be using the compile-time container std::array<T, N> (or std::vector<T> if the former is not supported).
Here is an example using std::vector. It also utilizes iterators which does away with having to explicitly create a copy of the input:
std::vector<int> v{ std::istream_iterator<int>{std::cin},
std::istream_iterator<int>{}};
You might want something like this:
int inp;
while(cin >> inp){
....
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
....
}
The while loop runs as long as the I/O is successful. Assuming you want to end input when the line of integers ends, you set the eofbit manually when a \n is encountered. This is checked with the condition if(cin.peek() == '\n'). When the condition is true the while loop terminates. In the example below, I demonstrate how to read a line of integers separated by space into a vector and then print it separated by space
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
int main(){
vector<int> coll;
int inp;
while(cin >> inp){
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
coll.push_back(inp);
}
copy(
coll.cbegin(),
coll.cend(),
ostream_iterator<int>(cout, " ")
);
cout << endl;
}
using fstream you can do something like this
ifstream ifile("input.txt");
while(!ifile.eof())
{
/* do something */
}
you can also use this
if(!ifile.is_open())
{
/* do something */
}
The idea is silimar with this code below so you can try :
int tmp;
while(cin >> tmp != NULL){ // C++ or while(scanf("%d", &tmp) != -1) {} for C
// do something
}
I usually detect end of cpp stream below:
while (cin.peek() != EOF) {
// To do your stuff...
// NOTE: peek() will set failbit when peeking end of stream and return EOF(-1).
}
I am reading a std::istream and I need to verify without extracting characters that:
The stream is not "empty", i.e. that trying to read a char will not result in an fail state (solved by using peek() member function and checking fail state, then setting back to original state)
That among the characters left there is at least one which is not a space, a tab or a newline char.
The reason for this is, is that I am reading text files containing say one int per line, and sometimes there may be extra spaces / new-lines at the end of the file and this causes issues when I try get back the data from the file to a vector of int.
A peek(int n) would probably do what I need but I am stuck with its implementation.
I know I could just read istream like:
while (myInt << myIstream) {…} //Will fail when I am at the end
but the same check would fail for a number of different conditions (say I have something which is not an int on some line) and being able to differentiate between the two reading errors (unexpected thing, nothing left) would help me to write more robust code, as I could write:
while (something_left(myIstream)) {
myInt << myIstream;
if (myStream.fail()) {…} //Horrible things happened
}
Thank you!
There is a function called ws which eats whitespace. Perhaps you could call that after each read. If that hits eof, then you know you've got a normal termination. If it doesn't and the next read doesn't produce a valid int, then you know you've got garbage in your file. Maybe something like:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream infile("test.dat");
while (infile)
{
int i;
infile >> i;
if (!infile.fail())
std::cout << i << '\n';
else
std::cout << "garbage\n";
ws(infile);
}
}
this is what I did to skip whitespace/detect EOF before the actual input:
char c;
if (!(cin >> c)) //skip whitespace
return false; // EOF or other error
cin.unget();
This is independent of what data you are going to read.
This code relies on the skipws manipulator being set by default for standard streams, but it can be set manually cin >> skipw >> c;
And simple
for(;;){
if(!(myIstream >> myInt)){
if(myIstream.eof()) {
//end of file
}else{
//not an integer
}
}
// Do something with myInt
}
does not work? Why you need to know if there are numbers left?
Edit Changed to Ben's proposition.
The usual way to handle this situation is not to avoid reading from the stream, but to put back characters, which have been read, if needed:
int get_int(std::istream& in)
{
int n = 0;
while(true) {
if (in >> n)
return n;
clean_input(in);
}
}
void clean_input(std::istream& in)
{
if (in.fail()) {
in.clear();
// throw away (skip) pending characters in input
// which are non-digits
char ch;
while (in >> ch) {
if (isdigit(ch)) {
// stuff digit back into the stream
in.unget();
return;
}
}
}
error("No input"); // eof or bad
}