LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-31-2006, 06:14 AM   #1
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Rep: Reputation: 0
Unhappy C++ ifstream: Problem reading a file


I am using ifstream to open a file, read a string then open a file which has that string in it.

for example:

I open "allroad.con" which has, say, "Bonavista" in it. I then open a file called "Bonavista.con". The problem is when I open Bonavista.con (I used is_open() to confirm that opening worked) the first read I try fails. I know the number 4 is on the first line so use inData >> a; where 'inData' is my ifstream and 'a' is an int.

Any ideas why the read is failing? It works fine for the first file which is almost exactly the same.

Here are a few lines, "routeName[i].getName()" gets the name say "Bonavista". I had to do some string-char conversions because using getline I get a std string so I converted it because inData.open cannot use a std string.

string file = "c:\\Wxsystem\\Roadgram\\Commands\\";
file = file + routeName[i].getName() + ".con";

inData.open(const_cast<char*>(file.c_str()));

if (!inData.is_open()) {
Error(file+" failed to open");
return -1;
}

inData >> a;
if (inData.fail()) {
Error(file+ "\nFailed to get number of grid points");
return -1;
}

//THIS LAST ERROR COMES UP.
 
Old 01-31-2006, 08:31 AM   #2
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
> inData.open(const_cast<char*>(file.c_str()));
you dont need the const_cast.. just use file.c_str() .

>> Any ideas why the read is failing? It works fine for the first file which is almost exactly the same.
its logic somewhere else .. inData.fail() is saying that the read operation failed.. which probably in this case means you are opening the wrong file or the file is empty?

if needed post some surrounding code for testing..
 
Old 01-31-2006, 09:14 AM   #3
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Does the first file have a space after the int in the file and the second doesn't? I think variables have to be seperated by spaces to use this.

Last edited by dmail; 01-31-2006 at 09:20 AM.
 
Old 01-31-2006, 09:43 AM   #4
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
Quote:
Originally Posted by dmail
Does the first file have a space after the int in the file and the second doesn't? I think variables have to be seperated by spaces to use this.
i wondered about that also.. but tested and the char delimits the int read..
i tested '123hello' and 'inData >> a;' grabs the int without a problem..
 
Old 01-31-2006, 01:09 PM   #5
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Original Poster
Rep: Reputation: 0
4 (gridpoints)
Bonavista to St. John's
437 237 A Near St. John's
434 233 B Near Whitbourne
429 234 C Near Clarenville
428 240 D Near Bonavista

that is what is exactly in the file.
the first line of the first file I read is "4 (number of routes)"

xhi-> when I remove const_cast do I still need the <char*>?
 
Old 01-31-2006, 01:13 PM   #6
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Original Poster
Rep: Reputation: 0
I took out const_cast<char*>...works but same error still.
Will not take in the value.
I also tried getline(inData,nextLine); nextLine being a string, but it wouldn't even take in the string. I also diverted the program to read another file with just "8" in it. and it wouldn't take the "8" in.
 
Old 01-31-2006, 01:17 PM   #7
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Original Poster
Rep: Reputation: 0
I just went to the extreme and tried to open the file I previously opened and that never even worked. I took out the

inData.open(const_cast<char*>(file.c_str()));

and replaced it with:

inData.open("c:\\Wxsystem\\Roadgram\\Commands\\AllRoad.con");

that means the file isn't the problem, Right?
 
Old 01-31-2006, 01:34 PM   #8
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
file permissions? are they good for the program to read.. i would think there is some problem with the file because .. somthing like
Code:
ifstream in("afile.file");
int gridpoints;
in >> gridpoints;
should work on the example file you posted.

though it would not have to be the file could be the code.. can you post some code?
 
Old 01-31-2006, 02:31 PM   #9
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
Quote:
Originally Posted by BenScaplen
xhi-> when I remove const_cast do I still need the <char*>?
const_cast<T>(x) is a parameterised operator. It takes a value, x, and changes it to type T by adding or removing const.

You can't just write (<char*>), because it would have no effect; you are trying to refer to a char* specialiation without a template.

std::string::c_str() will get you a pointer to the string of type const char*, which should be suitable for passing to ifstream:pen(const char *s, std::ios_base:penmode mode = std::ios_base::in);

So if this doesn't work:

inData.open(file.c_str());

