.eof() substitute while using arrays - c++

So recently I've learned that using .eof can be considered a kind of big no no and I want to start moving away from it. One of the main substitutions I have seen is using
while(inFile >> num)
{
}
However, when I do this using arrays it only stores the first input and nothing else. Any tips?
Example:
while(inMovie >> title[x])
{
inMovie >> income[x];
x++;
}

What you really want to be doing is:
while ((inMovie >> title[x]) && (inMovie >> income[x]))
{
x++;
}
Or, more succinctly:
while (inMovie >> title[x] >> income[x])
{
x++;
}
This way, both input operations have to "succeed" in order for you to continue.
That being said, there is nothing inherently broken with your attempt, and there is no reason for it to "only store the first input" as long as the input is correct.
Check your input.
I'm also concerned that you may not be using arrays properly. Does your array have enough space for all these elements? Or are you expecting title and income to expand automatically? Because they won't do that. In that case, your program has undefined behaviour (which may produce all sorts of weird results!) and you should consider using a vector instead.

Related

using input redirection in while loop

I need to create a program that reads in a list of random integers via input redirection and performs various tasks with them. For the purpose of this question I just want to print the sum of each number + 1. Trouble is, I don’t know how to get it to perform the operation on anything but the first number in the list. My mini program (program.cpp) is
#include <iostream>
using namespace std;
int main () {
int input;
bool arb = true;
cin >> input;
while (arb) {
cout << input + 1 << endl;
}
return 0;
}
and a sample textfile (textfile.txt) I'm using contains
9
8
7
6
When I run it it prints out “10” for infinity. What I’d like it do is print out
10
9
8
7
or the equivalent for whatever other text file may be used.
I thought maybe I could somehow reference specific lines in the textfile, but from searching how to do that all the similar questions I could find seemed to have solutions that required fstream, which is something I haven’t learned yet and therefore I’m not allowed to use it (this is for a class assignment).
The only compiler directives I’ve learned are iostream, string, cmath, iomanip, cstdlib, and ctime. The ways to get input I’ve learned are cin >> input, cin.get(input), and cin.getline(input), so if there are other ways of reading in the file besides those 3 that I’m unaware of, unfortunately I can’t use it. Note that my program HAS to use a while loop. The way the program will be run is
./program < whatevertextfile.txt
which I can't change.
given these restrictions, how can I get my program to read in and use each integer in the text file?
The idiomatic way to read a sequence of white-space separated integers in C++ would be
#include <iostream>
using namespace std;
int main () {
int input;
while (cin >> input) {
cout << input + 1 << endl;
}
return 0;
}
Let's come to why this works the way it does.
cin >> input
discards possible white-space and then reads an integer from the standard input. Moreover, it returns a reference of the cin object used. With this returned reference, you can call the bool conversion operator to check if any of the fail bits is set in the given std::basic_ios object. So
while (cin >> input)
does two things. Read an integer from standard input and check if it successfully completed the operation. As long as this operation succeeds, your while loop continues to iterate and you print the numbers.
See http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt for reference on std::basic_istream::operator>>.
See http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool for reference on operator bool.
Edit1: Move references to bottom so that the answer is more readable.

C++: cin.peek(), cin >> char, cin.get(char)

