Reputation: 4808
I was coding some C++ for a small hobby project when I noticed that I'm using C-style operations to access IO (printf
, fopen
, etc.).
Is it considered "bad practice" to involve C functions in C++ projects? What are the advantages of using streams over C-style IO access?
Upvotes: 32
Views: 17257
Reputation: 55705
Is it considered "bad practice" to involve C functions in C++ projects?
No. C functions are often used in C++ projects. Regarding the streams, Google C++ Style Guide, for example, recommends using them only in limited cases such as "ad-hoc, local, human-readable, and targeted at other developers rather than end-users".
What are the advantages of using streams over C-style IO access?
The main advantages are type safety and extensibility. However C++ streams have serious flaws, see the answers to this question such as problems with localization, poor error reporting, code bloat and performance issues in some implementations.
Upvotes: 3
Reputation: 44603
This is an heated topic.
Some people prefer to use the C++ IO since they are type-safe (you can't have divergence between the type of the object and the type specified in the format string), and flow more naturally with the rest of the C++ way of coding.
However, there is also arguments for C IO functions (my personal favorites). Some of them are:
printf
function, the generated code is smaller (this can be important in embedded environment).Personally, I wouldn't consider it bad practice to use C stream in C++ code. Some organisations even recommend to use them over C++ stream. What I would consider bad style is to use both in the same project. Consistency is the key here I think.
As other have noted, in a relatively large project, you would probably not use them directly, but you would use a set of wrapper function (or classes), that would best fit your coding standard, and your needs (localisation, type safety, ...). You can use one or the other IO interface to implement this higher level interface, but you'll probably only use one.
Edit: adding some information about the advantage of printf
formatting function family relating to the localisation. Please note that those information are only valid for some implementation.
You can use %m$
instead of %
to reference parameter by index instead of referencing them sequentially. This can be used to reorder values in the formatted string. The following program will write Hello World!
on the standard output.
#include <stdio.h>
int main() {
printf("%2$s %1$s\n", "World!", "Hello");
return 0;
}
Consider translating this C++ code:
if (nb_files_deleted == 1)
stream << "One file ";
else
stream << nb_file_deleted << " files ";
stream << removed from directory \"" << directory << "\"\n";
This can be really hard. With printf
(and a library like gettext
to handle the localization), the code is not mixed with the string. We can thus pass the string to the localization team, and won't have to update the code if there are special case in some language (in some language, if count of object is 0, you use a plural form, in other language, there are three forms one for singular, one when there is two object and a plural form, ...).
printf (ngettext ("One file removed from directory \"%2$s\"",
"%1$d files removed from directory \"%2$s\"",
n),
n, dir);
Upvotes: 45
Reputation: 147036
printf
and friends are hideously unsafe compared to <iostream>
, and cannot be extended, plus of course fopen
and friends have no RAII, which means that unless you've proved with a profiler that you definitely need the performance difference (that you've proved exists on your platform and in your code), you'd have to be an idiot to printf
.
Edit: Localization is an interesting thing that I hadn't considered. I've never localized any code and cannot comment on the relative localizational ability of printf
and <iostream>
Upvotes: 8
Reputation: 254741
Advantages
printf
arguments are passed through ...
causing undefined behaviour if they do not match the formatting.fclose
.Disadvantages
printf
formatting.Upvotes: 7
Reputation: 154047
As a general rule, you should prefer C++ operators, they're:
-- Type safe. You don't risk passing a double where the format calls for an int.
-- Extensible. You can write your own inserters and extracters, and use them.
-- Extensible. You can define your own manipulators (with application specific logical meaning), and use them. If you want to change the format of all of the WidgitNumber (internally, an int) in your output, you change the manipulator; you don't have to find all of the format statements where %d is a WidgitNumber.
-- Extensible. You can write your own sinks and sources, and these can forward to other sinks and sources, filtering or expanding the input or output as desired.
(FWIW: I don't think I've ever written an application which didn't use custom >> and << operators, custom manipulators, and custom streambuf's.)
Upvotes: 3
Reputation: 18572
Is it considered "bad practice" to involve C functions in C++ projects?
Usually, the file IO code should be encapsulated in a class or function implementation. I wouldn't consider any choices you make in the encapsulated implementations to be "bad practice", I reserve that term for what affects the user of your library or code (i.e. the interface). If you are exposing your file IO mechanism in the interface, then, IMO, it's bad practice whether you use IO stream or C-style IO functions.
I would rather say that C-style IO functions are (probably always) the worse choice.
What are the advantages of using streams over C-style IO access?
First, they integrate better with standard C++ constructs such as std::string
. They integrate fairly well with STL <algorithms>
. And they allow you to create encapsulated custom read/write operators (<< and >>) such that your custom classes almost look like primitive types when it comes to doing IO operations.
Finally, IO streams in C++ can use exception mechanism to report errors in the stream or read/write operations. These make the file IO code much nicer by avoid the terrible look of error-code mechanisms (sequence of if-statements and ugly while-loops, that check the error code after each operation).
Upvotes: 3
Reputation: 24561
For a small hobby project I would probably go with the more type-safe C++ io streams.
Funny enough, I've never seen a non-trivial real-life project that uses either of them. In all cases we used some abstractions built on top of the native OS API for IO.
Upvotes: 6
Reputation: 133112
Nothing can be considered bad practice if it has a definite purpose. I mean, if IO is the bottleneck of the program, then yes, C-style IO works faster than C++ IO. But if it is not, I would go with C++ stream approach. Cuz it's cuter :)
Upvotes: 6
Reputation: 19102
IMHO, a real C++ programmer tries to do things in idiomatic C++ way; the C converted programmer tries to cling on old ways of doing things. It has to do with readability and consistency.
Upvotes: 5
Reputation: 61457
For one, you don't have to convert C++ objects (notably string
s) to C-compatible forms first.
Upvotes: 3