Then you have a far more serious problem (possibly a bug in your compiler's implementation of the standard libraries). [Edit: This problem may or may not be related to the problem in your post].

[Edit: This is wrong:

In fact, I don't think you even need the .c_str(), because there's an implicit conversion to const char* in std::string, so you should be able to say:

inData.open(file); ]

Last edited by rjlee; 01-31-2006 at 03:09 PM.
 
Old 01-31-2006, 02:38 PM   #10
xhi
Senior Member
 
Registered: Mar 2005
Location: USA::Pennsylvania
Distribution: Slackware
Posts: 1,065

Rep: Reputation: 45
Quote:
In fact, I don't think you even need the .c_str(), because there's an implicit conversion to const char* in std::string, so you should be able to say:

inData.open(file);
no you cannot..
Quote:
because there's an implicit conversion to const char* in std::string
there is ?

Quote:
possibly a bug in your compiler's implementation of the standard libraries
or possibly a bug in the way the code (which we have yet to see the extent of) is written.

Last edited by xhi; 01-31-2006 at 02:40 PM.
 
Old 01-31-2006, 02:59 PM   #11
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
C++ has a "default" conversion from char * to string but not the other way around that I'm aware of and so yes the c_str() or data() methods are required.

It is very unlikely that there is a bug in the compiler, possible a corrupt installation but that is quite different.

But check the file permissions and maybe post a little more of the code.
Which OS are you using?
cout the file.c_str(); what do you get?
 
Old 01-31-2006, 03:07 PM   #12
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
Quote:
Originally Posted by xhi
there is ?
Sorry; I mis-read that. You're right, you do need .c_str(). My mistake.
 
Old 01-31-2006, 07:08 PM   #13
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
The following complete program opens a file named allcon.con, reads a filename from the file, closes the file, then opens a file using the name that was read.

allcon.con:
Code:
bonavista.con
bonavista.con
Code:
4 (gridpoints)
Bonavista to St. John's
437 237 A Near St. John's
434 233 B Near Whitbourne
429 234 C Near Clarenville
428 240 D Near Bonavista
The complete source code of the program:
Code:
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>

using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
using std::string;

static string get_name_of_file_to_open(ifstream&);
static void read_and_display_file(ifstream&);

int
main()
{
   ifstream file("allroad.con");

   if(!file)
   {
      cerr << "Failed to open file allroad.con" << endl;

      return EXIT_FAILURE;
   }

   const string& filename = get_name_of_file_to_open(file);

   file.close();

   file.open(filename.c_str());

   if(!file)
   {
      cerr << "Failed to open " << filename << endl;

      return EXIT_FAILURE;
   }

   read_and_display_file(file);

   return EXIT_SUCCESS;
}

static string
get_name_of_file_to_open(ifstream& file)
{
   string str;
   /* We assume the name of the file we want
      to open is the first string in this
      file and we assume our current reading
      position is at the beginning of the file. */
   file >> str;

   return str;
}

static void
read_and_display_file(ifstream& file)
{
   int num = 0;
   string str;

   /* We know the first line is a number and a single word. */
   file >> num >> str;

   cout << num << " " << str << endl;

   /* We know the second line is a string (that contains spaces),
      but we're actually still at the first line, so we need to
      skip to the second line by calling getline(). Then we call
      getline() again to read the second line. */
   getline(file, str); /* Skip to the second line. */
   getline(file, str); /* Read the second line. */

   cout << str << endl;

   int a = 0;
   int b = 0;
   char c = '\0';

   /* Now we loop the number of times as stated at the beginning of
      the file. The line all have the following format:
      int int char some_string_that_may_contain_spaces */
   for(int i = 0; i < num; ++i)
   {
      /* First we read the two ints and the char. */
      file >> a >> b >> c;

      /* The we read the remainder of the line into a std::string. */
      getline(file, str);

      cout << a << " " << b << " " << c << " " << str << endl;
   }  
}
Makefile:
Code:
CXX = g++
CXXFLAGS = -Wall -W -ansi -pedantic -g -O0 -c
LDFLAGS = -o $(EXEC)
EXEC = foo.exe
OBJECTS = main.o

all: $(OBJECTS)
	$(CXX) $^ $(LDFLAGS)

%.o: %.cpp
	$(CXX) $(CXXFLAGS) $<

clean:
	rm -f $(OBJECTS) $(EXEC) *~ *.stackdump
Output when run:
Code:
$ ./foo.exe 
4 (gridpoints)
Bonavista to St. John's
437 237 A  Near St. John's
434 233 B  Near Whitbourne
429 234 C  Near Clarenville
428 240 D  Near Bonavista
The gridpoints are stored in separate int variables and the single upper-case character is stored in a char and the remainder in a std::string.
 
Old 02-01-2006, 05:59 AM   #14
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Original Poster
Rep: Reputation: 0
I can open Allroad.con and get the data correctly no problem, so instead of opening the Bonavista.con the second time I tried to see if opening the Allroad.con file and that never worked. It's like I can't open two files??? if there is such a thing.


Here is the code:

Code:
include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <string.h>
#include "ARoute.h" //used later in the program

using namespace std;
int main (){

	ifstream inData;
	int noRoutes;
	ARoute* routeName;

	//temporary holds for setting characteristics of classes below
	string nextLine;
	int a,b;
	char letter;

	inData.open("c:\\Wxsystem\\Roadgram\\Commands\\AllRoad.con"); 
	if (!inData.is_open()){
		Error("AllRoad.con failed to open");
		return -1;
	}

	inData >> noRoutes;					//gets number of routes
	if (inData.fail()){
		Error("Number routes unspecified");
		return -1;
	}
	routeName = new ARoute[noRoutes];	//creates array to store route data

	
	inData.ignore(100,'\n');			//skips remainder of line

	for(int i=0; i<noRoutes; i++){		//gets route names
		getline(inData,nextLine);		
		if (inData.fail()){
			Error("Retrieving routes");
			return -1;
		}
		routeName[i].setName(nextLine);	
	}
		
	inData.close();


//Start major loop for each route Z

		for(int Z=0; Z<noRoutes;Z++){		
	
		string file = "c:\\Wxsystem\\Roadgram\\Commands\\" + routeName[Z].getName() + ".con";//file to open
	

		inData.open(file.c_str()); 		if (!inData.is_open()) {
			Error(file+" failed to open");
			return -1;		
		}	

		inData >> a;			//gets number of grid points in route

		if (inData.fail()) {
			Error(file+ "\nFailed to get number of grid points");
			return -1;		
		}
		routeName[Z].setNumGridPts(a);

		inData.ignore(100,'\n');

		getline(inData,nextLine);	//gets grid point description
		if (inData.fail()) {
			Error(file+"\nFailed to get description");
			return -1;		
		}
		routeName[Z].setDescription(nextLine);



		for(int j=0; j<routeName[i].getNumGridPts(); j++){ //gets each grid points data
			inData >> a >> b;		//gets x and y directional grid points
			if (inData.fail()) {	
				Error(file+ "\nFailed to get either of the grid numbers");
				return -1;
			}
			routeName[Z].setxy(a,b,j);

			inData >> letter;		//gets reference letter of grid point.
			if (inData.fail()) {
				Error(file+"\n Failed to get grid point reference letter");
				return -1;
			}
			routeName[Z].setGridLetter(letter,j);

			getline(inData,nextLine);	//gets the name of grid point
			if (inData.fail()) {
				Error("Failed to get grid point name");
				return -1;		
			}
			routeName[Z].setGridName(nextLine,j);

			
		}
		inData.close();
	
	
	}

Last edited by BenScaplen; 02-01-2006 at 06:06 AM.
 
Old 02-01-2006, 06:11 AM   #15
BenScaplen
LQ Newbie
 
Registered: Jan 2006
Posts: 10

Original Poster
Rep: Reputation: 0
Quote:
cout the file.c_str(); what do you get?
There is an error because of the '>>' operator

error C2676: binary '>>' : 'class std::basic_ostream<char,struct std::char_traits<char> >' does not define this operator or a conversion to a type acceptable to the predefined

could this be the problem?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
(quick!) ifstream problem Liche Programming 1 10-04-2005 06:55 PM
awk: fatal:cannot open file for reading (no such file or Directory) in Linux sangati vishwanath Linux - Software 4 07-06-2005 12:59 AM
problem reading arabic file names in fedora core 3 Yaan Linux - Newbie 1 05-21-2005 01:44 PM
ifstream - Problem siemens Programming 2 05-13-2005 01:25 PM
problem in reading Microsoft word as a binary file ljqu_happy Programming 15 02-02-2005 10:10 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:13 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration