Link to home
Start Free TrialLog in
Avatar of Sketchy
Sketchy

asked on

Need help with a simple VC++ 6 console app with an output file (EASY)

Ok, here's a problem thats probably simple, but its driving me completely insane, and I thought some of you C/C++ whizzes would be able to help.

1) I start by creating a "Hello World" console application, using VC++ 6.0 (It's one of the options when creating a new project). The application is meant to be in C++.

2) I want to add to the application such that it opens a file, prints "You printed hello world" in it, and then closes the file.

3) I included iostream and fstream.h and then changed the MAIN function to:

int main (...) //can't remember default params at the moment =P
{
ofstream test;
test.open ("test.txt");
printf ("hello world");
test << "you printed hello world!";
test.close();
return(0);
}

For whatever reason, this just doesn't work!!! It says the ofstream is undefined, and then complains about all the test.* calls, so I figured I must be including wrong, or something. I was also getting an error about reaching the end of a preprocessor directive or something.

If anyone could do a SIMPLE program for VC++ 6 similar (takes all of 2 minutes) to what I've done that actually works, I would be greatful to be able to test it to see if it works on my computer.

Thanks in advance!
Avatar of jkr
jkr
Flag of Germany image

Did you

#include <fstream>

using namespace std; // <-- select the 'std' namespace!

?

That's all that I am missing from your code...

#include <stdio.h>
#include <fstream>

using namespace std;

int main (void) {

ofstream test;
test.open ("test.txt");
printf ("hello world");
test << "you printed hello world!";
test.close();
return(0);
}

should actually do it...
>>should actually do it...

Hum, it _does_ what you want, just checked it :o)

Compile as

cl HelloWorld.cpp -GX
BTW, 500pts is heavily 'overprized' for this kind of question...
Avatar of nietod
nietod

>> int main (...) //can't remember default params at the moment =P
The two standard choices for an ASCII console ar

   int main(void)

and

   int main(int argc,char *argv[])


>> 3) I included iostream and fstream.h
jkr fixed the problem, but didn't explain how it was fixed.

the main problem is that there is no official file called <fstream.h>   It is called <fstreanm>.   The file called <fstream.h> that ships with VC is a non-standard file that is supplied for legacy (old) code.   Stay away from it for new programs.  it is just to let old programs continue to work.  As you can see, it is not compatible with the modern STL files like <iostream>.

I have a prepared document that explains some more on this...
The official STL (Standard Template Library) files are all extensionless files, like <iostream>, <vector>, and <list>.  You may find that your compiler has files with these names but a .h extension, like <iostream.h>, <vector.h>, and <list.h> but these are not the standard files.  These files are old, non-standard files that are provided for compativbility for old programs that used them before the standard files were settled upon.  You want to avoid usign this files if you have the standard ones available.  The non-stnadard files may not have all the features of the standard ones, they also likely to have more bugs and other problems, and also since they are not standardized, they will varry from compiler to compiler, and might not even exist on many compilers.  So avoid using these files if you have the extenionless, standardized files.

Now there is one big difference between the standardized files and many of the non-standardized files.  The standardized files place all of their symbolic names in the "std" namespaces.  This is so that the names defined in these files don't clash with names you write in your program.  So in order to access the names inside the standard STL files you need to prefix them with "std::" like

std::vector<std::string> StringArray;

If you do not wish to use those "std::",  you can instead add a using directive like

using namespace std;

after you include the STL  include files.  Then these names will all be brought into your namespace.
jkr, if you ever lock questions anymore, you should lock this one.  At 500pts, I suspect that if you don't, someone else will!
>>At 500pts, I suspect that if you don't, someone else will!

I know - but what Is CS for? :o)

AND: I am simply pi***d by that ever ongoing discussion about locking Qs and people trying to force you to follow their opinion... or being called point-greedy... or whatever...
@ nietod:
| If you do not wish to use those "std::",  you can
| instead add a using directive like
|
| using namespace std;
|
| after you include the STL  include files.  Then these
| names will all be brought into your namespace.

Bjarne Stroustrup strongly discourages the use of the 'using namespace'-directive. I don't have his exact words at hand, but he states something like: "if you ever have to use it, keep it as local as possible", i.e. you certainly don't use it right after you include stl-files.
>> Bjarne Stroustrup strongly discourages the use of the 'using namespace'-directive.
 Admittidly it can be used incorrectly and lead to errors.   The same can be said of virtually all features in the language, including say, an if statement.    As with all features of the language, you must learn their advantages and dissagvantages and then consider them and their alternatives for every situation.  

If you have 500,000 line C program that you are converting to C++, its probably best to use a using directive to get the C standard library functions in the global namespace.  Otherwise there will probably be millions of errors from all the C standard library functions and data types that are now hidden in the std namespace.

However there are times when its not appropriate to use a using directive.   You might notice that I specifically mentuoned an specifying the fully qualitifed names in comments.  In fact, I mentioned it before I mentioned the using directive.

>>  "if you ever have to use it, keep it as local as
>> possible", i.e. you certainly don't use it right after you include stl-files.
that seems very unlikely.   Why would that location be worse than another?
Agreed, if you have a large scale project AND time is of the essence then using the "lazy" [as Strourtup actually calls it] 'using namespace std;' is a way to get things going with very little effort. On the other hand using some sort of 'replace all'-functionality will also quite efficiently lead the goal. But since porting an application from c to c++ involves rewriting large portions of the code anyway I can live with this type of scope resolution as long as it's considered to be more or less temporary.

However, Sketchy clearly isn't porting anything. On the contrary, he is just beginning with a completely new project. In this case you shouldn't suggest using the ugly and error-prone 'alternative', even if you precede it with the correct way of doing this.

Whether it seems unlikely, improbable or plain impossible to you doesn't invalidate Stroustrup's recommondation. The whole thing has to do with ambiguity. In short, the more global the 'using namespace'-directive is, the more possibilities there are that the compiler will come across objects that exist in both namespaces. With no explicit namespace-resolution it will have to use its own rules to resolve the ambiguity which might not be what the developer meant. I.e. no errors during compilation and the developer also can't find anything wrong with the code, but the runtime-behaviour isn't as expected. Now this is one of the hardest bugs to track down. So to narrow down the possibility of such bugs keep the implicit namespace resolution as local as possible. Better safe than sorry.
>> But since porting an application from c to c++ involves rewriting
>> large portions of the code anyway
Often it requires few changes other than changing the header file names and adding a using directive for std.   That is often enough to get most of the code to compile (and in virtually all cases if the code compiles, it will work correctly--if it worked correctly in c).

>> I can live with this type of scope resolution as long as it's considered to be more or less temporary
I usually prefer to see it that way for a huge namespace, like std.  but small namespaces as well as namespaces whose contents are unlikely to change may have little harm and may make the code more readable (a matter of opinion)   Although not using the directive can help a programmer "locate" identifiers when multiple libraries (and hence namespaces) are  used.

>> In this case you shouldn't suggest using the ugly and
>> error-prone 'alternative', even if you precede it with the
>> correct way of doing this.
That vast majority of programmers do place std in the global namespace.  Just look at few books and articles.  You need to understand both.  Understand the advantages and dissadvatages.  Then make the appropriate choice.

>> Whether it seems unlikely, improbable or plain impossible to you
>> doesn't invalidate Stroustrup's recommondation.
I have read quite of lot of Stroustrup's opions on this, both positive and negative.  I don't recall anything that specifically states that the using dirrective should not be placed right after the STL files.  That seems like rediculous advice and he wouldn't state it.  What about

#include <fstream>

void somefunction() {};

using namespace std;

int main()
{
    fstream fil;
    return 0;
}

Does the position of the using directive seriously effect anything?

Do you have soe sort of quote from him to this effect?

>> The whole thing has to do with ambiguity.
Not really.  The rules governing name lookup are well defined.   If a name is made ambiguious the code will fail to compile.  

>> In short, the more global the 'using namespace'-directive
>> is, the more possibilities there are that the compiler will come
>> across objects that exist in both namespaces.
That is not necessarily a problem.  If the identifiers in a namespace are well known then a programmer can choose not to use them in his/her namespaces.  Of course problems can arrise when the identifiers are not well know or when they may change over time.   In most small libraries they are likely to be well know..  In a large library less well know.   std is sort of an exception, while it is large, its names tend to be well known, so its sort of in a gray area.   Its also in a gray area in terms of changes over time.   While identifiers are likely to be added in the future, the number is probalby minimal and there are reasonable guesses as to what they are, like hashmap.

