Reading file until blank line - c++

After reading Jerry Coffin's answer on this question I copy-pasted his code into my editor, and after some minor edits it compiled and run like it should.
Here is the code after the changes:
#include <iostream>
#include <string>
#include <istream>
#include <fstream>
class non_blank {
private:
std::string data_;
friend std::istream& operator>> (std::istream &is, non_blank &n) {
std::getline(is, n.data_);
if (n.data_.length() == 0) {
is.setstate(std::ios::failbit);
}
return is;
}
public:
operator std::string() const {
return data_;
}
};
int main(int, char *[]) {
non_blank line;
std::ifstream ifs("teste.txt");
while(ifs >> line) {
//std::cout << line; <----- error
std::string s = line;
std::cout << s << std::endl;
}
return 0;
}
I've got an error when trying to use a non_blank variable in a std::cout <<... expression. Shouldn't I be able to use a variable of the type non_blank anywhere I would use a std::string? Isn't it the purpose of the cast/conversion operator?? answer
Why can't I access the private variable string::data_ directly in the definition of the operator >>?
Here is the error I got:
..\main.cpp: In function `std::istream& operator>>(std::istream&, non_blank&)':
..\main.cpp:21: error: invalid use of non-static data member `non_blank::data_'
..\main.cpp:26: error: from this location

Shouldn't I be able to use a variable
of the type non_blank anywhere I would
use a std::string? Isn't it the
porpuse of the cast operator?
Not quite. If the compiler sees you doing something that it knows requires a std::string, it can call your conversion operator to get one. But in the case of the ostream operator <<, it doesn't have a single specific function to call, but rather quite a lot of them, all different and none matching precisely the actual type you mean to print. So it lists a whole bunch of candidates, none of which is a strong enough match. You need to define an ostream operator << for your type in order to make it print as it should.
As for your operator >>, you should make it not be a member of your class. Declare it as a friend within the class declaration if you must, but write the function itself outside.

Related

How to pass other variables as args along with std::ostream in a function in C++?

I was working on a function which looks like so:
inline std::ostream& mvUp(int n,std::ostream& ss){
char u[8];
sprintf(u,"\033[%dA",n);
ss<<u;
return ss;
}
and using it like so:
std::cout<<mvUp(1);
however it shows error:
std::cout<<mvUp(1);
| ^_____too few args in function call
^_______________no operator "<<" match these operands
I also tried: std::cout<<mvUp(1,std::cout); but still not working.
std::cout<<mvUp(1);
^_______________no operator "<<" match these operands
now when I try making it template,
template <int n>
inline std::ostream& mvUp(std::ostream& ss){
char u[8];
sprintf(u,"\033[%dA",n);
ss<<u;
return ss;
}
and use it: std::cout<<mvUp<1>, this works totally fine but the problem with this is that templates take const args.
Not able to figure out where am I getting wrong. Also how is it working in templates when I am not passing any args?
Modern C++ code uses std::string, and other classes. This makes implementing this kind of an overload trivial.
#include <string>
#include <sstream>
inline std::string mvUp(int n) {
std::ostringstream o;
o << "\033[" << n << "A";
return o.str();
}
Then, everything will work automatically:
std::cout<<mvUp(1);
Your mvUp returns std::string, and the existing << overload takes care of the rest.
The fact that std::ostream& mvUp(std::ostream& ss); std::cout << mvUp<1> works is not a peculiarity of C++ function call syntax.
std::cout has its operator<< overloaded to accept single-parameter functions like this one, and call them by passing itself as the first argument.
Given std::ostream& mvUp(int n,std::ostream& ss);, std::cout<<mvUp(1) doesn't work because your function doesn't have one parameter. And std::cout << mvUp(1,std::cout); doesn't work because your function returns std::ostream&, which can't be printed.
The generic solution is to make a class with overloaded operator<<. But, as the other answer suggests, here you can just make a function that returns std::string, and print its return value.
You are trying to create a custom ostream manipulator, similar to std::setw() and other manipulators from the <iomanip> library. But what you have written is not the correct way to implement that. Your manipulator needs to return a type that holds the information you want to manipulate the stream with, and then you need to overload operator<< to stream out that type. That will give you access to the ostream which you can then manipulate as needed.
Try something more like this:
struct mvUpS
{
int n;
};
mvUpS mvUp(int n) {
return mvUpS{n};
}
std::ostream& operator<<(std::ostream& ss, const mvUpS &s) {
return ss << "\033[" << s.n << "A";
}
Now std::cout << mvUp(1); will work as expected.
Demo

