overloading operator >>() - c++

My knowledge of C++ is small as I have only taken a couple classes. I undersand the basic case of using a friend function to overload the input, output stream operator for the "simple book example" of a Point object that has x, y instance variables. I am looking at a real project now, trying to understand what someone wrote and am getting the error:
error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
1> c:\program files\microsoft visual studio 9.0\vc\include\istream(1000): could be 'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
Noob question (1), can someone explain what basic_istream is? The error points to:
template<class _Traits> inline
basic_istream<char, _Traits>& __CLRCALL_OR_CDECL operator>>(
basic_istream<char, _Traits>& _Istr, signed char *_Str)
{ // extract a signed char NTBS
return (_Istr >> (char *)_Str);
}
The other part the error points to is:
void input(std::istream &in = std::cin)
{in >> "(" >> X >> "," >> Y >> "," >> Z >> ")" ; }
inline friend std::istream& operator >> (std::istream& in, Coord &val)
{val.input(in); return in; };
Not sure what the error is looking at with my limited knowledge. It seems to be complaining about not the right type in the inline friend std::istream& operator>> function because of something wrong in the basic_istream template (which I'm not sure what is happening there). Any advice would be greatly appreciated. Thanks!

I'm pretty sure you can't parametrize istream extraction like that. It would be cool to be proven wrong though :)
Try this:
void input(std::istream &in = std::cin)
{
char t;
in >> t >> X >> t >> Y >> t >> Z >> t;
}

You can't use a string as an input in that way. You will need to use something like
char c;
cin.get() >> c;
if (c != '(') throw SomeError;
cin >> X;
cin.get() >> c;
if (c != ',') throw SomeError;
cin >> Y;
and so on.

First off, since you are new to C++: Do not trust the compiler error messages too much. In complicated code (templates, overloading...) you frequently get messages that are unrelated to the real issue.
Incorporating the comment on my answer: In your case though, the "," and similar objects are const, and the operator for the X, Y, Z is only declared on non-const objects, therefore not applicable. You'd either have to duplicate it, or only write a const version.

basic_istream is the real class behind istream -- the definitions look something like:
namespace std {
typedef basic_istream<char> istream;
typedef basic_ostream<char> istream;
typedef basic_istream<wchar_t> wistream;
typedef basic_ostream<wchar_t> wostream;
}
As to why you're getting the error message in the first place, the problem is pretty clearly with parts like:
some_istream >> "(";
You seem to want to read a character, and have it match that against an opening parenthesis, and (probably) fail if that's not what it finds. For better or worse, however, istreams don't really support that directly. To do it, you could do something like this:
char ch;
some_istream >> ch;
if (ch != '(')
// handle failure
Alternatively, you could just read a character, and assume it's what should be there without checking. This can also allow somewhat more flexible input formatting, so "1 2 3" would be accepted just as well as "(1, 2, 3)". For some cases (e.g., input entered directly by a person) that can be fairly helpful. In other cases (e.g., input from another program) any deviation in the input signals a problem.

The problem is this:
in >> "("
Conceptually, this makes no sense. You're trying to read input into a string literal. (That's like trying to read input into the constant 5.) The error is because a string literal is a const array of characters (hence the const char[2] type) and so cannot be read into.
You might want this:
void input(std::istream &in = std::cin)
{
char dummy = 0;
in >> dummy >> X >> dummy >> Y >> dummy >> Z >> dummy;
}
All this does is read those characters into a dummy variable. It works, but those characters could be anything.
Rather, you should probably do the following:
// if you do it more than once, make it a function
bool expect_char(std::istream& in, char expected)
{
char check = 0;
in >> check;
if (check != expected)
{
in.putback(); // replace it
in.clear(std::ios::failbit); // set fail bit
return false;
}
else
{
return true;
}
}
void input(std::istream &in = std::cin)
{
if (!in) // if stream is bad, just return
return;
if (!expect_char(in, '('))
return;
in >> X;
if (!expect_char(in, ','))
return;
in >> Y;
if (!expect_char(in, ','))
return;
in >> Z;
if (!expect_char(in, ')'))
return;
}
Now the only problem is that if extraction fails half-way, we have modified the point object. Ideally, it would be all or nothing. We store intermediate values, then copy them when it all works:
void input(std::istream &in = std::cin)
{
if (!in)
return;
if (!expect_char(in, '('))
return;
int newX; // or whatever type it is
in >> newX;
if (!expect_char(in, ','))
return;
int newY;
in >> newY;
if (!expect_char(in, ','))
return;
int newZ;
in >> newZ;
if (!expect_char(in, ')'))
return;
X = newX;
Y = newY;
Z = newZ;
}
And we get what we were after.

