C++ How to write a logfile - c++

I have to write a program for school that calculates current, voltage, and efficiency. I have almost finished the program but now I want to write the results in a logfile. I have already read some threads but it didn't really help.
here is the part that I want to write in a logfile:
cout<<"Die spannung U1 betraegt"<<U1<<"Ohm."<<endl;
I would really appreciate help thanks.

Simply using File I/O in C++ locally should solve your issue:
#include <fstream>
//...
ofstream fout("logfile.txt");
if (fout){
fout << "Die spannung U1 betraegt" << U1 << "Ohm." <<endl;
fout.close();
}
However, logging can become very cumbersome, so people have come up with all kinds of solutions for loggers. I found this article on logfiles (In context of the Singleton design pattern) to be very useful.

I would recommend using FILE and fprintf.
http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_fprintf-printf-sprintf.html
Remember - if you have threads - you need to protect the object,
don't forget to fflush() when the content is meaningful, and to fclose when you're done.
There are other methods to do it- I presonally like the bare bone the most..

Related

Safe use of std::tmpnam

so I am developing an application, which requires to create a file, write into it, call another program with that file is an input, and delete the file.
I looked for possible solution and one solution looks like this.
std::FILE* tmpf = std::tmpfile();
std::fputs("Hello, world", tmpf);
According to the documentation of std::tmpfile, if either the file is closed manually, or the program exits in natural way, the file will be deleted. This looks like good solution with one exception. It looks messy (using C I/O, instead of C++ streams).
Another solution would be to use std::tmpnam, which will generate unique file name.
std::string file_name = std::tmpname(NULL);
// (*)
std::fstream stream{file_name};
stream << "Hello World" << std::endl;
But there is a problem with this one too. If another program creates file with the same name, while my program is in (*), we will both be doing operations on same file, which is certainly something I'd like to avoid.
C++ STL (still) does not support file system operations, like checking if file exists. I could use something like stat to check that, but since checking for file and creating it is not atomic, it would not solve anything. And I did not find C++ STL method of atomic operation, which would: Check if file exists, if not, open it, if yes, fail.
So, my question is, what is the right way of solving this problem? Did I miss something?
Your specification "...create a file, write into it, call another program with that file is an input, and delete the file." is incompatible with tmpfile(). For one thing, there is no (portable) way to get the file name from the FILE pointer you get from tmpfile(), secondly on POSIX platforms tmpfile() will typically delete the file from the directory before returning from tmpfile() (if you're unfamiliar with POSIX filesystem semantics, the file exists as long as your process has an open file descriptor to it even after it's deleted from the directory, meaning there is no way to access it from the filesystem).
Given that, you'll have to use some kind of tmpname() type approach, and figure out a way to prevent two processes from simultaneously accessing it (file locks, check link count with stat(), or such).
Or better yet, don't use files for interprocess communication. For the simplest possible(?) case, create a pipe in the parent, connect it to stdin of the child.
Here is my almost not messy solution:
#include <cstdio>
#include <iostream>
#include <string>
#include <ext/stdio_filebuf.h> // libstdc++ specific
int main()
{
__gnu_cxx::stdio_filebuf<char> tmpfile_buf{std::tmpfile(), std::ios::in | std::ios::out | std::ios::binary};
std::iostream tmpstream{&tmpfile_buf};
// write in stream
tmpstream << "Hello World" << std::endl;
tmpstream.seekg(0);
// read from stream
std::string str;
std::getline(tmpstream, str);
std::cout << str << std::endl;
}
Live example
std::tmpfile() is used and a stream is build from a buffer having an underlying FILE*. This is a GNU extension and thus not portable :(.
I may have a Boost solution to suggest, but I can't test it here.
With a FILE* returned from std::tmpfile(), one can get a file descriptor:
#include <cstdio>
FILE* const tmpfile = std::tmpfile();
const int fd = ::fileno(tmpfile);
and at this stage, everything looks good to use boost::iostreams::file_descriptor_source:
#include <boost/iostreams/code_converter.hpp>
#include <boost/iostreams/maped_file.hpp>
file_descriptor_source tmpstream(fd, boost::iostreams::close_handle);

What are 'aliased' stream buffers?

What are 'aliased stream buffers`? I encountered the term in a comment on an answer of mine.
I've never heard the term before, but in the thread you cite,
the person who used it also gave an example: two streams which
use the same streambuf.
Of course, just because two streams don't use the same
streambuf, doesn't mean that data written to them doesn't
ultimately end up in the same place; that they don't alias the
same sink, if that is what is meant. There are filtering
streambuf's, which forward the actual sinking and sourcing to
another streambuf, and on most systems, it's possible to open
a file at the system level, and connect a streambuf (or two) to
it.
--
James Kanze
It means an object with different name, for example this:
ostream &lbw = cout;
lbw << "Shahid out" << "Sachin in" << endl; //goes to cout!
What probably was meant in the comment there is this:
ofstream file;
file.rdbuf(cout.rdbuf());
// writes to cout
file << "hello";
So now the check there doesn't work:
if(&file == &cout)
// no, it doesn't

C++ pipes in Objective-C

I made the transition from C++ to objective-C a while ago, and am now finding NSLog() tiresome. Instead, still in Objective-C, I would like to be able to write something like
stdout << "The answer is " << 42 << "\n";
(I know that NSLog prints to stderr, I could put up with writing stderr << "Hello world";)
Basically, I just want to be able to use the C++ pipe syntax in Objective-C.
I don't care about speed (within reason) or if the only method uses precompiler macros or other hack-ish things.
You really should get used to format strings as in NSLog. The C++ style syntax may be easy to write, but it is a nightmare to maintain. Think about internationalization. A format string can easily be loaded at runtime. Cocoa provides the function NSLocalizedString for that. But for C++’s stream operators you probably have to write different code for every language.
What you're wanting is stream operations.
There isn't a really 'good' way to do this in Cocoa, I have a library that I never really fleshed out that would allow you to do something 'near' this, but still wouldn't get a lot of the benifits.
http://github.com/jweinberg/Objective-Curry/blob/master/OCFileStream.m
Starting from there you would be able to write a class that did
[[[stdOutStream write:#"10"] write:[bleh description]] write:#"more stuff"];

Internal "Tee" setup

I have inherited some really old VC6.0 code that I am upgrading to VS2008 for building a 64-bit app. One required feature that was implemented long, long ago is overriding std::cout so its output goes simultaneously to a console window and to a file. The implementation depended on the then-current VC98 library implementation of ostream and, of course, is now irretrievably broken with VS2008. It would be reasonable to accumulate all the output until program termination time and then dump it to a file. I got part of the way home by using freopen(), setvbuf(), and ios::sync_with_stdio(), but to my dismay, the internal library does not treat its buffer as a ring buffer; instead when it flushes to the output device it restarts at the beginning, so every flush wipes out all my accumulated output. Converting to a more standard logging function is not desirable, as there are over 1600 usages of "std::cout << " scattered throughout almost 60 files. I have considered overriding ostream's operator<< function, but I'm not sure if that will cover me, since there are global operator<< functions that can't be overridden. (Or can they?)
Any ideas on how to accomplish this?
You could write a custom stream buffer and attach it to cout with cout.rdbuf(). Your custom stream buffer would then tee the data to cout's original stream buffer and to a stream buffer stolen from an appropriate ofstream.
ofstream flog("log.txt");
teebuf tb(flog.rdbuf(), cout.rdbuf());
cout.rdbuf(&tb);
For your teeing stream buffer you can get an inspiration from this page.
You could use the pre-processor:
#define cout MyLogger
to inject new code.

Non-threadsafe file I/O in C/C++

While troubleshooting some performance problems in our apps, I found out that C's stdio.h functions (and, at least for our vendor, C++'s fstream classes) are threadsafe. As a result, every time I do something as simple as fgetc, the RTL has to acquire a lock, read a byte, and release the lock.
This is not good for performance.
What's the best way to get non-threadsafe file I/O in C and C++, so that I can manage locking myself and get better performance?
MSVC provides _fputc_nolock, and GCC provides unlocked_stdio and flockfile, but I can't find any similar functions in my compiler (CodeGear C++Builder).
I could use the raw Windows API, but that's not portable and I assume would be slower than an unlocked fgetc for character-at-a-time I/O.
I could switch to something like the Apache Portable Runtime, but that could potentially be a lot of work.
How do others approach this?
Edit: Since a few people wondered, I had tested this before posting. fgetc doesn't do system calls if it can satisfy reads from its buffer, but it does still do locking, so locking ends up taking an enormous percentage of time (hundreds of locks to acquire and release for a single block of data read from disk). Not doing character-at-a-time I/O would be a solution, but C++Builder's fstream classes unfortunately use fgetc (so if I want to use iostream classes, I'm stuck with it), and I have a lot of legacy code that uses fgetc and friends to read fields out of record-style files (which would be reasonable if it weren't for locking issues).
I'd simply not do IO a char at a time if it is sensible performance wise.
fgetc is almost certainly not reading a byte each time you call it (where by 'reading' I mean invoking a system call to perform I/O). Look somewhere else for your performance bottleneck, as this is probably not the problem, and using unsafe functions is certainly not the solution. Any lock handling you do will probably be less efficient than the handling done by the standard routines.
The easiest way would be to read the entire file in memory, and then provide your own fgetc-like interface to that buffer.
Why not just memory map the file? Memory mapping is portable (except in Windows Vista which requires you to jump through hopes to use it now, the dumbasses). Anyhow, map your file into memory, and do you're own locking/not-locking on the resulting memory location.
The OS handles all the locking required to actually read from the disk - you'll NEVER be able to eliminate this overhead. But your processing overhead, on the otherhand, won't be affected by extraneous locking other than that which you do yourself.
the multi-platform approach is pretty simple. Avoid functions or operators where standard specifies that they should use sentry. sentry is an inner class in iostream classes which ensures stream consistency for every output character and in multi-threaded environment it locks the stream related mutex for each character being output. This avoids race conditions at low level but still makes the output unreadable, since strings from two threads might be output concurrently as the following example states:
thread 1 should write: abc
thread 2 should write: def
The output might look like: adebcf instead of abcdef or defabc. This is because sentry is implemented to lock and unlock per character.
The standard defines it for all functions and operators dealing with istream or ostream. The only way to avoid this is to use stream buffers and your own locking (per string for example).
I have written an app, which outputs some data to a file and mesures the speed. If you add here a function which ouptuts using the fstream directly without using the buffer and flush, you will see the speed difference. It uses boost, but I hope it is not a problem for you. Try to remove all the streambuffers and see the difference with and without them. I my case the performance drawback was factor 2-3 or so.
The following article by N. Myers will explain how locales and sentry in c++ IOStreams work. And for sure you should look up in ISO C++ Standard document, which functions use sentry.
Good Luck,
Ovanes
#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
double do_copy_via_streambuf()
{
const size_t len = 1024*2048;
const size_t factor = 5;
::std::vector<char> data(len, 1);
std::vector<char> buffer(len*factor, 0);
::std::ofstream
ofs("test.dat", ::std::ios_base::binary|::std::ios_base::out);
noskipws(ofs);
std::streambuf* rdbuf = ofs.rdbuf()->pubsetbuf(&buffer[0], buffer.size());
::std::ostreambuf_iterator<char> oi(rdbuf);
boost::progress_timer pt;
for(size_t i=1; i<=250; ++i)
{
::std::copy(data.begin(), data.end(), oi);
if(0==i%factor)
rdbuf->pubsync();
}
ofs.flush();
double rate = 500 / pt.elapsed();
std::cout << rate << std::endl;
return rate;
}
void count_avarage(const char* op_name, double (*fct)())
{
double av_rate=0;
const size_t repeat = 1;
std::cout << "doing " << op_name << std::endl;
for(size_t i=0; i<repeat; ++i)
av_rate+=fct();
std::cout << "average rate for " << op_name << ": " << av_rate/repeat
<< "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
<< std::endl;
}
int main()
{
count_avarage("copy via streambuf iterator", do_copy_via_streambuf);
return 0;
}
One thing to consider is to build a custom runtime. Most compilers provide the source to the runtime library (I'd be surprised if it weren't in the C++ Builder package).
This could end up being a lot of work, but maybe they've localized the thread support to make something like this easy. For example, with the embedded system compiler I'm using, it's designed for this - they have documented hooks to add the lock routines. However, it's possible that this could be a maintenance headache, even if it turns out to be relatively easy initially.
Another similar route would be to talk to someone like Dinkumware about using a 3rd party runtime that provides the capabilities you need.