>> With no explicit namespace-resolution it will have to use its
>> own rules to resolve the ambiguity which might not be what
>> the developer meant. I.e. no errors during compilation and
>>the developer also can't
If there is ambiguity, the code won't compile.  You won't get a run-time error, you will get a compiler error.  
              find anything wrong with the code, but the runtime-behaviour isn't as expected.
Avatar of Sketchy

ASKER

The code posted by JKR doesn't work on my system.  I get the error:

fatal error C1010: unexpected end of file while looking for precompiled header directive

The error points to the closing brace of the main function.

I just did a direct copy/paste of the code here, which pretty much only changed <fstream.h> to <fstream>.

I'm not sure what the heck the problem could be, I have a real copy of VC++ 6 (Intro), not warez or anything that could make it busted.  
>>fatal error C1010: unexpected end of file while looking for precompiled header directive


Make it read

#include <stdafx.h> // <-- this one was missing
#include <stdio.h>
#include <fstream>

using namespace std;

int main (void) {

ofstream test;
test.open ("test.txt");
printf ("hello world");
test << "you printed hello world!";
test.close();
return(0);
}

I forgot that you were using a generated project. But, as I wrote,

cl HelloWorld.cpp -GX

would have made that unnecessary...

First of all, change the first include file to <cstdio> like

#include <cstdio>
#include <fstream>

using namespace std;

etc

Then go to your project settings.  (project menu).

In the dialog, switch to the "C/C++" page tab

In the "category" list choose "precompiled headers"

If automatic headers (radio button) is selected, make sure the "through header" box is blank or specifies a header file you are actually using.

Otherwise turn off use of precompiled headers (for now anyways).
First of all, change the first include file to <cstdio> like

#include <cstdio>
#include <fstream>

using namespace std;

etc

Then go to your project settings.  (project menu).

In the dialog, switch to the "C/C++" page tab

In the "category" list choose "precompiled headers"

If automatic headers (radio button) is selected, make sure the "through header" box is blank or specifies a header file you are actually using.

Otherwise turn off use of precompiled headers (for now anyways).
| Often it requires few changes
I guess we are using different interpretations of the term 'porting' then. While you are happy with just having it compile with a c++-compiler, I believe that using c++ calls for a completely different set of programming paradigms, thus having to redesign and reimplement mostly everything.

| That vast majority of programmers do place std in the global namespace.
And even if I was the last man on earth to not use it, I'd rather be safe than sorry. IMHO it also improves the readability of code. A 'std::sort' vs. 'sort' leaves no questions as to where the sorting-routine comes from, right?

| That seems like rediculous advice and he wouldn't state it.
"The C++ Programming Language" section 8.2.2/8.2.3, however ridiculous that may seem to you. Concerning your code sample (which actually doesn't make much difference since you didn't take the 'using'-directive out of the global scope) he would suggest something like:

#include <fstream>

void somefunction() {};

int main() {
    using std::fstream;

    fstream fil;
    return 0;
}

| If there is ambiguity, the code won't compile.
Two types of ambiguity: From a compiler's point of view and from a human perspective. I was talking about the latter. If there are two objects with the same definition that are brought into the same namespace the compiler *DOES* resolve this ambiguity using its own set of rules and *WILL* compile.
>>  guess we are using different interpretations of the term 'porting'
>> then. While you are happy with just having it compile with a
>> c++-compiler,
Actually no.  I diffinitely agree with you on that.   The rest of the world--especially those paying to have things ported--use a much more narrow term.

>>  A 'std::sort' vs. 'sort' leaves no questions as to
>> where the sorting-routine
>> comes from, right?
For many programmers there is absolutely no question where "sort",:"string", vector", "map", "fprintf" etc comes from.  They would no more create idenifiers like that in their code than they would "new" "if" or "while" etc.  

>> "The C++ Programming Language" section 8.2.2/8.2.3,
>> however ridiculous that may seem to you.
Can you post the exact part.  I still don't see any location where he says not to use it right after including the STL headers.

>> If there are two objects with the same definition that are
>> brought into the same namespace the compiler *DOES*
>> resolve this ambiguity using its own set of rules and *WILL* compile.
No, in most cases it doesn't compile.   (I'm not sure of the exact situations you are reffering to.)   You can hide declarations in the global scope and get it to compile, but you can also do this with an ordianry local variable.    But if you have a real name clash you will not get it to compile.
1.) ok

2.) so I'll have to use less obvious examples in the future, otherwise you'll keep responding that it is obvious?

3.) no, I never quoted him like that - his point was on using it as local as possible, while putting it right after the #include makes it almost as global as possible. If you look closely at the code sample I provided and compare it to yours you'll see that my version makes the 'using'-directive more local in two ways: it is only active within the main-function and doesn't affect any class or function outside; it only affects those objects that are actually being used.

4.) That's what I was talking about when calling it an 'ambiguity from a human perspective': You have two objects (fxn or class) 'example_obj' with the exact same declaration, one declared in global namespace and one declared in namespace 'this_is_an_example'. Next you put 'using namespace this_is_an_example;' in your code before instantiating the object in question using 'example_obj which_one_is_it;'. This code *WILL* compile as the compiler uses its set of rules to resolve this 'conflict'. Clear enough?
I don't get the "obvious" stuff?  I didn't say anything was obvous.

>> 3.) no, I never quoted him like that
I guess I missunderstood you.  I thought you were saying he said   " i.e. you certainly don't use it right after you include stl-files." which seemed unlikely--and indeeded he didn't.

>> You have two objects (fxn or class) 'example_obj' with the
>> exact same declaration, one declared in global namespace
>> and one declared in namespace 'this_is_an_example'.
>>Next you put 'using namespace this_is_an_example;'
Except this has nothing really to do with namespaces.   Any local declaration will always hide a global one.  This is true without namespaces.   The "problem" is with using globals, not with using namespace directives.

i.e.

int i

int main()
{
   i = 0  // ::i;
   int i // placed in by mistake
   cout << i; // Opps main::i;  
};
> I guess I missunderstood you.
Can't help you on that. If you don't care about quotation-marks you are likely to get confused again in the future.

> Except this has nothing really to do with namespaces.
It doesn't have to do with namespaces exclusively if you prefer to put it this way. On the other hand it's kind of a naive argument to say: "Oh well, you can **** up your code with global variables anyway, so why care about keeping them namespaces seperated?"
And like you correctly stated: "The \"problem\" is with using globals [...]". So why fake objects to be global with the 'using'-directive when it introduces "problems"? You commented your second 'int i;' as being there by mistake -- why aren't you equally consistent when it comes to namespaces?
Sketchy,

apart from the ongoing discussion - did that help?
>> "Oh well, you can mess up your code with global variables anyway,
>> so why care about keeping them namespaces seperated?"
No, that is backwards, the source of the problem is the use of the global.  No matter what you do with namespaces, if you have th global you have the problem.  Avoiding the global fixes the problem, not matter what you do with namespaces.  

>>  So why fake objects to be global with the 'using'-directive
>> when it introduces "problems"?
It doesn't introduce problems.  The use of the global introduces the problem. You still get the problem without the using directive.

>> You commented your second 'int i;'
>> as being there by mistake -- why aren't you equally
>> consistent when it comes to namespaces?
You can make that mistake with or without using namespace directives.  Thus the problem isn't associated with using namespaces directives..   The problem is with globals.  
Sketchy, do you have any further problems with

include <stdafx.h> // <-- this one was missing
#include <stdio.h>
#include <fstream>

using namespace std;

int main (void) {

ofstream test;
test.open ("test.txt");
printf ("hello world");
test << "you printed hello world!";
test.close();
return(0);
}

?
Avatar of Sketchy

ASKER

Nope, it worked.  Now I'm trying to implement it as a class, but that's opening a whole other can of evil C++ OO worms.

Thanks for all your help peeps, it was greatly appreciated.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>so that we can PAQ it :o)

Should actually read "move it to the PAQ area" :o)
Sketchy,
On really compicated questions like these, it is customary to award a small bonus, such as 300 or 325 points, to each Expert who contributed unrelated inanities and frivolous banter.

I just thought you might like to know the proper etiquette.

-- Dan
>>On really compicated questions like these

What a cynism :o)

Comment
From: jkr  Date: 06/10/2002 10:04AM PST  
BTW, 500pts is heavily 'overprized' for this kind of question...