File reading/writing in C

Started by
22 comments, last by Zahlman 17 years, 11 months ago
You don't need to change your file extensions. C++ compilers will compile .c files fine.

And if you put a call to ios::synch_with_stdio() at the start of your program, you can freely mix C-style and C++-style file and console reading and writing functions.

I'm afraid I can't agree that:

printf("%d\n",i);

is cleaner than

cout << i << endl;

And the reason for << is that it creates an extensible input/output system that can be extended to support user-defined types, unlike printf, fgets and all the other motley crew of functions which are by their nature error-prone and susceptible to array overflows.

Having said that, I quite like C programming as well so please feel free to ignore the above. :)
Advertisement
Ah yes, but what about those :: things. Why must they insist we have those dotted around our program like mines? What do the denote, other than as far as I know, a sub function.

And that private and public stuff, what good is it? If you don't what to access a variable... DON'T ACCESS IT. There is no need to denote it as "private" to stop yourself from doing so.

Argh. Maybe I'll read a book on the language. :/
You don't make something private to stop you from accessing it. You do it to stop ME from accessing it :)
Ah, yes I suppose that its true.

Anyway, new problem! :)

Standard cpp never compiles on my computer (I'm using standard gcc on a mac.) I've had this issue before, and so decided to use C.

However, if I change the C++, so that it is not like that found on the internet or in books (which I'm assuming is standard, simple c++) so that all my cout's and cin's have std:: before them, it works. Now, it's doing the same thing but with my ifstream's and ofstreams. Say this is my code:

#include <iostream.h>
#include <fstream.h>


ifstream in_stream;
ofstream out_stream;

char some_variable;

int main() {

in_stream.open("test.txt");

in_stream >> some_variable;

std::cout << some_variable << endl;

return 0;
}

I would get these errors:



In file included from /usr/include/gcc/darwin/4.0/c++/backward/iostream.h:31,
from test.cpp:1:
/usr/include/gcc/darwin/4.0/c++/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
/usr/bin/ld: Undefined symbols:
std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
std::basic_ifstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)
std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream()
std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()
std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream()
std::basic_ofstream<char, std::char_traits<char> >::~basic_ofstream()
std::ios_base::Init::Init()
std::ios_base::Init::~Init()
std::cout
std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)
std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)
___gxx_personality_v0
collect2: ld returned 1 exit status



And I'm not sure what they mean.

Thanks for any help you guys/gals can give me!
Quote:Original post by OneMoreToGo
I choose not to use C++, because C is far more clean, and results in easier to understand code.


This is some kind of joke?

// C++#include <iostream>#include <string>#include <algorithm>int main() {  std::string hw("hello");  hw += ", world!";  std::sort(hw.begin(), hw.end());  hw += "%d"; // not for formatting, but to force workarounds in the C version ;)  std::cout << hw << 123 << std::endl;}


vs.

// C#include <stdlib.h>#include <stdio.h>#include <string.h>int chrcmp(const void* x, const void* y) {  return *x - *y;}void main() {  char* h = "hello";  char* hw = malloc(strlen(h) + strlen(", world!") + strlen("%d") + 1);  strcat(strcpy(hw, h), ", world!");  qsort(hw, strlen(hw), 1, chrcmp);  strcat(hw, "%d"); /* I was clever enough to allocate ahead of time for this */  printf("%s%d\n", hw, 123);  free(hw);}


In the C code you have to:

