Input file stream: "Incomplete type is not allowed"

Alright support personnel,

Going through my file streams and I am intending to open a file for reading integers as the exercise details..... well I'm using the book's example and I get an error saying that "Incomplete type is not allowed." The lines of code are simple and are as follows: (I'm using VisStudio 2015 as the environment...)

1
2
3
4
5
  std::cout << "Please enter your input file name==> ";
  std::string input_file;
  std::cin >> input_file;
  std::ifstream ifs{input_file};  //it is THIS line that is generating the error
  if (!ifs) error("can't open input file!");


So I am just learning streams again and I realize this does NOT use explicit "open" or "close" commands because the good Dr. says you shouldn't have to use explicit commands (not all the time at least!) and implicitly opening a file will allow the scope of the program block to close the file when finished - he says implicit opening is easier for "housekeeping" due to not having to keep track of what is open and what is closed.

With that said, anyone have a clue as to why VS 2015 is throwing a fit? I'm taking this right out of his book so I'm at a loss as to why this is choking....

Also, in VS 2015 the file I'm going to open: "input_file"..... will it ask me for a path to this file or do I have to put this in the "resource" folder to begin with or some other location inside the project?

Xanadu
You're missing <fstream>. :-)

And it's not that you shouldn't use explicit open and close commands. It's the more basic principle of initializing variables at the point of their definition whenever possible. And why break it into two statements?

As for finding the default directory when you run your program from the IDE, try running this, giving a unique filename, and then look for it in the project directory structure. That will be your default directory. Alternatively, calling system("dir"); in the code would presumably tell you where you are. In Linux we could say system("pwd"); to "print working directory", but I don't know the windows equivalent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::cout << "Filename: ";
    std::string filename;
    std::cin >> filename;
    std::ofstream out {filename};
    if (!out) {
        std::cerr << "Cannot open file.\n";
        return 1;
    }
    out << "Here I am!\n";
}
Last edited on
I have never seen someone use "{}" for initializing a stream constructor. It is a useful tool in preventing casting for things like int and float, but I don't see the point for strings (maybe to preven't C-Strings from mixing?).

And yes I checked the signature and that seems to be the case:
explicit ifstream (const char* filename, ios_base::openmode mode = ios_base::in); (not sure if this changed beyond C++11).

edit: oh it turns out that this sites C++11 ifstream page is wrong, Cppreference says that in C++11 they included std::string as an constructor.

It seems like perhaps the reason why you don't have a "undefined reference" error is because iostream might have forward declared fstream or something like that?
Last edited on
Thank you Dutch,

Right as always..... I did NOT have the correct <fstream> in the header. So that made ALL the difference of course. Much appreciated.

I think I know what the default directory is for the project so I will do as you say just to test this for my project and make sure it ends up where it should.

Question, does the file have to have an extension when you name it in the code (for example: input_file.txt) or JUST the name (as you see in my code above)?

Does the file have to be a certain TYPE of file (text, XML, etc. whatever? - I prefer text since it is simple to create and use and inspect of course) and do I have to put it into the project as a "resource" and let the project have knowledge of its existence?

Xanadu
Dutch and all who are slightly interested.....

Turns out you need to do 3 things inside Windows VS2015 for reading files (of the text version)…..

1.) You need to include the file in the root directory of the PROJECT itself and it MUST be the root

2.) You need to include the file INTO the project inside of VS2015 (I placed my as a source file) and also inside of the properties of that file (right clicking it) you must choose "include as content"

3.) Finally you MUST include the full file name WITH extension for the file to read or you get errors.

just FYI if any were wondering.....

Xanadu
Yes, if you want ".txt" on the end of a filename then you need to append it yourself (or beg the user to enter it that way).

But whether or not you append ".txt" to the end of the filename, the file is basically a "text" file, since that's what's inside it. For instance, you would probably want to open it in "text" mode when reading from it. Opening a windows text file in "binary" mode exposes the extaneous '\r' before every '\n' (which are hidden from you in "text" mode).

There's no way you need to include a file in your project in order to use it as an input (or output) file. That simply cannot be correct.
Dutch,

Agree totally that the text file will function as a text file regardless of the extension since that was how that file was defined.

My point was merely that if I only typed "input_file" rather than "input_file.txt" for some reason VS did not like this and simply said it failed to open the file. (not sure if this is due to a setting or what have you...???) but it would seem that if you don't include the extension (regardless of whatever that extension is... .txt, .inf, .a$$ or what have you...) it seemed to simply ignore the file and not open it. Not sure if this is an "absolute" in VS or whatever but I'm just reporting how it seemed to function.

I'm no expert in VS by any means and I'll take your word that the file doesn't need to be included in the project. I'll try what you are saying and let you know but I believe I already tried this and it seemed to make a difference...… or I could simply be in error. But I'll let you know what I find.

Xanadu
Dutch,

You are correct...… my point #2 above is incorrect as you stated. Still functioned correctly WITHOUT including the file into the project proper. So I was simply wrong about having tried this.

Now that I did...….. it shows the project doesn't need to have any "fore-knowledge" or inclusion of this file before use.

I stand corrected.