Operator overloading the stream extraction operator (>>) in C++ results in infinite recursive stream extraction

I'm still learning my way around C++ (I am a high school student) and for a competition I need to read in comma separated values, and I thought it would be a neat opportunity to learn how to overload the stream extraction (>>) operator to get rid of any delimiters that may come after a value. (This is the best way I could think of, if there are any better, please share!) However, as the title says, the stream extraction operation recurses infinitely, causing the program to crash. I have no idea how to fix this and I tried searching online for a solution for hours. Here is the code:
#include <iostream>
#include <fstream>
using namespace std; // Sorry if this annoys some people
// Create a class the inherits from ifstream for file opening and stream extraction and stuff. (cStream stands for Custom Stream)
class cStream : public ifstream
{
private:
string Delimiters;
public:
cStream() : ifstream() {}
cStream(const char* filename, const char* _Delimiters = "\n\t\0") : ifstream(filename), Delimiters(_Delimiters) {}
// Define friend functions so that the stream extractor can access the private variable Delimiters. (might not be needed but eh)
template <class t> friend cStream& operator >> (cStream&, t&); // Problem function.
};
cStream& operator >> (cStream in, const char* delimOverride)
{
in.Delimiters = delimOverride;
return(in);
}
// Operator overloaded stream extractor that gets rid of any characters in cStream.Delimiters.
// The variable names are weird but I didn't know what to name them.
template <class t> cStream& operator >> (cStream& in, t& out)
{
in >> out; // What the heck do I do here?
// The cStream stream extraction operator gets called recursively because it takes a cStream and returns a cStream,
// but how do I fix that...?
// Get rid of any trailing delimiters and spaces
while ((in.Delimiters + " ").find(in.peek()) != -1) in.ignore();
//Return with new input stream
return(in);
}
I don't know if this is bad code or not, as I said, I'm still learning about C++. If it is bad code, please help me improve it. Thank you! <3
I'm also a noob to Stack Overflow so if I did anything wrong, please tell!
in >> out; // What the heck do I do here?
That line of code is translated as operator>>(in, out), which leads to infinite recursion.
I am guessing you want to read to out using the base class functionality. For that, you need to explicity create a reference to the base class and use that reference.
std::ifstream& in_f = in;
in_f >> out;
You may also use a one-liner.
static_cast<std::ifstream&>(in) >> out;

Why does fstream not utilize the istream prototype of operator>>?