Related

Questions related to reading in different format of numbers characters

How I can read in those elements and store them into two different arrays., i.e. : the number in <?> and the word in [?] to be separately read in and stored.
<98>
Avs [adadada]
<45>
[adafaf] BBBHADA
asdadqd aada [Mammoth]
<-1> // ends the read
The rest of the info in the file is useless which do not require to be stored.
Edit:
Following the advice of one of the answers, here is my first attempt:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string.h>
using namespace std;
int main(int argc, char* argv[])
{
if(argc != 3)
cout<< "Error! Not enough file!"<<endl;
int** page = new int*[];
char** words = new char*[];
}
//---------------------------------------------------------
void readInput(int** page1, char** name1){
istream is;
char par1, par2;
int usefulVal;
is >> par1 >> usefulVal >> par2;
// check if any input
if(!is) return is;
// check for valid input format
if (par1 != '<' || par2 != '>'){
// set failbit to indicate invalid input format
is.clear(ios_base::failbit);
// assign input values to second argument
page1(usefulVal);
char par_1, par_2;
string string_value;
is >> par1 >> string_value >> par2;
if(!is) return is;
if (par_1 != '[' || par_2 != ']')
{
is.clear(ios_base::failbit);
return is;
}
name1(string_value);
return is;
}
Question:
1. Is there a way to read and store the above elements separately?
2. What am I doing wrong?
P.S.: I'm just trying out some C++. Hope someone can shed some light on it, thanks!
To specify your format and read only specific elements you could overload the operator >>. For example, the first format: < int_value >, could be implemented with:
istream& operator>>(istream& is, class_name& array_name){
char par2, par2;
int int_value;
is >> par1 >> int_value >> par2;
// check if any input
if(!is) return is;
// check for valid input format
if (par1 != '<' || par2 != '>'){
// set failbit to indicate invalid input format
is.clear(ios_base::failbit);
return is;
}
// assign input values to second argument
array_name(int_value);
// chain for consecutive use
return is;
}
and the second format: [ string_value ] with:
istream& operator>>(istream& is, class_name& separate_array_name){
char par2, par2;
string string_value;
is >> par1 >> int_value >> par2;
if(!is) return is;
if (par1 != '[' || par2 != ']'){
is.clear(ios_base::failbit);
return is;
}
separate_array_name(string_value);
return is;
}
Note:
The second parameter in both examples: class_name& array_name and class_name& separate_array_name are not real types and are left for you to decide/ implement.
Edit:
The function you've defined is not used in your main().
The function needs to be either defined before the main() or forward declared.
Limit the excessive use of pointers and dynamically allocated memory, as it needs to be taken care of (freed) at the end.
Look up how to use istream: file name, modes, etc.
Prefer simple functions, i.e. doing one single process. It is much more easier to implement and detect errors.

'==' operator not found

So apparently this prgoram is not working. Software tells me that the '==' operator is missing. Could some tell me what to do about this and explain why his/her solution works?
#include <iostream>
using namespace std;
int main() {
int var{ 0 };
cout << "Bitte eine Ganzzahl eingeben: ";
if ((cin >> var) == false) {
cerr << "Falsche Eingabe - Keine Zahl\n";
exit(1);
}
system("pause");
//return 0;
}
And while we're at it. Why is it possible to execute 'cin' in the if statemant? I would have used 'cin' before the if statemant.
In modern C++, the status of a stream can be tested using an explicit operator bool. This means that it can be used directly as the condition in an if statement, but can't be implicitly converted to bool to compare with false. So you'd need the more idiomatic
if (cin >> var)
to test the status.
Why is it possible to execute 'cin' in the if statemant?
Because the condition can be any expression, as long as it has a result that can be converted to bool. The >> operator returns a reference to the stream, which can be converted via the operator I described above.
First cin is not something that you execute, like the print command of some other languages. It is an object of class istream that represents the standard input stream of chars.
The operator >> extracts formatted input from such streams. Its prototype is something like
istream& operator>> (int& val);
meaning it returns a reference to the istream itself, so you can chain operations like
cin >> foo >> bar;
so you can't compare the result of cin >> foo, which is a reference, to the constant false.
On the other hand, the operator "!" is overloaded and means the same thing as fail, so you can check that an operation succeeds like this
if ( ! (cin >> var) ) {
cerr << "something is going wrong" << endl;
}
std::istream has conversion operator to bool, but it has to be explicit (http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool):
explicit operator bool() const;
You can use an explicit conversion operator:
if ( (bool)(cin >> var) == false) {
cerr << "Falsche Eingabe - Keine Zahl\n";
}
or simply use:
if ( !(cin >> var) ) {
cerr << "Falsche Eingabe - Keine Zahl\n";
}

Read at once inputs string and integer separated by a space in c++

I was wondering if, like in C, in C++ there was a way to take at once two different type of varibales as inputs.
For example I am supposed to read a command (a string) followed by an index(an integer) from a user, and they separated by a space.
The >> operator for a std::istream is overloaded for many different types. Any class which inherits >> from std::istream can read inputs from all the types >> is overloaded for. This means you can use the >> operator with std::cin, std::ifstream, std::istringstream, etc. to read in multiple types.
The basic syntax for your case would have the form
std::string s;
int n;
std::cin >> s >> n; // or std::ifstream, etc.
Of course you should perform error checking to make sure you actually received what you expected. You can use the ! operator to check if the stream is (not) in a good state. So in your case you might use the following:
std::string s;
int n;
if (!std::cin) {
// error handling here
} else {
std::cin >> s; // get the std::string
}
if (!std::cin) {
// error handling here
} else {
std::cin >> n; // get the int
}

fstream with a string delimiter or two char

I have this situation where I need to get two int values from each row inside a file with this format:
43=>113
344=>22
Is it possible to do someting like setting a delimiter equal to => and than use >> operator to assign ints?
ifstream iFile("input.in");
int a,b;
iFile >> a >> b;
Also can be done autoamtically to output with similar format?
oFile << a << b;
instead of
oFile << a << "=>" << b;
Thanks.
You can't do it directly, without any extra code when reading or
writing, but you can write a manipulator which handles it for
you more explicitly:
std::istream&
mysep( std::istream& source )
{
source >> std::ws; // Skip whitespace.
if ( source.get() != '=' || source.get() != '>' ) {
// We didn't find the separator, so it's an error
source.setstate( std::ios_base::failbit );
}
return source;
}
Then, if you write:
ifile >> a >> mysep >> b;
, you will get an error is the separator is absent.
On output, you can use a similar manipulator:
std::ostream&
mysep( std::ostream& dest )
{
dest << "=>";
return dest;
}
This has the advantage of keeping the information as to what the
separator is isolated in these two specific functions (which
would be defined next to one another, in the same source file),
rather than spread out where ever you are reading or writing.
Also, these data presumably represent some particular type of
information in your code. If so, you should probably define it
as a class, and then defined operators >> and << over that
class.
Given a and b are variables of inbuilt types, you can not define your own user-defined operators for streaming them (the Standard library already provides such functions).
You could just write out code with the behaviour you want...
int a, b;
char eq, gt;
// this is probably good enough, though it would accept e.g. "29 = > 37" too.
// disable whitespace skipping with <iomanip>'s std::noskipws if you care....
if (iFile >> a >> eq >> gt >> b && eq == '=' && gt == '>')
...
OR wrap a and b into a class or struct, and provider user-defined operators for that. There are plenty of SO questions with answers explaining how to write such streaming functions.
OR write a support function...
#include <iomanip>
std::istream& skip_eq_gt(std::istream& is)
{
char eq, gt;
// save current state of skipws...
bool skipping = is.flags() & std::ios_base::skipws;
// putting noskipws between eq and gt means whatever the skipws state
// has been will still be honoured while seeking the first character - 'eq'
is >> eq >> std::noskipws >> gt;
// restore the earlier skipws setting...
if (skipping)
is.flags(is.flags() | std::ios_base::skipws);
// earlier ">>" operations may have set fail and/or eof, but check extra reasons to do so
if (eq != '=' || gt != '>')
is.setstate(std::ios_base::failbit)
return is;
}
...then use it like this...
if (std::cin >> a >> skip_eq_gt >> b)
...use a and b...
This function "works" because streams are designed to accept "io manipulator" functions that reconfigure some aspect of the stream (for example, std::noskipws), but for a function to be called it just has to match the prototype for an (input) io manipulator: std::istream& (std::istream&).
If you have always have => as the deliminator, you can write a function that will parse lines of the document.
void Parse(ifstream& i)
{
string l;
while(getline(i,l))
{
//First part
string first = l.substr(0, l.find("=>"));
//Second part
string second = l.substr(l.find("=>")+2, l.length());
//Do whatever you want to do with them.
}
}

error: no match for 'operator>>' in 'std::cin >> stopat'

I'm trying to get back into C++, and this is my second program in a long while. Everything compiles just peachy, until it gets to cin >> stopat; where it returns what seems to be a fairly common error: error: no match for 'operator>>' in 'std::cin >> stopat'
I've looked through a few things explaining what causes this, but nothing I actually understand (due to my relative inexperience in programming). What causes this error, and how do I fix it in case I come across it again?
#include <iostream>
#include "BigInteger.hh"
using namespace std;
int main()
{
BigInteger A = 0;
BigInteger B = 1;
BigInteger C = 1;
BigInteger D = 1;
BigInteger stop = 1;
cout << "How Many steps? ";
BigInteger stopat = 0;
while (stop != stopat)
{
if (stopat == 0)
{
cin >> stopat;
cout << endl << "1" << endl;
}
D = C;
C = A + B;
cout << C << endl;
A = C;
B = D;
stop = stop + 1;
}
cin.get();
}
EDIT: Somehow, I didn't think to link the libraries referenced. Here they are: https://mattmccutchen.net/bigint/
You haven't shown us the code for BigInteger, but there would need to be a function defined (either in BigInteger.hh or in your own code) like this:
std::istream& operator >>(std::istream&, BigInteger&);
This function would need to be implemented to actually get a "word" from a stream and try to convert it to a BigInteger. If you're lucky, BigInteger will have a constructor that takes a string, in which case it would be like this:
std::istream& operator >>(std::istream& stream, BigInteger& value)
{
std::string word;
if (stream >> word)
value = BigInteger(word);
}
Edit: Now that you have pointed out the library that's being used, here's what you can do. The library itself should probably do this for you, since it provides the corresponding ostream operator, but if you look into that you will see that general-purpose, library-quality stream operators are more complex than what I'm writing here.
#include <BigIntegerUtils.hh>
std::istream& operator >>(std::istream& stream, BigInteger& value)
{
std::string word;
if (stream >> word)
value = stringToBigInteger(word);
}
What you've left out here is details about your BigInteger class. In order to read one from an input stream with the >> operator, you need to define operator>> (often called a stream extractor) for your class. That's what the compiler error you're getting means.
Essentially, what you need is a function that looks like this:
std::istream &operator>>(std::istream &is, BigInteger &bigint)
{
// parse your bigint representation there
return is;
}