Part of my cpp code look like this:
void Error()
{
string line;
fperror.open("Error.txt");
while ( getline (fperror,line) )
{
cout << line << endl;
}
fperror.close();
return;
}
Its c counterpart is this:
void Error()
{
int c;
fperror= fopen("Error.txt", "r");
c=getc(fperror);
while(c != EOF)
{
putchar(c);
c=getc(fperror);
}
fclose(fperror);
return;
}
This is my project for my class and our professor told us we weren't allowed to use cout/cin or printf/scanf within the functions. So I was wondering if it is possible to output the contents of the text file without using cout/printf? (We have to use void fun(void)-type of functions)
There are certainly other functions you could call instead, but I suspect you've missed the point. What your instructor probably meant was that your function should not print anything itself. Instead, it should return something that the caller then prints. Part of the purpose of your assignment is probably for you to demonstrate that you understand how the return statement works and how to pass and receive function parameters. In that light, the use of any function to generate output, not just printf and cout, would be an error. Those two were mentioned because those are probably the only things you've been taught in class, and enumerating all other possibilities could confuse and overwhelm students who worry that they're supposed to know what all those other functions are. Consult with your instructor to confirm.
You can use ofstream:
std::ofstream ofs("file.txt");
ofs << "text"; // This line outputs "text" to file
You can display your output using fwrite in C/C++
For Example:
char buffer[] = "hello world"
fwrite (buffer , sizeof(char), sizeof(buffer), stdout);
Related
I have a c++ program that prints to the screen using std::cout.
Sometimes I need to run it as a service. Is there any way of seeing the cout outputs when it's running as a Windows service?
Redirecting the output to a file or some sort of debugging program would be ideal.
Obviously I could replace the cout with a function that writes to a file, and that's probably what I'll do, but I'm curious to know if there are other solutions.
There's basically infinite options. The first few that come to mind:
Pass around an ostream reference
You could pass around an std::ostream reference:
void someFunc(std::ostream& out) {
//someFunc doesn't need to know whether out is a file, cout, or whatever
out << "hello world" << std::endl;
}
Replace cout underlying buffer with a file
Example from cplusplus.com:
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
There's a 1-liner with freopen, but I have a creeping feeling (and this seems to reenforce it in the comments) that it's undefined behavior since stdin and cout can be un-synchronized.
freopen("/path/to/file", "r", stdout);
//cout is now writing to path/to/file
A logging library
Not sure of a good one of the top of my head, but you could go full out and use some type of logging library. (There's also Windows events, though depending on what you're outputting, that might not make sense.)
Piping
I doubt this is possible with a Windows service, but if it is, there's always the classic redirection:
blah.exe > C:\path\file
The easy solution is SetStdHandle(STD_OUTPUT_HANDLE, your_new_handle).
You could do something like this:
class MyTerminal {
std::stringstream terminalText;
}
class MyWindow {
public:
void OnUpdate();
protected:
CTextbox m_textbox;
MyTerminal m_terminal;
}
void MyWindow::OnUpdate()
{
m_textBox.setText(m_terminal.terminalText.str());
m_terminal.terminalText.str(std::string());
}
I use cout statements in my program for debugging purposes. I would like to make a function that works like it, or works like printf, but is sensitive to a global variable. If this global variable is true, then it will print to screen. If it is false, then it won't print anything. Is there already a function like this? If not, then how can it be made?
Something like this:
int myPrintf(const char* format, ...)
{
if (globalCheck == 0)
return 0
va_list vl;
va_start(vl, format);
auto ret = vprintf(format, vl);
va_end(vl);
return ret;
}
va_start and va_end take the arguments in the ... and encapsulate them in a va_list. with this va_list you can then the vprintf which is a variant of printf designed exactly for this need.
Side note - usually it is bad practice to use global variables. A better thing to do is to encapsulate it in a class like this -
class ConditionalPrinter {
public:
ConditionalPrinter() : m_enable(true) {}
void setOut(bool enable) { m_enable = enable; }
int myPrintf(const char* format, ...);
private:
bool m_enable;
}
and then to check m_enable instead of the global variable.
Usage of this looks like this:
ConditionalPrinter p;
p.myPrintf("hello %d", 1); // printed
p.setOut(false);
p.myPrintf("hello2 %d", 1); // not printed
....
Don't write it yourself. Doing it right is much harder then you think. Even harder when you need threads and efficiency. Use one of existing logging libraries like:
glog: http://code.google.com/p/google-glog/ (I prefer this - it is lightweight and do what it needs to do)
Log4cpp http://log4cpp.sourceforge.net/ (powerful and configuration compatible with popular java logging)
... add your favorite to this wiki
As someone else said, there are several good logging frameworks available. However, if you want to roll your own, the first thing to note is that cout isn't a function, it's a stream. The function is operator<<. What you can do is something like the following:
/* trace.h */
extern ostream debug;
void trace_init();
void trace_done();
/* trace.cpp */
#include "trace.h"
ostream debug(cout.rdbuf());
static ofstream null;
void trace_init()
{
null.open("/dev/null");
if(output_is_disabled) { // put whatever your condition is here
debug.rdbuf(null.rdbuf());
}
}
void trace_done()
{
null.close();
}
You might have to adjust a bit if you're on a platform without /dev/null. What this does is let you write
debug << "here's some output << endl;
and if you have the output enabled, it will write to cout. If not, it will write to /dev/null where you won't see anything.
For that matter, you could just set cout's rdbuf to somewhere where you won't see that output, but I would find that to be a really bad idea. Creating new streams gives you a lot more flexibility in controlling your output.
In my application, I want to redirect the output that would normally go to the stdout stream to a function I define. I read that you can redirect stdio to a file, so why not to a function?
For example:
void MyHandler( const char* data );
//<<Magical redirection code>>
printf( "test" );
std::cout << "test" << std::endl;
//MyHandler should have been called with "test" twice, at this point
How can I achieve this / similar behaviour?
#Konrad Rudolph is right, you can totally do this, easily, at least for cout/cerr/clog. You don't even need your own streambuf implementation, just use an ostringstream.
// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );
// This goes to the string stream.
cout << "Hello, World!" << endl;
// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );
// Will output our Hello World! from above.
cout << strCout.str();
Same thing works for cerr and clog, but in my experience that will NOT work for stdout/stderr in general, so printf won't output there. cout goes to stdout, but redirecting cout will not redirect all stdout. At least, that was my experience.
If the amount of data is expected to be small, the freopen/setbuf thing works fine. I ended up doing the fancier dup/dup2 thing redirecting to a pipe.
Update: I wrote a blog post showing the dup2 method I ended up using, which you can read here. It's written for OS X, but might work in other Unix flavors. I seriously doubt it would work in Windows. Cocoa version of the same thing here.
Invoking a callback function whenever something’s written to the underlying standard output stream is hard: it requires overriding low-level, system-specific functions (on POSIX systems, it would require at least overriding write, and the way this is called might depend on the standard library implementation, so it might be different between e.g. glibc and musl).
But depending on what exactly you’re after you can solve this in C++ without resorting to low-level OS specific functions, by manipulating the C++ stream buffers directly.
For this you need to create your own std::streambuf implementation, i.e. your own stream buffer.
Once you have that, you can redirect the std::cout stream by switching the buffer:
auto buf = callback_streambuf(MyHandler);
auto pold_buffer = std::cout.rdbuf(&buf);
std::cout << "Hello" << std::cout;
// Restore original buffer:
std::cout.rdbuf(pold_buffer);
However, what this implementation won’t do is call your callback function exactly twice. Instead, the number of calls will depend on several factors, but it generally will not depend on the number of stream insertions (<<), and there is no way around that!
For the specific example above, the callback is called once, with the data "Hello\n".
The following minimal implementation illustrates how to get a streambuf to call your handler:
class callback_streambuf : public std::streambuf {
public:
callback_streambuf(std::function<void(char const*, std::streamsize)> callback) : callback(callback) {}
protected:
std::streamsize xsputn(char_type const* s, std::streamsize count) {
callback(s, count);
return count;
}
private:
std::function<void(char const*, std::streamsize)> callback;
};
This implementation has several caveats. For instance, it does the wrong thing when attempts are made to use it as an input stream. It doesn’t override overflow (since I don’t think this is ever called, although I find conflicting information about this on the internet; at any rate, adding overflow would be trivial). I didn’t implement synchronisation, so the callback will be called concurrently from multiple threads. Furthermore, there is no error handling, since the callback does not return a success status. I also had to change the signature of the callback to
void MyHandler(char const* data, std::streamsize count);
The second parameter is required since data isn’t a string, it’s a raw char buffer, so there is no way to determine its length intrinsically, and MyHandler can do nothing useful with the data without knowing its length.
Answer: Yes you can, via a dup. freopen will only reopen stdout to a file, as you talked about.
Check out How to buffer stdout in memory and write it from a dedicated thread
It's possible to disable stdin/stdout by dereferencing its pointer:
FILE fp_old = *stdout; // preserve the original stdout
*stdout = *fopen("/dev/null","w"); // redirect stdout to null
HObject m_ObjPOS = NewLibraryObject(); // call some library which prints unwanted stdout
*stdout=fp_old; // restore stdout
The std::cout object has a fixed meaning, and that is to output to the standard out stream. The user of your program gets to control where standard out is connected to, not you. What you can do is decide whether you wish to write to a file, to standard out or to any other output stream. So in your code you switch what stream you write to.
Again, the point of writing to the standard out stream is to give the user a flexibility in choosing where the output goes to. You're not supposed to redirect standard out; this is something the user is supposed to have the freedom to do.
Another thing is that you shouldn't mix C IO and C++ IO in a C++ program. Choose which IO library you wish to work with and stick to it.
That said, you can in C++ quite elegantly switch streams for a function to take input from by templating the handler function on the template parameters of std::basic_istream<>. Then the function will read its input from the input stream independently of the real kind of stream it's working with. Here's an example:
#include<iostream>
#include<fstream>
#include<string>
template<class Ch, class Tr>
void dodge_this(std::basic_istream<Ch, Tr>& in)
{
// in is an input stream. read from it as you read from std::cin.
}
int main(int argc, char* argv[])
{
if( std::string(argv[1]) == "cin" ) {
dodge_this(std::cin);
} else if( std::string(argv[1]) == "file" ) {
std::ifstream file("input.txt");
dodge_this(file);
} else {
dodge_this(dev_null_stream); // i just made that up. you get the idea.
}
}
Another option is to place your handler class calls into the inherited streambuf class. I had a requirement to redirect cout to a Win GUI edit control in a dialog box that may be of some use. Here is the class code:
//-------------------------------- DlgStringbuf Definition -----------------------
class DlgStringbuf : public std::stringbuf
{
public:
DlgStringbuf(void) : _hwndDlg(NULL), _editControlID(0), _accum(""), _lineNum(0) {}
void SetDlg(HWND dlg, int editControlID)
{ _hwndDlg = dlg; _editControlID = editControlID; }
void Clear(void)
{ _accum.clear(); _lineNum = 0; }
protected:
virtual std::streamsize xsputn(const char* s, std::streamsize num)
{
std::mutex m;
std::lock_guard<std::mutex> lg(m);
// Prepend with the line number
std::string str(s, (const uint32_t)num);
str = std::to_string(_lineNum) + ": " + str + "\r\n";
// Accumulate the latest text to the front
_accum = str + _accum;
// Write to the Win32 dialog edit control.
if(_hwndDlg != NULL)
SetDlgItemTextW(_hwndDlg, _editControlID, (LPCWSTR)(std::wstring(_accum.begin(), _accum.end())).c_str());
_lineNum++;
return(num);
}//end xsputn.
private:
std::string _accum;
HWND _hwndDlg;
int _editControlID;
uint32_t _lineNum;
};//end DlgStringbuf.
//-------------------------------- DlgStream Definition ------------------------------
class DlgStream : public std::ostream
{
public:
DlgStream(void) : std::ostream(&_sbuff) {}
void SetDlg(HWND dlg, int editControlID)
{ _sbuff.SetDlg(dlg, editControlID); }
void Clear(void)
{ _sbuff.Clear(); }
private:
DlgStringbuf _sbuff;
};
...and in the WinMain, someplace after the dialog box and its edit control is created:
// Redirect all cout usage to the activity dlg box.
// Save output buffer of the stream - use unique pointer with deleter that ensures to restore
// the original output buffer at the end of the program.
auto del = [&](streambuf* p) { cout.rdbuf(p); };
unique_ptr<streambuf, decltype(del)> origBuffer(cout.rdbuf(), del);
// Redirect the output to the dlg stream.
_dlgStream.SetDlg(hwndActivityDlg, IDC_EDIT_ACTIVITY);
_dlgStream.copyfmt(cout);
cout.rdbuf(_dlgStream.rdbuf());
cout << "this is from cout";
You can use sprintf to write to a character array and then read the value:
char buf[1024];
sprintf(buf, "test");
MyHandler(buf);
there are also snprintf and a few others depending on platform
I would like to have an easy to use way to write code like:
#include <iostream>
int main (){
std::cout << "hello, world!\n";
}
but that supports i18n. Here is an example using gettext():
#include <libintl.h>
#include <iostream>
int main (){
std::cout << gettext("hello, world!\n");
}
This can then be processed by xgettext to produce a message catalog file that can be used
by translators to create various versions. These extra files can be handled on target
systems to allow the user to interact in a preferred language.
I would like to write the code something like this instead:
#include <i18n-iostream>
int main (){
i18n::cout << "hello, world!\n";
}
At build time the quoted strings would be examined by a program like xgettext to produce the
base message catalog file. << operator with argument i18n::cout would take a string
literal as the key to lookup the run-time text to use from a message catalog.
Does it exist somewhere?
At build time the quoted strings would be examined by a program like xgettext to produce the base message catalog file. << operator with argument i18n::cout would take a string literal as the key to lookup the run-time text to use from a message catalog.
You try to convert a string like a single instance, but it isn't/
The point, you don't want something like this. Think of:
if(n=1)
i18n::cout << "I need one apple"
else
i18n::cout << "I need " << n << " apples" ;
So why this is would not work, because "n=1" or "n!=1" works only for English, many other languages have more then one plural form, also it requires translation of "I need X apples" as signle instance.
I suggest you just to learn to deal with gettext, it is quite simple and powerful, many people had thought about it.
Another point, you are usually do not call gettext but
#include <libintl.h>
#include <iostream>
#define _(x) gettext(x)
int main (){
std::cout << _("hello, world!\n");
}
This makes the code much cleaner, also it is quite a "standard" feature to use "_" as gettext alias.
Just learn how to use it, before you try to make "nicer" API. Just to mention, gettext API is quite de-facto standard for many languages, not only C.
The short answer is "No" :)
Seriously, which aspects of internationalization are you interested in? ICU provides pretty much everything but does not feel like standard C++. There are other libraries smaller in scope that provide some i18n functionalities, i.e. UTF-CPP for handling UTF-8 encoded strings.
Personally I would go with this answer, but it might be possible to use a bit of streambuf magic to do this as the text is written to the stream. If you're really interested in doing this though, please take a look at Standard C++ IOStreams and Locales by Langer and Kreft, it's the bible of iostreams.
The following assumes that everything written to the buffer is to be translated, and that each full line can be translated completely:
std::string xgettext (std::string const & s)
{
return s;
}
The following transbuf class overrides the "overflow" function and
translates the buffer every time it sees a newline.
class transbuf : public std::streambuf {
public:
transbuf (std::streambuf * realsb) : std::streambuf (), m_realsb (realsb)
, m_buf () {}
~transbuf () {
// ... flush m_buf if necessary
}
virtual std::streambuf::int_type overflow (std::streambuf::int_type c) {
m_buf.push_back (c);
if (c == '\n') {
// We have a complete line, translate it and write it to our stream:
std::string transtext = xgettext (m_buf);
for (std::string::const_iterator i = transtext.begin ()
; i != transtext.end ()
; ++i) {
m_realsb->sputc (*i);
// ... check that overflow returned the correct value...
}
m_buf = "";
}
return c;
}
std::streambuf * get () { return m_realsb; }
// data
private:
std::streambuf * m_realsb;
std::string m_buf;
};
And here's an example of how that might be used:
int main ()
{
transbuf * buf = new transbuf (std::cout.rdbuf ());
std::ostream trans (buf);
trans << "Hello"; // Added to m_buf
trans << " World"; // Added to m_buf
trans << "\n"; // Causes m_buf to be written
trans << "Added to buffer\neach new line causes\n"
"the string to be translated\nand written" << std::endl;
delete buf;
}
You mean you just want another API? You could write a small wrapper, shouldn't be too hard and it would give you the possibility to use the best API you can think of :)
I try to write and read object of class into and from binary file in C++. I want to not write the data member individually but write the whole object at one time. For a simple example:
class MyClass {
public:
int i;
MyClass(int n) : i(n) {}
MyClass() {}
void read(ifstream *in) { in->read((char *) this, sizeof(MyClass)); }
void write(ofstream *out){ out->write((char *) this, sizeof(MyClass));}
};
int main(int argc, char * argv[]) {
ofstream out("/tmp/output");
ifstream in("/tmp/output");
MyClass mm(3);
cout<< mm.i << endl;
mm.write(&out);
MyClass mm2(2);
cout<< mm2.i << endl;
mm2.read(&in);
cout<< mm2.i << endl;
return 0;
}
However the running output show that the value of mm.i supposedly written to the binary file is not read and assigned to mm2.i correctly
$ ./main
3
2
2
So what's wrong with it?
What shall I be aware of when generally writing or reading an object of a class into or from a binary file?
The data is being buffered so it hasn't actually reached the file when you go to read it. Since you using two different objects to reference the in/out file, the OS has not clue how they are related.
You need to either flush the file:
mm.write(&out);
out.flush()
or close the file (which does an implicit flush):
mm.write(&out);
out.close()
You can also close the file by having the object go out of scope:
int main()
{
myc mm(3);
{
ofstream out("/tmp/output");
mm.write(&out);
}
...
}
Dumping raw data is a terrible idea, from multiple angles. This will break even worse once you add pointer data.
One suggestion would be to use Boost.Serialization which allows for far more robust data dumping.
Your main problem is the file does not contain the contents yet due to fstream buffering. Close or flush the file.
I'll echo "you shouldn't be doing this". If you print out sizeof(myc) in the code above it's probably 4, as you'd expect... BUT try changing read and write to be virtual. When I did so, it prints out the size as 16. Those 12 bytes are internal guts with sensitive values—and saving them out and then reading them back in would be like expecting a pointer value to be still good if you wrote it and loaded it again.
If you want to circumvent serialization and map C++ object memory directly to disk, there are ways to hack that. But rules are involved and it's not for the faint of heart. See POST++ (Persistent Object Storage for C++) as an example.
I'll add that you did not check the fail() or eof() status. If you had you'd have known you were misusing the fstream API. Try it again with:
void read(ifstream *in) {
in->read((char *) this, sizeof(myc));
if (in->fail())
cout << "read failed" << endl;
}
void write(ofstream *out){
out->write((char *) this, sizeof(myc));
if (out->fail())
cout << "write failed" << endl;
}
...and see what happens.
My C++ is pretty rust and highly under-tested, but you may want to take a look at Serialization and Unserialization. FAQ
I've done something similar using output.write((char*)&obj, sizeof(obj)), obj being an instance of your class. You may want to loop this if you want to write the data inside the object instead, which would generally be the case as you need members to be readable, right ?
Same thing for reading with read function. But if you have dynamic allocation to do then with this data, you need to handle it.