I've got this code with use of cin.peek() method. I noticed strange behaviour, when input to program looks like qwertyu$[Enter] everything works fine, but when it looks like qwerty[Enter]$ it works only when I type double dollar sign qwerty[Enter]$$. On the other hand when I use cin.get(char) everything works also fine.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char ch;
int count = 0;
while ( cin.peek() != '$' )
{
cin >> ch; //cin.get(ch);
count++;
}
cout << count << " liter(a/y)\n";
system("pause");
return 0;
}
//Input:
// qwerty$<Enter> It's ok
//////////////////////////
//qwerty<Enter>
//$ Doesn't work
/////////////////////////////
//qwerty<Enter>
//$$ works(?)
It's because your program won't get input from the console until the user presses the ENTER key (and then it won't see anything typed on the next line until ENTER is pressed again, and so on). This is normal behavior, there's nothing you can do about it. If you want more control, create a UI.
Honestly I don't think the currently accepted answer is that good.
Hmm looking at it again I think since, operator<< is a formatted input command, and get() a plain binary, the formatted version could be waiting for more input than one character to do some formatting magic.
I presume it is way more complicated than get() if you look what it can do. I think >> will hang until it is absolutely sure it read a char according to all the flags set, and then will return. Hence it can wait for more input than just one character. For example you can specify skipws.
It clearly would need to peek into more than once character of input to get a char from \t\t\t test.
I think get() is unaffected by such flags and will just extract a character from a string, that is why it is easier for get() to behave in non-blocking fashion.
The reason why consider the currently accepted answer wrong is because it states that the program will not get any input until [enter] or some other flush-like thing. In my opinion this is obviously not the case since get() version works. Why would it, if it did not get the input?
It probably still can block due to buffering, but I think it far less likely, and it is not the case in your example.

C++: std::istream check for EOF without reading / consuming tokens / using operator>>

I would like to test if a std::istream has reached the end without reading from it.
I know that I can check for EOF like this:
if (is >> something)
but this has a series of problems. Imagine there are many, possibly virtual, methods/functions which expect std::istream& passed as an argument.
This would mean I have to do the "housework" of checking for EOF in each of them, possibly with different type of something variable, or create some weird wrapper which would handle the scenario of calling the input methods.
All I need to do is:
if (!IsEof(is)) Input(is);
the method IsEof should guarantee that the stream is not changed for reading, so that the above line is equivalent to:
Input(is)
as regards the data read in the Input method.
If there is no generic solution which would word for and std::istream, is there any way to do this for std::ifstream or cin?
EDIT:
In other words, the following assert should always pass:
while (!IsEof(is)) {
int something;
assert(is >> something);
}
The istream class has an eof bit that can be checked by using the is.eof() member.
Edit: So you want to see if the next character is the EOF marker without removing it from the stream? if (is.peek() == EOF) is probably what you want then. See the documentation for istream::peek
That's impossible. How is the IsEof function supposed to know that the next item you intend to read is an int?
Should the following also not trigger any asserts?
while(!IsEof(in))
{
int x;
double y;
if( rand() % 2 == 0 )
{
assert(in >> x);
} else {
assert(in >> y);
}
}
That said, you can use the exceptions method to keep the "house-keeping' in one place.
Instead of
if(IsEof(is)) Input(is)
try
is.exceptions( ifstream::eofbit /* | ifstream::failbit etc. if you like */ )
try {
Input(is);
} catch(const ifstream::failure& ) {
}
It doesn't stop you from reading before it's "too late", but it does obviate the need to have if(is >> x) if(is >> y) etc. in all the functions.
Normally,
if (std::is)
{
}
is enough. There is also .good(), .bad(), .fail() for more exact information
Here is a reference link: http://www.cplusplus.com/reference/iostream/istream/
There are good reasons for which there is no isEof function: it is hard to specify in an usable way. For instance, operator>> usually begin by skipping white spaces (depending on a flag) while some other input functions are able to read space. How would you isEof() handle the situation? Begin by skipping spaces or not? Would it depend on the flag used by operator>> or not? Would it restore the white spaces in the stream or not?
My advice is use the standard idiom and characterize input failure instead of trying to predict only one cause of them: you'd still need to characterize and handle the others.
No, in the general case there is no way of knowing if the next read operation will reach eof.
If the stream is connected to a keyboard, the EOF condition is that I will type Ctrl+Z/Ctrl+D at the next prompt. How would IsEof(is) detect that?

c++ isalnum endless loop

Greetings!
Lets cut the excessive intro this time and get straight to the point.
I have a problem in C++ using the isalnum method.
the code:
int playAgainst = 0;
do
{
cout << "Who do you want to play against?(1/2)\n";
cout << "1: Human player\n";
cout << "2: Computer player\n";
cin >> playAgainst
} while(!isalnum(playAgainst) && playAgainst != 0);
As seen in the code, I'm providing the user with a choice. Play against human or play against a computer.
What I want is, as long as the user enters anything else then an integer value(cin >> playAgainst) to repeat the question. However, If i enter a char, or string value, it keeps looping endlessly. I am not 100% sure, but it would be obvious, if the problem is, that the non int value is already saved as the value for playAgainst.. How can I check in this bit of code if the input value is int before saving it?
Or is the only possibility to save as a char/string and then check?
If the latter is the case, a new problem arises. isalnum only accepts int as parameter, atleast from what I know. How will I check if that string or char is an int?
Thank you for taking the time to read. And hopefully Ill be accepting a reply as answer soon ^^
Thanks everyone for the answers.
I have gotten what I wanted, and everything has been solved.
The reason I chose for the accepted answer, is well... because initially, it made my code work the way I want it to. I want to accept multiple answers though..
Make playAgainst a char and compare against '0', not 0. Right now, the user has to enter the ASCII (or whatever your character set is) code for the character '1' or '2'.
isalnum won't work on ints outside the valid range of char, except for EOF. (The fact that it takes an int argument is a leftover from C, which has different integer promotions rules than C++. to accomodate for EOF.)
Remove the isalnum() check. cin >> playAgainst will convert anything except a number to zero, which will be caught by the second check. Note that this is only an option because zero is not a valid input.
isalnum() is useful if you're interpreting the characters yourself, but in this case the stream has already done that for you.
This is how the compiler will implement isalnum:
int isalnum (int ch)
{
return (ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9');
}
So you might as well write that code snippet in your own code, and it will be equivalent with an inlined version of isalnum.
It's because you don't clear the buffer. When the input is invalid, you need to clear it from the buffer, and then you can move on to the next input, else you're trying to extract the same input every time (which fails, because it's the same bad input), and thus enter an infinite loop.
The problem is that you're inputing an int, and not a char. And if the
text in the input isn't an int, then the input fails. In which case,
playAgainst isn't modified, and the failure is memorized in std::cin
until you explicitly clear the error. And inputting from a stream in an
error state is a no-op. What you probably want to do is
Input a single character: if you don't want to skip spaces, using
`std::cin.get( ch )` or `ch = std::cin.get()`. (In the latter
case, `ch` should be an `int`, since it must also handle `EOF`.
On the other hand, you can use `::isalnum` on it directly, which
you can't do if `ch` is a `char`.
Fully check for valid input: not just `::isalnum`, but rather
whether the input is a legal selector in your list. Something
along the lines of:
ch != EOF && std::find( legalChars.begin(), legalChars.end(), (char)ch ) != legalChars.end()
In case of error, clear any remaining input, say with:
std::cin.ignore(INT_MAX, '\n');
In practice, you'll probably want to treat EOF differently from
an erroneous command. (If you don't clear the input after EOF, you
won't be able to read anything else. But presumably, if you got EOF,
it's because the user gave up, and doesn't want to try any more.)
Finally, it's probably preferrable to keep all of the information in
a common location, using a table of:
struct Command
{
char op;
char const* prompt;
void (* func)();
};
You then loop over a table of these to output the prompt, search it to
see if the character was legal, and finally, call the function on the
entry you found. Or define an abstract base class, a concrete class
deriving from it for each command, and use an std::map<char,
AbstractBase*> for the mapping, etc. Very C++, but perhaps a bit
overkill for such a simple case.
Why not use isdigit().

Why does this C++ char array seem to be able to hold more than its size?

#include <iostream>
using namespace std;
typedef struct
{
char streetName[5];
} RECORD;
int main()
{
RECORD r;
cin >> r.streetName;
cout << r.streetName << endl;
}
When I run this program, if I enter in more than 5 characters, the output will show the whole string I entered. It does not truncate at 5 characters. Why is that?
How can I get this to work correctly?
You are overflowing the buffer. Put another char array after streetName and you will likely find that it gets the rest of the characters. Right now you are just corrupting some memory on your stack.
In order to limit the input to the size of the receiving array you need to use the length-limiting facilities provided by your input method. In your case you are using cin, which means that you can specify the limit by using its width method
cin.width(5);
cin >> r.streetName;
Because cin sees streetName as a char * and writes to memory and there is nothing to stop writing to *(streetName + 6) and further. This is a form of buffer overrun
The best code in this case is define streetName as a std::string
i.e.
typedef struct
{
std::string streetName;
} RECORD;
Because you're overruning the end of your buffer and in this particular case you're getting away with it. C and C++ make it very easy to "shoot yourself in the foot", but that doesn't mean that you should.
It's a buffer overrun.
C++ does not perform bounds checking on array accesses, and memory does not simply stop at the end of the array. You are writing data to memory that is not part of the array, the consequences of which are non-deterministic, and may sometimes even appear to work.
It is quite likely that if you placed that code into a function, the program would crash when you tried to return from the function, because one likely possibility is that you will have dumped on the function return address on the stack. You may also have corrupted data belonging to the calling function.
The way to do this correctly in c++ is to use a std::string.
#include<iostream>
#include<string>
....
std::string r;
getline(cin, r);
std::cout << r <<std::endl;
For truncated input(with suitably defined and inited values).
while(cin.peek() != EOF && i < len)
{
cin >> arr[i];
++i;
}
You will want to do something after this to flush the buffer and not leave the rest of the line sitting on the input stream if you plan on doing other things with it.