• Advertisement
Sign in to follow this  

files in c/c++

This topic is 4144 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi, In C you open files to read and write using functions in stdio.h. In c++ you use the streams instead for file operations. What is the difference between the 2 methods as they both appear to do the same thing, so why did c++ reinvent file operations?

Share this post


Link to post
Share on other sites
Advertisement
Streams are adapted to C++'s object-oriented approach. In particular, polymorphism allows them to be extended globally instead of individually. Using C, and typedef struct { float x; float y; } complex;, write a single function to write a complex in text form to:
- the standard output, error output, or log
- a file
- another string
- any kind of equivalent object, passed as an argument

The C++ version is:


std::ostream& operator<<(std::ostream& out, const complex& c) {
return out << "(" << c.x << "," << c.y << ")";
}

// Usage:
complex c;

std::cout << c;
std::cerr << c;
std::clog << c;

std::ofstream fout("foo.txt");
fout << c;

std::stringstream sout;
sout << "The complex is '" << c << "'.";

mystream mout;
mout << c;



Of course, binary writing is possible in the exact same way.

Share this post


Link to post
Share on other sites
Plus c++ streams are designed to work well with generic programming methods as well (ala templates). This means they are compatable with the various algorithms that are available to in the standard c++ library (see ostream_iterator and istream_iterator for details).

eg:


std::vector<int> v;

// copy typed in numbers into a vector
std::copy(
std::istream_iterator(std::cin, ' '),
std::istream_iterator(),
std::back_inserter(v)
);

// write vector to screen
std::copy(
v.begin(),
v.end(),
ostream_iterator(std::cout, '\n' )
);


And adding that to what ToohrVyk said makes it possible to do that with anything that derives from istream ad ostream (which bothe derive from stream)

Share this post


Link to post
Share on other sites
Another of advantage of C++'s method of file I/O that's worth mentioning in it's own category is it's type safe.

With C style *printf, your compiler will at best warn you (which if you accidentally skim over to work on later, may not come up again for quite awhile if you're using conditional recompilaiton), and at worst silently cause runtime failures if you mismatch the variable type and format specifier. This also causes mantinence nightmares for changing types as every format string by necessity repeats the variable type, and thus must be updated in sync.

Worse yet, behavior is completely undefined if you pass an object to a va_args using function.

On the other hand, C++ streams don't force you to repeat the type. It uses operator overloading to select the appropriate formatting option based on type. It works sanely with custom classes, and it's downright impossible to mismatch the number of format specifiers and display arguments.

Those advantages that format specifiers do have - namely, discoupling format from the code that wants to display a formatted string - can be accomplished using the boost::format library, which interoperates with C++'s iostreams for all of the advantages and none of the avoidable disadvantages:

1) Unlike *printf, boost::format still uses operator chaining to accomplish it's argument input, meaning it can automatically deduce types and number of arguments safely.

2) While like *printf it's possible to mismatch format specifiers and the total number of arguments with boost::format, unlike *printf, this has specified and defined behavior, rather than undefined "launch nukes at a cow ranch in Alaska for all I care" va_args behavior.

This has been a message from the "all you ever wanted to know about the advantages of iostreams over FILE*s, and then some" department of information.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Streams are adapted to C++'s object-oriented approach. In particular, polymorphism allows them to be extended globally instead of individually. Using C, and typedef struct { float x; float y; } complex;, write a single function to write a complex in text form to:
- the standard output, error output, or log
- a file
- another string
- any kind of equivalent object, passed as an argument

The C++ version is:

*** Source Snippet Removed ***

Of course, binary writing is possible in the exact same way.


Why would you manipulate a stream using ostream say instead of just using ofstream/cout on any object data you need. A more manula way I guess.

What benefit is there as it seems a more complicated way to use files?

Share this post


Link to post
Share on other sites
Quote:
Original post by jagguy
Why would you manipulate a stream using ostream say instead of just using ofstream/cout on any object data you need. A more manula way I guess.

What benefit is there as it seems a more complicated way to use files?


You've got your view reversed, that's all.

The benefit of using an ostream instead of a concrete implementation of an ostream is that you've separate the concept of a stream from the concept of a file, or a string, or a socket, or a hyperspace transporter. Your object doesn't care about the internals of where it's serializing its data to.

