Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem reading input from a file

Status
Not open for further replies.

krotkruton

Programmer
Jan 3, 2005
6
US
I've been working on a creating my own barmonkey and I've run into problems while reading in from a file (I think that's the problem). I need to take the entries from the file and insert them into an array in my program. The file is text file with multiple entries of drinks and their ingredients and amounts. It is in the format of
Code:
Name
Ingredient1 : Amount1
Ingredient2 : Amount2
...
IngredientN : AmountN
end
Where N has a maximum of 16 I think.

Here are the first and last two entries of the file.

Code:
44
amaretto : 2.2
cranberry : 5.8
end

73 Bus
cranberry : 1.6
gin : 4.8
triplesec : 1.6
end
.
.
.
1 oz Vodka
vodka : 1.0
end

1 oz Whiskey
whiskey : 1.0
end
ENDOFFILE
ENDOFFILE
ENDOFFILE
ENDOFFILE

I put those "ENDOFFILE" strings at the end as a way to exit the file because I couldn't remember how determine when the end of the file is reached. I know its not a great way to do things, but I don't think that it should be causing my problem.

The array that each entry is entered into is in the form of "drinks" which is basically a string for the name and then another array of strings for the ingredient and array of double for the amounts.
The code that I use to load the drink database from the file is:

Code:
void loadDrinkDB(ifstream drinkDB)
{
    int i = 0;
    int j = 0;
    string currentInput = "";
    getline (drinkDB, currentInput);
    while (currentInput != "ENDOFFILE") {
        drinkList[i].name = currentInput;
        drinkDB >> currentInput;
        while (currentInput != "end") {
            drinkList[i].ingredientName[j] = currentInput;
            drinkDB >> currentInput;
            drinkDB >> currentInput;
            string doubleString, string_object(currentInput);
            drinkList[i].ingredientAmounts[j] = atof(string_object.c_str());
            drinkDB >> currentInput;
            ++j;
        }
        j = 0;
        getline (drinkDB, currentInput);
        getline (drinkDB, currentInput);
        getline (drinkDB, currentInput);
        ++i;
    }
    numDrinksInDB = i;  
}

I thought this would all be pretty straightforward, but I think I am messing things up with the multiple use of getline. Anyway, I get the error "The instruction at "0x0042b75d" referenced memory at "0x40019999". The memory could not be "read"." Which I then click "ok" to and is followed by another error with different memories. Then the program just terminates.
I've got a feeling that this is something simple that I just keep missing, but I've been working on it for a few days and just can't get past it.
Any help is appreciated.
Sorry about not putting this all in a better form but I'm still getting used to this forum.
 
Do you have a debugger? If so, it could really help if you just stepped through or looked at the call stack when the exception occurs. If you don't have a debugger, or don't want to learn to use one, try putting simple debugging statements in. For example:
Code:
std::cout << "Read in drink name - " << currentInput << std::endl;
This would tell you if something in the file is making your code hiccup.

What is drinkList? Is it an array already filled with objects? Is it a vector? Either way, by accessing the elements with [], you are assuming those elements exist. If you are using an array then you should make the array big enough to hold all of the drinks in the input file. If you are using a vector, you should have already initialized it with your drink class objects. If you didn't, then the vector will be empty and you will get a crash when you try to access an element. If this is the case, use push_back to push back an instance of your drink class at the beginning of your first while loop.

The only other possibility that I can see is if one of the ingredients is two words. This might throw off your code which reads the ingredients using operator >>.
 
Sorry for not putting all of that information in there. I was trying to keep the post relatively short while still including all of the useful information.

drinksList is an array of class drinks, unless I'm using the wrong terminology. It is defined outside of the main as
Code:
drinks drinkList[300];
It is not declared as const because it is changed, so I don't know if there might be a problem by defining it outside of main, but I didn't think there should be. I also need to define it outside because I use a function that is declared outside of main but in the same file as main to load the database.

Here is a snippet of the most important information from the drinks class:
Code:
class drinks  
{
public:
	drinks();
	virtual ~drinks();

	string     name;
	string     ingredientName[MAX_INGREDIENTS];	double     ingredientAmounts[MAX_INGREDIENTS];
};

And here is the default constructor for drinks
Code:
drinks::drinks()
{
	int i = 0;
	while (i < MAX_INGREDIENTS) {
		name = "NULL";
		ingredientName[i] = "NULL";
		ingredientAmounts[i] = 0;
		++i;
	}
}

I think that should cover all of it.

In response to your questions, there are 288 (give or take a couple) entries for drinks in the file, which is fewer than the size of the array, 300. I had also tested it with larger numbers and the same thing happens. I've never used vectors before so I don't think that is the issue either.

As far as the debugger goes, I have a small amount of experience with them, but I'm not great. I have run through the debugger for the first 20 or so and everything appeared to be working perfectly.

The thing is, this is something that should be really simple. I'm sure there are thousands of applications which read in information that is made for easy viewing instead of easy inputting. I just don't get what I'm missing here.
 
The only thing I can say is to continue to use your debugger (which one are you using - VC++ has the option to stop execution when the exception is thrown so you can see exactly when and where it happens).

Also, if you just aren't comfortable with the debugger, use the debug statements to find out where it crashes. Start by outputting the name of each drink after it is successfully read in. That way, you know which drink was the last one that was read in before the crash. Then, if that doesn't show you the problem, add output statements to display what is happening on each step, so you know pretty much which line of code was the last to execute successfully.

Hope that helps.
 
Thanks for the tips, I really appreciate the help.
I've always been a big fan of using output commands to see what's happening, but it has yet to help in this case. I'm pretty sure its a pointer problem but I can't figure out which pointer or where because after I run the loadDrinkDB function, all of the entries appear to be correct when I output different aspects of them. That's why I keep thinking it has something to do with the getline function and how it accesses memory... I'm getting to the point where I might remake the whole function to read in one character at a time, but that is going to be a bigger pain to use and may or may not cause problems when I try to save, but I'll figure that out later.
I'm just gonna stop right there because its really a hobby of mine I've spent too much time on it lately and have to get back to the work that I have to do. I'll update again if I manage to find anything interesting. Thanks again for the help. (I know that this post doesn't really say much, but I'm just kinda writing down what's going through my head so maybe when I look at this again in a few days when I have more time, I should be able to get back on track faster.)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top