I have a class that uses a friend function to overload the operator>>. The overloaded operator method tests well on standard cin use. However, when I try to upgrade the code to use ifstream objects instead of istream objects, the prototype is not recognized as a valid method.
It is my understanding that ifstream is inherited from istream, and as such, polymorphism should allow ifstream objects to operate with the istream overloaded function. What is wrong with my understanding?
Is it necessary to duplicate the function for every input stream type?
Class:
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
class Hospital {
public:
Hospital(std::string name);
std::string getName();
void write();
friend ostream & operator<<( ostream &os, Hospital &hospital );
friend istream & operator>>( istream &is, Hospital &hospital );
private:
void readFromFile( std::string filename );
std::string m_name;
};
function implementation:
istream &operator>>( istream &is, Hospital &hospital ){
getline( is, hospital.m_name );
return is;
}
Error:
Hospital.cpp: In member function ‘void
Hospital::readFromFile(std::string)’: Hospital.cpp:42:24: error: no
match for ‘operator>>’ (operand types are ‘std::ifstream {aka
std::basic_ifstream}’ and ‘Hospital*’)
storedDataFile >> this;
This error occurs in the stack after a call to readFromFile, which I copy here for completeness:
/**
* A loader method that checks to see if a file exists for the given file name.
* If no file exists, it exits without error. If a file exists, it is loaded
* and fills the object with the contained data. WARNING: This method will overwrite
* all pre-existing and preset values, so make changes to the class only after
* invoking this method. Use the write() class method to write the data to a file.
* #param filename
*/
void Hospital::readFromFile(std::string filename) {
ifstream storedDataFile( filename.c_str() );
if( storedDataFile ){
storedDataFile >> this;
storedDataFile.close();
}
}
In this situation, 'this' is a Hospital object.
All help and ideas are appreciated. I am reteaching myself C++ and searching for a deeper understanding of the language and its processes.
You'll have to use :
storedDataFile >> *this;
// ~~ dereference the `this` pointer (i.e. Hostipal Object)
/* Enabling the match for operator>>( istream &is, Hospital &hospital ) */

std::ostream::operator<< not defined for std::string?

I have stumbled upon an error for which I cannot grasp the reason.
I think it basically gets down to this error:
error: no matching function for call to ‘std::basic_ostream<char>::operator<<(const std::basic_string<char>&)’
I looked into specification on www.cplusplus.com and indeed it says there is no definition for std::ostream::operator<< with std::string as an argument.
My question is, what happens when one writes std_ostream_instance << std_fancy_string;. I believe it is one of the most common invocations ( e.g. std::out << std::string("Hello world!") ) next to const char*.
The error originates from these lines:
template<typename T>
void Log::_log(const T& msg)
{ _sink->operator<<( msg ); }
_sink is defied as std::ostream*
There are some wrapping functions around but it breaks here.
I think I could work around by writing
template<>
void Log::_log<std::string>(const std::string& msg) {
_sink->operator<<( msg.c_str() );
}
since there is ostream& operator<< (ostream& out, const unsigned char* s ); defined by default.
I just see no reason why it is not guessed automatically since it clearly works in simple use like cout << any_std_string.
Not sure if this is relevant but I want to be able to pass down through my log functions anything than can be handled by std::ostream. I used explicit non-templated declarations but decided to move to template for log(const T& anything_to_log) to refacator it. It seemed plain stupid to have 5+ overloads. I get the error when I try compiling something like Log::log( std::string("test case") ).
It looks like something stupid-simple but I cannot get it on my own. Tried to google and search stack to no avail.
With regards, luk32.
PS. I checked the work-around and it works. Why it's not implicitly done ?
operator << overloads are not members of ostream. They are freestanding functions, for example
ostream& operator << ( ostream& out, const basic_string<T>& bs );
Try
template<typename T>
void Log::_log(const T& msg)
{ *_sink << msg; }
The std::string version is not a member function, so can't be called as a member of _sink. Try it this way to pick up both member and non-member versions (in fact it is unlikely you will need the member versions at all anyway):
#include <iostream>
#include <string>
int main()
{
std::ostream * os = &std::cout;
std::string s = "Hello\n";
// This will not work
// os->operator<<(s);
(*os) << s;
return 0;
}
Or better yet would be to store _sink as a reference, and output exactly as you normally would to cout.

Custom class ostringstream output error

