I am calling a function funcB from funcA.
funcB uses several printf statements to output data.
Is there a way for me to capture that data via funcA?
I can not modify funcB.
funcB(){
printf( "%s", "My Name is" );
printf( "%s", "I like ice cream" );
}
funcA(){
funcB();
}
(This answer is a corrected version based on this answer.)
This answer is POSIX centric. Use open to create a file descriptor for the file you want to redirect to. Then, use dup2 to STDOUT_FILENO to change stdout to write to the file instead. But, you'll want to dup the STDOUT_FILENO before you do that, so you can restore stdout with another dup2.
fflush(stdout);
int stdout_fd = dup(STDOUT_FILENO);
int redir_fd = open(redirected_filename, O_WRONLY);
dup2(redir_fd, STDOUT_FILENO);
close(redir_fd);
funcB();
fflush(stdout);
dup2(stdout_fd, STDOUT_FILENO);
close(stdout_fd);
If funcB is using std::cout, use std::cout.flush() instead of fflush(stdout).
If you want to manipulate C++ streams more directly, you can use Johnathan Wakely's answer.
If nothing else in your program uses printf, you can write your own version and link it explicitly. The linker will not look in the standard library if the function is already defined. You can probably use vsprintf for the implementation, or some safer version with overrun checking if it is supplied by your compiler.
If you're willing to play a dirty game interposing on printf you can 'steal' its output doing something like:
#include <stdio.h>
#include <stdarg.h>
static char buffer[1024];
static char *next = buffer;
static void funcB(){
printf( "%s", "My Name is" );
printf( "%s", "I like ice cream" );
}
static void funcA(){
funcB();
// Do stuff iwth buffer here
fprintf(stderr, "stole: %s\n", buffer);
next=buffer; // reset for later.
}
int main() {
funcA();
}
int printf(const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
const int ret = vsnprintf(next, sizeof buffer-(next-buffer), fmt, argp);
next += ret;
va_end(argp);
return ret;
}
You could use a flag to indicate how to handle the instances where you want printf to work as normal. (E.g. map it onto fprintf or use dlsym()/similar to find the real call).
You could also use realloc to manage the size of the buffer more sensibly.
Put funcB in a separate program. You can then capture its standard output, e.g. by piping or by redirecting it to a file. How to do that generally depends on the OS and is outside the realm of C++.
Alternatively, maybe you can redirect your funcA process' standard output to a file, then call FuncB, and retrieve the output from the file.
Again, how to do that is outside the realm of C++ and depends on the OS.
Related
I have a program that writes occasional status updates, but I'm sure some will want it to run silently so I have provided a -s / --silent CLI option. What would be the best way to have my program abide by that parameter?
This method adds a global variable, and still executes the fprintf functions adding to the smell slightly.
FILE *outfile
if (silent) {
*outfile = NULL;}
else {
*outfile = stderr;}
fprintf (outfile, "This program can run silently");
This method also adds a global variable, and if statments littered throughout the code also adding to the smell.
if (!(silent)){
fprintf (stdout, "This program can run silently");
}
Ternary operators with a global variable might be more elegant:
(silent) ? : fprintf(stdout, "This program can run silently");
Are there better practices than any of these methods? Are there shortcomings to any one that I'm not seeing?
As Don Shankin said in his comment, the most maintainable way to do it is by wrapping fprintf() in a function that implements your filtering logic, and then have your code call the wrapper function rather than calling fprintf() directly. That way you only have to implement the filtering logic in a single location and not all over the place. Here's a program that demonstrates the technique:
#include <stdio.h>
#include <stdarg.h>
bool silent = false;
void my_fprintf(FILE * outFile, const char * fmt, ...)
{
if (silent == false)
{
va_list argsList;
va_start(argsList, fmt);
vfprintf(outFile, fmt, argsList);
va_end(argsList);
}
}
int main(int argc, char ** argv)
{
my_fprintf(stdout, "Not silent now...\n");
silent = true;
my_fprintf(stdout, "But now I'm silent, so you won't see this!\n");
silent = false;
my_fprintf(stdout, "Silent is false again!\n");
return 0;
}
... and here is the output from the program:
Not silent now...
Silent is false again!
Since it's also tagged C++, I'd like to point out that you can replace the output buffer of std::cout by calling std::cout.rdbuf(newbuf). A "devnull buff" is trivial to implement.
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);
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
This is with reference to the question I asked earlier -
What is the correct way to declare and use a FILE * pointer in C/C++?
MyFile.h
char sMsg[712] = "";
#define STD_MSG(string) \
fprintf (stderr, string)
#define ERR_MSG(fp, string) \
fprintf (fp, "%s\n", string);\
fflush (fp)
MyFile.C
#include "PdmTestClnt.h"
//---------------------------------------------------------------
// ** Global variables
//---------------------------------------------------------------
FILE * fpErr = NULL;
funcxyz() {
//FILE * fpErr1 = NULL;
sprintf (sMsg, "************ CHECKING FOR THE CRASH ************. \n");
ERR_MSG (fpErr, sMsg);
//ERR_MSG (fpErr1, sMsg);
}
//========================================================================
// Main
//========================================================================
integer main (integer argc, char ** argv)
{
//FILE * fpErr = NULL;
if (!(fpErr = sysFopen (sErrFileName, "a+")))
{
sprintf (sMsg,"Error in opening file %s", sErrFileName);
STD_MSG (sMsg);
}
// Log in the error file
sprintf (sMsg, "Log into the error file. \n");
ERR_MSG (fpErr, sMsg);
funcxyz();
}
If the File pointer is declared global it works. But if it is declared local it results in Memory fault(coredump).
Ran on:
HP Unix Itanium
aCC compiler (C++ Compiler)
Can somebody explain the behaviour?
Edit: Sorry for not editing the question. I now understand the problem with printf()/fprintf(). I showed the results for printf()/fprintf() with Dev C++ compiler on Windows in my answer. But when I run it on HP Unix with aCC compiler it ignores %s completely and always prints the string correctly. So how do I ask my architect to change it without showing him it memory fault on Unix?
Thanks.
Assuming by local you mean in funcxyz() uncommenting fpErr1, it segfaults because you don't open a file. You can't just use NULL there, where would you expect the data to go?
I would suggest writing funcxyz to take fpErr1 as a parameter, e.g.:
funcxyz(FILE *fpErr1) {
//FILE * fpErr1 = NULL;
sprintf (sMsg, "************ CHECKING FOR THE CRASH ************. \n");
ERR_MSG (fpErr1, sMsg);
//ERR_MSG (fpErr1, sMsg);
}
And then calling it from main like:
...
funcxyz(fpErr);
...
This information is irrelevent to the question. I should read more carefully before I answer. =X
Your problem is that you're shadowing the fpErr on the global scope with the one in the local scope. For example:
int var = 0;
void print_var() {
printf("print_var: %d\n", var);
}
int main() {
int var = 42;
printf("main: %d\n", var);
print_var();
return 0;
}
If you run the code, the output should be:
main: 42
print_var: 0
In your case, fpErr has a value of NULL (0) and thus the file I/O functions try accessing data at NULL, which causes the segmentation fault.
Don't define variables in headers - it is a nasty habit to get into.
Remove the initializer from sMsg[] in the header, and prepend 'extern' - and do define the variable, with initializer, in an appropriate source file (usually MyFile.c if the header is MyFile.h). This really matters when MyFile.h is used by several source files - and if it is used by just one source file, why were you using a header in the first place?
Your code also includes 'PdmTestClnt.h' and not MyFile.h - should we assume that MyFile.h is what you meant to include?
funcxyz() has no return type - it won't compile in C++ or under a strict C99 compiler. Why does the function format into sMsg, and then use fprintf() to copy the string? fprintf() can do the whole job (and then some).
Why you need a global definition
When you have a global variable, the code in main() initializes it by calling fopen(), and the other functions can use the initialized value. That's convenient. When you have a local variable, you have to initialize it. That's a pain because you'd end up opening the file many times which has numerous unwanted side effects - too many file handles in use, you have to close them too, and you probably keep truncating the output already in the file. To avoid that, pass the file pointer to the functions - or accept that a global is OK. Think about it - in some shape or form, the names stdin, stdout and stderr refer to global variables too.
void funcxyz(FILE *fp)
{
sprintf(sMsg, "************ CHECKING FOR THE CRASH ************. \n");
ERR_MSG (fpErr, sMsg);
}
int main(int argc, char **argv)
{
FILE *fpErr = NULL;
if ((fpErr = sysFopen(sErrFileName, "a+")) != 0)
{
sprintf(sMsg,"Error in opening file %s", sErrFileName);
STD_MSG(sMsg);
}
// Log in the error file
sprintf(sMsg, "Log into the error file. \n");
ERR_MSG(fpErr, sMsg);
funcxyz(fpErr);
return(0);
}