- Do all your own memory management - and either be unusually clever about it, or end up with repeated allocations. This is "cleaner"?
- Slow things down by repeatedly checking string lengths, or else clutter the code and complicate the logic by caching calculated string length values. The C++ string object carries the length with it.
- Invoke functions with names like "strcpy". This is "easier to understand"?
- Deal with format specifiers to output multiple things. The "silly" >> and << operands have the nice properties that they (a) can be made to work with any data type, while printf-style output can only ever work with primitives; (b) are typesafe - you never have a format string that needs to be kept in sync with the data, and you never have mysterious crashes when you mess that up.
- Write your own comparison function to compare two pointed-at characters! (If you think you can just use strcmp, well it should work, but it will also be inefficient, and do meaningless random comparisons of characters that follow the ones that the sort algorithm is currently interested in. The C++ library sort has a templated equal-comparison available and also uses it by default - but you can supply something else if you need to.
- Tell the sort algorithm the size of your objects. And it's schizophrenic, too: when you write the comparison function, it's up to you to make sure that it understands the same "block size" that qsort does.

Quote:Besides, using C++ would mean having to re-learn certain aspects of the language


No, it would require you to learn a new language that coincidentally happens to have a lot in common with C. Treating it as "an improved C" is a wrong mindset for learning the language. But it *is* definitely "improved", compared to C.

Quote:and also having to adapt the code on a project for which these file reading fuctions are destined, seeing as it would be stupid to only change my file extensions. If I were to use C++ for this work, I would have to go through my code making it C++'ish, otherwise there's no point at all.


In the long run your investment will pay off. This is the year 2006; what are you still using C for? C++ is designed to give you all the convenience I illustrated above at the absolute minimum cost for what is provided, as a result of the careful efforts of lots of very smart people. Plus, a hell of a lot more research is being done on optimizing C++ compilers these days. C has almost no advantages in terms of expressive power to the l33t h4xor optimizer any more (the 'restrict' keyword is one of them, but its application is limited and it shifts a serious burden of static proof-of-correctness onto the programmer). When do you think was the last time anyone touched your vendor's qsort() implementation?
Quote:Original post by OneMoreToGo
Standard cpp never compiles on my computer (I'm using standard gcc on a mac.) I've had this issue before, and so decided to use C.

However, if I change the C++, so that it is not like that found on the internet or in books (which I'm assuming is standard, simple c++) so that all my cout's and cin's have std:: before them, it works. Now, it's doing the same thing but with my ifstream's and ofstreams. Say this is my code:

<snip />

I would get these errors:

<snip />

And I'm not sure what they mean.

Thanks for any help you guys/gals can give me!


Did you actually read the error messages?

Quote:Your compiler
Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>

It's telling you what to do! The headers <iostream.h> and <fstream.h> are both deprecated. Use <iostream> and <fstream> instead. Then put std:: in front of your ifstream and ofstream definitions:
#include <iostream>#include <fstream>std::ifstream in_stream;std::ofstream out_stream;char some_variable;int main() {in_stream.open("test.txt");in_stream >> some_variable;std::cout << some_variable << std::endl;return 0;}


And just to prove how hard it is to write error-free C code Zahlman (who has way more experience than you do) made an error in a 13 line example program (his chrcmp function tries to dereference a void *), and I nearly made one earlier on a similar length example (in fact there may well still be errors in the C code I wrote earlier).

And I really don't understand what you mean by:
Quote:However, if I change the C++, so that it is not like that found on the internet or in books (which I'm assuming is standard, simple c++) so that all my cout's and cin's have std:: before them, it works.

What internet and/or books are you reading? Standard C++ uses namespaces and has done for the last eight years.

Σnigma
No luck, adding the std::'s and changing the header names has no effect, if I try std::basic_ifStream, like the errors say, I get told I'm missing arguments.

This is why I don't use C++. I'd rather be actually working and having to find more workarounds, then be stuck with problems with the simplest code.
Enigma, I tried your exact code, and it returns these errors:

/usr/bin/ld: Undefined symbols:
std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
std::basic_ifstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)
std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream()
std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()
std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream()
std::basic_ofstream<char, std::char_traits<char> >::~basic_ofstream()
std::ios_base::Init::Init()
std::ios_base::Init::~Init()
std::cout
std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)
std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)
___gxx_personality_v0
collect2: ld returned 1 exit status

*shrug*

Also, in response to your question:

The C++ book I have is "Problem Solving with C++", by Walter Savitch. I like the way it teaches, but it leaves out all these strange std:: tags which appear neccessary.

EDIT: Look: http://www.cplusplus.com/doc/tutorial/files.html

They don't use std::, but they're on the new headers? Could someone PLEASE explain this?

[Edited by - OneMoreToGo on June 1, 2006 5:18:07 PM]
Your problem is your compiler, not the language. How are you invoking the compiler? It looks like you're not linking the standard library.

If your C++ textbook doesn't mention namespaces then it doesn't matter how well written it is, because it's not teaching you proper C++. It would be a bit like a medical journal written by a Booker prize winner. I'm sure it would be a great read, but the information it contained would almost certainly be worthless. Get a new textbook.

<edit>
Quote:Original post by OneMoreToGo
EDIT: Look: http://www.cplusplus.com/doc/tutorial/files.html

They don't use std::, but they're on the new headers? Could someone PLEASE explain this?
Quote:http://www.cplusplus.com/doc/tutorial/files.html
using namespace std;

They have a using namespace declaration. A decent textbook would have taught you about this, as would an earlier tutorial at www.cplusplus.com.

</edit>

Σnigma
I added the namespace declaration, but no luck still. But no worries, I'll try resolving this on my own.

As for how I'm compiling it, I'm using GCC command line, with the simple invocation:

gcc test.cpp -o test

This has always worked before with C, perhaps cpp requires that I actually write in the framework inclusions?


I'll try an xCode C++ project next.


Thanks for all your help guys/gals!

You're great people!

EDIT: I also find it funny that these std:: things are now necessary, what purpose do they serve? I never needed them when I took two C++ coding courses 2 years back.

EDIT 2: Stuck it in an xCode project and I'll be darned, it worked. But the project does not appear to have any extra linking commands...

This topic is closed to new replies.

Advertisement