I don't know why this is erroring, but I'm just trying to add something "akin" to endl so that I can throw what's in an ostringstream to our debugger. I have the following:
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
os.str("");
os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers" << debug_stream_info(__LINE__, __FILE__, LOG_LEVEL);
return 0;
}
The error I'm getting is: error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'debug_stream_info' (or there is no acceptable conversion) for the line in main. This is on VS2008.
I'm including sstream, iostream, etc, and have the namespaces set up right. I'm getting no other errors. I even tried replacing all occurrances of basic_ostream with just ostringstream and there was no difference (I'll be having a w_char version later, but I wanted the simple case to work first). I made the object on the line above and then passed a fully-constructed object on the line, and the error was exactly the same. I've changed the signature of the second argument to and from const with no change as well.
Any ideas on what I'm doing wrong here?
Edit: since EVERY response seems to want to put it there, I can NOT use std::ostream because I want this to work ONLY for std::ostringstream (and std::basic_ostringstream) and not for any type of output stream. Besides, the function wouldn't compile with ostream anyways, since I'm using the os.str() method, which isn't in ostream, only the sub-classes.
The real problem with your code is that you've overloaded std::ostringstream rather than std::ostream. So your code would work if you write this:
debug_stream_info info(/** blah blah**/);
std::ostringstream oss;
oss << info ; //OK
However this will not work:
oss << 1 << info; //ERROR
This is compilation error because the expression oss<<1 returns an object of type std::ostream& which doesn't have overload which takes debug_stream_info as second argument. That means if you use cast as:
static_cast<std::ostringstream&>(oss << 1) << info; //OK
then that should work again.
So the solution is to overload std::ostream, instead of std::basic_ostringstream.
Also, the second parameter should be const & . This is also a problem with your code.
So write this:
std::ostream& operator<<(std::ostream&, debug_stream_info const &);
//^^^^^^^ note this
The second parameter should be const & so that you could write temporary objects to the stream.
debug_stream_info(__LINE__, __FILE__, LOG_LEVEL); is creating unnamed object which is not returning anything hence error
#include <iostream>
#include <cstdio>
#include <sstream>
using namespace std;
class debug_stream_info
{
public:
debug_stream_info(int errorLine, char *errorFile, int level)
:m_errorLine(errorLine), m_errorFile(errorFile), m_logLevel(level)
{
}
friend std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info);
std::ostringstream& fun(std::ostringstream& os)
{
os<<"Ashish"<<endl;
return os;
}
private:
int m_errorLine;
std::string m_errorFile;
int m_logLevel;
};
std::basic_ostringstream<char>& operator<<(std::basic_ostringstream<char>& os, debug_stream_info& debug_info)
{
// Write the stream's contents to cpu_debug
// Deleted custom logging function. No errors here though
// Clear the stream for re-use.
// os.str("");
// os.seekp(0);
return os;
}
int main(int argc, char** argv)
{
std::ostringstream myout, test;
myout << "hey there" << " and some more " << "Numbers!!: " << 435 << 54.2 << " that's good for numbers"
<< debug_stream_info(1, "/home/ashish/test", 1).fun(test);
return 0;
}
Nawaz has explained very clearly why you're getting the error. The
usual solution in this case is to define your own stream type, unrelated
to std::istream. Something along the lines of:
class DebugStream
{
std::ostringstring* collector;
public:
template <typename T>
DebugStream& operator<<( T const& value )
{
if ( collector != NULL ) {
*collector << value;
}
return *this;
}
};
There are infinite variations on this; in your case, you could add a
non-template member function for your type; more likely, you'd add a
constructor which took the same arguments:
DebugStream( int lineNumber, std::string const& filename, int logLevel )
: collector( isActive( logLevel ) ? new std::ostringstream : NULL )
{
// Initial insertion of lineNumber, filename, timestamp...
}
You can also add a destructor which atomically flushes the collected
data to a file (or sends an email, or writes it to the system log, or
whatever). (Be very careful about this. You don't want an exception to
escape from the destructor, even if the logging fails.)
Finally, you might want to use a custom streambuf, rather than
stringstream. Say one that keeps the allocated buffer from one
instance to the next. And if you do this, rather than newing the
stream each time, you might pick up an instance from a table, indexed by
the log level (and initialized from a configuration file).