With C, your object would have to know where your data is going, and use fprintf() or sprintf() or send() or whatever. With C++, you just stream to an ostream and let the ostream object woryy about which orifice it's filling.

This is a basic idiom in object-oriented design.

Share this post


Link to post
Share on other sites
Quote:

so why did c++ reinvent file operations?

For what it's worth, the difference between the C standard library file IO routines and the C++ standard library file IO routines is largely one of interface (in that the C++ version's interface has all of the aforementioned advantages).

Neither really constitute a "reinvention" of the actual file operations, which in the long run all call down to the file IO routines of whatever operating system you're running.

Share this post


Link to post
Share on other sites
Bregma, nice way to put it... quite colorful [cool]

I think it should be noted that the advantages in using streams instead of FILE pointers, etc, is completely dependent on implementation and circumstance. IE: it is somewhat silly to use a stream to open a single file of known name and format from which you are reading a string of known size (bad example, I know). But generally, streams are a better idea if you are concerned about runtime errors since the printf functions are rather difficult to debug (however you will run into far more problems when using the sprintf functions... those seem to enjoy causing headaches).

Share this post


Link to post
Share on other sites
Quote:

I think it should be noted that the advantages in using streams instead of FILE pointers, etc, is completely dependent on implementation and circumstance.

I disagree; if you are using C++, I don't see any reason to use the C file IO routines.

Quote:

it is somewhat silly to use a stream to open a single file of known name and format from which you are reading a string of known size (bad example, I know)

Yes, terrible example. How is this "silly?"

{
std::ifstream fp("test.txt");
std::string s;

fp >> s;
}

When compared to the C equivalent, this is cleaner, safer, and shorter. Where's the disadvantage? Where's the "silliness?"

Don't use C when you're writing C++.

Share this post


Link to post
Share on other sites
It also has much more overhead. But anyway, it is certainly shorter and safer.

I must say, though, the concept of not using C when writing C++ is more than slightly crazy. Especially because the old standard headers are not technically part of the language. When you are writing C++ you ARE writing C except that you are also using some newer features such as classes, etc. So lets revise that to say "Don't use C libraries when you're writing C++". Sorry, I digress.

Share this post


Link to post
Share on other sites
Quote:

When you are writing C++ you ARE writing C


C and C++ share a common syntactical ancestry. The intersection set of the syntax of modern C and modern C++ does not form a (recognized and named) language. In other words, "No, not neccessarily."

Quote:

It also has much more overhead.

It might (although the overhead is easily a small price to pay for the safety, and besides, actually reading from the disk will be the operation bottleneck anyway, not the host program code). The implementation for fopen() and the constructor of std::ifstream on my implementation converges to the same OS-level call by about four function calls (only two of which do any work).

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
It also has much more overhead. But anyway, it is certainly shorter and safer.

I must say, though, the concept of not using C when writing C++ is more than slightly crazy. Especially because the old standard headers are not technically part of the language. When you are writing C++ you ARE writing C except that you are also using some newer features such as classes, etc. So lets revise that to say "Don't use C libraries when you're writing C++". Sorry, I digress.


hm.. the c++ version does at compile time detect type and sets up proper file reading and conversion to your c++ types, while a c version has to at runtime parse the printf/scanf statements, interpret them, read in from the file (or write out to it), and convert the types then according to the interpreted string.

now what, do you guess, is faster at runtime? what is simpler? less error prone?


oh, and no, if you're coding in c++, you're coding in c++. it happens to be mostly compatible with c-code, but that doesn't mean it should be used.

Share this post


Link to post
Share on other sites
Quote:
Original post by medevilenemy
It also has much more overhead. But anyway, it is certainly shorter and safer.


I've seen Fruny run a test between the old C file libraries and C++ file streams. Once you disable stdio syncing, the speed is exactly the same.

Quote:
I must say, though, the concept of not using C when writing C++ is more than slightly crazy. Especially because the old standard headers are not technically part of the language. When you are writing C++ you ARE writing C except that you are also using some newer features such as classes, etc. So lets revise that to say "Don't use C libraries when you're writing C++". Sorry, I digress.


I think that'd be even better revised as "Don't use old C libraries when you're writing in C++ if there is a better C++ library available" [grin].

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement