0

I am just learning the very basic aspects of input/output streams, and can't seem to have my program read a text file. It gives me errors that indicate it is trying to read the .txt file as C++ code, while I am just using values in there to test my stream.

These are the contents of my included .txt file:

12345
Success

And here is the main program's code:

#include <fstream>
#include <iostream>
#include "C:\Users\Pavel\Desktop\strings.txt"
using namespace std;

int main (int nNumberOfArgs, char* pszArgs[])
{
    ifstream in;
    in.open("C:\Users\Pavel\Desktop\strings.txt");
    int x;
    string sz;
    in << x << sz;
    in.close();
    return 0;
}

The first error message I receive is "expected unqualified-id before numeric constant" which tells me the program is attempting to compile the included file. How can I prevent this and have the text file read as intended?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

3 Answers3

8

Don't #include your .txt file. Includes are for source code. They textually insert the file into your code, as if you had actually copy-pasted it there. You shouldn't be #includeing a file you're opening with an ifstream.

John Calsbeek
  • 35,947
  • 7
  • 94
  • 101
2

Opening files on the filesystem at runtime doesn't require any mention of that file's name in the source code. (You could, for instance, ask the user for a filename, and then open it just fine!)

The case where you might #include data in your source would be if you wanted to have that data embedded into the executable of your program (and thus not rely on a file that was on the filesystem when running). But to do that, you have to format your file as a valid C++ data declaration. So it would not be a .txt file at that point.

For instance, in strings.cpp

#include <string>

// See http://stackoverflow.com/questions/1135841/c-multiline-string-literal
std::string myData =
    "12345\n"
    "Success";

Then in your main program:

#include <iostream>
#include <sstream>
#include "strings.cpp"
using namespace std;

int main (int nNumberOfArgs, char* pszArgs[])
{
    istringstream in (myData);
    int x;

    // Note: "sz" is shorthand for "string terminated by zero"
    // C++ std::strings are *not* null terminated, and can actually
    // legally have embedded nulls.  Unfortunately, C++ does
    // have to deal with both kinds of strings (such as with the
    // zero-terminated array of char*s passed as pszArgs...)
    string str;

    // Note: >> is the "extractor"
    in >> x >> str;

    // Note: << is the "inserter"
    cout << x << "\n" << str << "\n";

    return 0;
}

Generally speaking, just #include-ing a source file like this is not the way you want to do things. You'll quickly run into trouble if you do that in more than one file in your project (duplicate declarations of myData). So the usual trick is to separate things into header files and implementation files...including the headers as many times as you want, but only putting one copy of the implementation into your build process.

1

An #include directive works the same way regardless of the extension of the file being included - txt, h, no extension at all - it doesn't matter. How it works is the contents of the file are pasted into your source file by the preprocessor before that file is passed to the compiler. As far as the compiler is concerned, you might as well have just copied and pasted the contents yourself.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • *"As far as the compiler is concerned, you might as well have just copied and pasted the contents yourself."* -- Technically true, but the devil is in the details. For instance, `__FILE__` will report the name of the `#include`d file, but if you pasted the contents it would evaluate to the name of the formerly-`#include`ing source. :-/ (A fine distinction between "as far as the compiler is concerned" vs. "as far as the preprocessor is concerned", just worth mentioning.) – HostileFork says dont trust SE Jul 11 '12 at 18:19