Xanadu
I'm no expert in VS

I know nothing about VS. It just seemed like madness to me. :-)


it would seem that if you don't include the extension it seemed to simply ignore the file and not open it

The extension is just part of the filename and is not special. You need to supply the entire text of the filename for it to match the filename text stored in that directory. It's that prosaic. Any specialness of the extension is simply a matter of the programs that work on files with that extension reading and writing them in certain formats. Also you can generally register programs with the OS shell to open a given file type when clicked. E.g., playing an mp4 by clicking on it causes the OS shell to look up the associated program and run that program with the mp4 as its input file.

As for file types in general, they exist on a couple of different levels.

The lowest level is chosen by how you open it, either in "text" or "binary" mode. In binary mode, you see the raw byte stream of the file. In text mode, there may (or may not!) be a level of "translation" of the input into the stream of characters that you actually see, and a level of translation back into the text format that the system uses.

In *nix, there is no difference between text and binary modes, so you always see the raw byte stream (but you should use the correct opening mode for portability). In windows, on output '\n' is written as '\r' followed by '\n', while on input, '\r' followed by '\n' is read as '\n'. This presents a problem reading windows text files on *nix since they seem to contain extraneous '\r' characters before every '\n'. (We write them to a temporary file and sell them back to MS.)

Anyway, there is more to be said -- Apple's old '\r', DOS ctrl-z, weird mainframe formats -- but that's about it for text vs binary mode. It's more annoying than useful.

The second level of file types, which may best be called "file formats", exists on top of the text/binary distinction. The operating system generally knows nothing about these formats. It's up to you to impose them on the file while writing and interpret them correctly while reading, in either the lower-level text or binary mode.

A text file format may be very loose. It could simply be "a sequence of characters". Or a "sequence of tokens/words/numbers". Or a "sequence of lines".

On top of the line-based format we could have another level of structure where each token in the line represents the values for contiguous fields in a struct. Clearly the order of values is important here, and therefore part of the file format. We could describe this overall format as a line-based text file with one struct per line with field order: a, b, c, etc. But do we ignore blank lines or are they an error? Are comments allowed, say after a # character? That's part of the file format, too, since the files that process it need to deal with that stuff.

Anyway, I've already gone on too long, but two final points about file-type information inside the file itself.

Firstly, there's the interesting case on *nix where a text file (with it's "execute" bit set, a technical detail) can be run like a program based purely on information inside the file (not on a program being "registered" in a system database). The OS looks at the first two bytes and if they are #! then the rest of that line (details vary) is used as the command to run in order to process this text file. If the text file contains text in a scripting language and the program name after the #! is it's interpreter then "executing" the text file is the same as executing the interpreter program with the text file as an input file. And since *nix scripting languages use # as the comment character, the first "magic" line is ignored by the interpreter program.

It's also interesting to note that binary files sometimes have a special first few bytes that identify the file type. Here's a list of a few. The hex represents the bytes; the characters are what they look like in ascii (with . meaning non-printable).

bmp:  42 4D                    BM
ELF:  7F 45 4C 46              .ELF
flac: 66 4C 61 43              fLaC
gif:  47 49 46 38 39 61        GIF89a
mp3:  FF FB
mp3 with ID3v2 container:
      49 44 33                 ID3
MZ executable:
      4D 5A                    MZ
pdf:  25 50 44 46 2d           %PDF-
png:  89 50 4E 47 0D 0A 1A 0A  .PNG....
UTF-8 encoded Unicode byte order mark:
      EF BB BF
wav:  52 49 46 46 ?? ??
      ?? ?? 57 41 56 45        RIFF....WAVE
zip:  50 4B ?? ??              PK..


The png signature is particularly well-designed, with it's initial byte with the high bit set, two different line endings (0D 0A and 0A), and even ctrl-z (1A): http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
Xanadu4ever wrote:
Turns out you need to do 3 things inside Windows VS2015 for reading files (of the text version)…

Er, not quite; what follows is true of any compiler/system (and not unique to VS or Windows).

1) In order to open a file you must provide either:
    • A full path name
    • A path relative to the current working directory
When you run your program from VS the CWD will be your project root.

2) You only need to include the file as part of the project if the project/build options require it (listing it as a dependency). Otherwise it is just as good as any other file on the system (for which you have read privileges), and your program will be able to open it.

3) Again to point 1: you can only open a file if you give a correct file name. Changing or omitting the file extension will not open the file as it is not the file’s name.

Hope this helps.
Thanks Gentlemen.

Really appreciate the extra details you gave for files Dutch and the differences between the *nix systems (wish I had those instead of Micro-sloth! Maybe I'll make the switch??) and MS OS systems.

A lot of details there I had no idea about and probably will run into sooner than later. Maybe you are preparing me for the inevitable??

Anyhow, I'll consider this problem solved and will be posting more (I say this with inevitable sadness - but that's how you learn so I know I will be screwing stuff up with the next problems!!) for the next exercises that I'll be working on this week.

After this week and maybe next I start GUI's! Should be exciting to see the errors I generate with that stuff!

Xanadu
Topic archived. No new replies allowed.