c++ fstream file i/o

Started by
4 comments, last by Vopisk 18 years, 2 months ago
Hey, I'm trying to extract values from a file to insert them into int variables. I'm using the following code:

cout<<"\nEnter the name of the input file and press <Enter>:";
   cin>>filename;
   iFile.open(filename.c_str(),ios::in || ios::beg);
   
   while(!iFile.eof()){

		iFile >> beg;
		iFile >> end;
		cout << beg + "\n";
		cout << end + "\n"; 

   }
The file I'm reading from looks like this: 3 16 18 22 So through the first time in the loop beg would equal 3 and end would equal 16. I'm trying to print the value to see if it works but it doesn't :( I am new to c++... In my program we've only worked with Java and now I'm forced to use c++ because it's closer to the native language then Java is (it also has pointers etc, etc...) Any help works :) thanks Seb
Advertisement
Quote:Original post by sanch3x
		cout << beg + "\n";		cout << end + "\n"; 



Your problem is probably these lines. You should use the << operator instead of the + operator. Also, rather than printing "\n", you should use endl. Like this:
		cout << beg << endl;		cout << end << endl; 


Also, in the future, you should go into more detail about what is wrong. "It doesn't work" is rarely sufficient.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
'+' doesn't work with strings the way you want it to in C++. Actually, double-quoted strings in C++ aren't even really strings: they are pointers to some static character array built into the executable, whereas the standard library provides an object std::string that is much more like what you are used to using (actually it is mutable, so it is more like a java.lang.StringBuffer; but it doesn't offer general Java niceties like being derived from a common Object class).

The << symbol is just an operator here, which makes use of C++'s operator overload mechanism. 'std::cin' and 'std::cout' are global object instances, in the std:: namespace, similar to how Java System.in and System.out are static members of the System class. For objects of this 'stream' type, the operator is defined to read/write the value and then return the same stream object (i.e. the left-hand side) - though naturally the stream object's internal state will have changed.

So what we do in C++ to output or input multiple items is 'chain' the operator: we write things like "cin >> foo >> bar", where "cin >> foo" gets evaluated first, altering foo as a side effect and then returning cin, so that we can then read in bar in the same way.

Also, when you output, you need to "flush" output streams manually, because they are buffered internally. This is lower-level, but gives you better control and the chance for better I/O performance (and we all know how slow I/O is) because you can wait for a proper 'chunk' of data to accumulate before flushing it.

The 'stream manipulators' std::endl and std::flush can be used for this purpose. std::flush is "outputted" onto a stream in order to flush it. std::endl is effectively equivalent to '\n' followed by std::flush.

By the way, if you're from a Java background, you should (a) know enough to initialize objects when you know what their initial state will be, and delay their construction to the middle of a scope; and (b) have a little better taste in variable names (write words in full; there are some misguided people BTW who would interpret that lowercase 'i' as Hungarian notation).

cout << "\nEnter the name of the input file and press <Enter>:" << flush;cin >> filename;ifstream inputFile(filename.c_str(),ios::in || ios::beg);while(!inputFile.eof()){  inputFile >> beg >> end;  cout << beg << '\n' << end << endl;} // for example. You could flush at the end of the loop instead// The buffer will automatically flush anyway when it would overflow, but// the size of that buffer is an implementation detail, and you want to make// sure that any leftover stuff is flushed, so you'll need to do at least the// one flush. I put it inside the loop to demonstrate the use of endl instead// of flush.

Thanks guys I got it to work. It was in fact the cout line.

I'm sorry for not following coding etiquette when it comes to OOP but I'm frustrated enough as it is just trying to figure out how to get this to work to worry about certain details. (for example: I don't even know what the Hungarian notation is - googling now...)

It's the whole navigating through file streams that I find increasingly difficult. Just going to a certain position in my file, printing the character, and then replacing it with an 'X' (although very simple) I find impossible.

Once I figure how to work things I'll clean up my code so I can get this darn assignment corrected without confusing my prof too much. I've always hated university, so much theory so little practice...

Yes yes, I can practice on my own but with assignments due and the likes it's not always possible.

Thanks again.

edit: Hungarian notation is a set of conventions, first proposed by Charles Simonyi in 1974, that may be used to name variables, procedures, and other quantities in programming using their types and possibly a standardized ending. A good description of the original conventions can be found here.
Quote:Original post by sanch3x
It's the whole navigating through file streams that I find increasingly difficult. Just going to a certain position in my file, printing the character, and then replacing it with an 'X' (although very simple) I find impossible.


Yeah, files aren't designed to work this way. They're not random-access things. Anything you might have done with java.io.RandomAccessFile (?? I think that's it) is really working with a wrapper that's keeping part or all of the file in memory, making edits and saving it back. Normally, to keep things simple, you do just that with the whole file: read it all in somewhere, edit the appropriate data, and write it back.

// Something vaguely like this (assuming you want binary I/O):#include <iostream>#include <algorithm>#include <vector>#include <iterator>using namespace std;//...ifstream f("foo.txt", ios::in | ios::binary);vector<char> allFileData;copy(istreambuf_iterator<char>(f), istreambuf_iterator<char>(), back_inserter(allFileData));allFileData[42]='X'; // assuming you know there is that much data.f.close();ofstream f2("foo.txt", ios::out | ios::binary);copy(allFileData.begin(), allFileData.end(), ostreambuf_iterator<char>(f2));


Quote:edit: Hungarian notation is a set of conventions, first proposed by Charles Simonyi in 1974, that may be used to name variables, procedures, and other quantities in programming using their types and possibly a standardized ending. A good description of the original conventions can be found here.


And now that you know, you'll probably want to avoid most or all of it. :)
For clarification, make sure that you only use a single pipe character ( | ) when seperating flags in File I/O streams.

That's all I have to add seeing as everyone else already solved the problems and gave such good advice. :)

Vopisk

This topic is closed to new replies.

Advertisement