I send out multiple types of variables (i.e. 2 char arrays, 1 int, 1 double, and two more char arrays). But when I read then back at the beginning of the program (building a LLL) I get multiple declarations of the same variables and then when I display the LLL it stops at the beginning as if waiting for input.

Console Result:

Name: a b
Acct Num: 1801640999
Balance: $0

Name: a b
Acct Num: 1801640999
Balance: $0

Name: c d
Acct Num: 1801674613
Balance: $0

Name: a b
Acct Num: 1801640999
Balance: $0

Name: kill
quit

This code reads in from the file:

ifstream fin ("AccountDatabase.dat");
while (fin && !fin.eof())
		{
			Node * temp = new Node;
char first [100];
			char last [100];
			int acctnumber;
			double balance;
			//char notes [100];
			char created [80];
			char modified [80];
			fin >> first >> last >> acctnumber >> balance >> created >> modified;
}

This code sends it to the file:

ofstream fout;
	fout.open("AccountDatabase.dat", ios::app);
	Node * temp = head;
	while (temp && !fout.eof()) {
		fout << temp->first << " ";
		fout << temp->last << " ";
		fout << temp->accountNumber << " ";
		fout << temp->balance << " ";
		fout << temp->dateCreated << " ";
		fout << temp->dateModified << endl;
		temp = temp->next;
	} // while
	fout.close();

A look at the file "AccountDatabase.dat" is:
a b 1801640999 0 08/18/2010 08/18/2010
c d 1801674613 0 08/18/2010 08/18/2010
a b 1801640999 0 08/18/2010 08/18/2010


Any help would be great! I have been looking for a long time on Google and on the forums!

Recommended Answers

All 11 Replies

I would think its an issue with the arrays. Have you tried using the ';' as a file delimiter between each entry and a space between items that are part of the same field ie your array?

file might have something like "a;b;1801640999;0;DDMMYYYY;DDMMYYYY;" for one record. With that the joy you can use is getline. so if you want to fill a record you call getline a few times instead.

//get some items from file
getline(fin,first,';');
...
getline(fin,dateModified,';');

If this doesnt work then consider also using strings instead of char arrays. i dont know how forgiving the i/o stream is for reading into a c style array.

Hope this helps

It wouldn't let me use

getline(fin, first, ';');

or any of the getline functions. Do I have to supply a specific #include or is that not the issue?

I wouldn't use getline for this. If you do so, you must take responsibility for tokenizing the lines and converting string data. The iostream library can do this automatically for you, so using ifstream and the >> operator is correct.

My guess is that you are reading all of the data into the same variables over and over.

this code:

while( fin && !fin.eof() )
{
    Node * temp = new Node;
    char first [100];
    char last [100];
    int acctnumber;
    double balance;
    //char notes [100];
    char created [80];
    char modified [80];
    fin >> first >> last >> acctnumber >> balance >> created >> modified;
}

Doesn't do anything with the data it has read. It simply goes to the next iteration of the loop and reads that data into the same variables as the previous loop.

My guess is that your output is the last record in the file repeated so many times.

My suggestion for you would be to create an array of structs containing the data read from file. That way, you can store all the data you have read without overwriting anything.

Something similar to this should work for you:

#include <iostream>
#include <fstream>

using namespace std;

struct MyData
{
    char   someString[100];
    int    someInteger;
    double someReal;
};

void myReadingFunction( ifstream& fin, MyData data[], int& count )
{
    count = 0;
    while( !fin.eof() )
    {
        fin >> data[count].someString
            >> data[count].someInteger
            >> data[count].someReal;
        count++;
    }
}

void myPrintingFunction( MyData data[], int count )
{
    for( int i=0; i<count; i++ )
    {
        cout << data[i].someString  << " "
             << data[i].someInteger << " "
             << data[i].someReal    << endl;
    }
}

int main()
{
    MyData data[100];
    int count;
    ifstream fin( "myData.txt" );
    myReadingFunction( fin, data, count );
    myPrintingFunction( data, count );
    return 0;
}

The data file is

Hello 1 1.1
World 2 2.2
This  3 3.3
Is    4 4.4
A     5 5.5
Test  6 6.6

And the resulting output is

Hello 1 1.1
World 2 2.2
This 3 3.3
Is 4 4.4
A 5 5.5
Test 6 6.6

If you do not want to store the data you read, then you must position your output immediately after you read each record. Like so

while (fin && !fin.eof())
{
Node * temp = new Node;
char first [100];
char last [100];
int acctnumber;
double balance;
//char notes [100];
char created [80];
char modified [80];
fin >> first >> last >> acctnumber >> balance >> created >> modified;
// Place output here before the data can be overwritten by the next iteration!
}

The key here is to understand that you are currently just overwriting the data you have extracted from the file on each iteration of the loop. Consequently, only the last record survives in memory.

I would in hindsight agree with dusktreader, however make one final suggestion.

Instead of a constant sized array of data consider using stl vectors or llists which let you read any amount of input without knowing its size first. If you know the size of input will never change i guess the above way is fine but its just a thought.

I would in hindsight agree with dusktreader, however make one final suggestion.

Instead of a constant sized array of data consider using stl vectors or llists which let you read any amount of input without knowing its size first. If you know the size of input will never change i guess the above way is fine but its just a thought.

I completely agree. This code could be improved greatly by using the Standard Template Library.

However, it is obvious that this person is studying computer science. Often teachers/professors insist on students using old programming paradigms that are carry-overs from C. To me, this practice is asinine, because many programmers continue to use these methods beyond the classroom when there are simpler, cleaner, and more robust ways to implement the same functionality. It is especially annoying when the preferred method is native to the C++ language!

So, I didn't want to confuse the OP. However, if you are listening, dear OP, please read up on the use of std::vector and the other joys of the c++ standard template library. I promise you that once you embrace the STL, your code will improve and you'll be spending less time bounds checking and searching for seg faults and more time producing good code.

Thank you both for your help! I will try these new coding examples and put them into practice. I have only used std::vector once and I think that it would help! I will look into it! I haven't been programming in C++ for a couple of years and have been working heavily in Java so that has hindered me a little bit!! Not used to all this dynamic memory etc.

So I tried a new format! Like the one that you suggested. Here is my code:

ifstream fin ("AccountDatabase.dat");
	number_of_Nodes = 0;
	head = NULL;
	while (fin && !fin.eof())
	{
		char first [100];
		char last [100];
		int acctnumber;
		double balance;
		char created [80];
		char modified [80];
		if (!head)
		{
			head = new Node;
			fin >> first >> last >> acctnumber >> balance >> created >> modified;
			fin.ignore();
			head->first = new char [strlen(first) + 1];
			strcpy (head->first, first);
			head->last = new char [strlen(last) + 1];
			strcpy (head->last, last);
			head->accountNumber = acctnumber;
			head->balance = balance;
			strcpy(head->dateCreated, created);
			strcpy(head->dateModified, modified);
			head->next = NULL;
		}
		else
		{
			Node * temp = new Node;
			fin >> first >> last >> acctnumber >> balance >> created >> modified;
			fin.ignore();
			temp->first = new char [strlen(first) + 1];
			strcpy (temp->first, first);
			temp->last = new char [strlen(last) + 1];
			strcpy (temp->last, last);
			temp->accountNumber = acctnumber;
			temp->balance = balance;
			strcpy(temp->dateCreated, created);
			strcpy(temp->dateModified, modified);
			temp->next = head;
			head = temp;
		}
	} // if
	fin.close();

It is the default constructor for a class (aka it populates a LLL before the program does anything bringing in saved information). It sends everything out with a space and once run it brings in the correct data, except the first item is duplicated.

Console Read:

Name:      a b
Acct Num:  1801640999
Balance:   $0

Name:      a b
Acct Num:  1801640999
Balance:   $0

File: ("AccountDatabase.dat")

a b 1801640999 0 08/18/2010 08/18/2010

There is a good explination of this. It has to do with using

while (fin && !fin.eof())

As the while condition. I cant explian correctly the reason for this as its a bit complicated but the correct way to do it is

while(cin>> var)
{
//...
}

This means that if a read fails (incorrect input or eof) the loop breaks immediately and unlike what you got the last read is NOT duplicated .

Im going to look for the forum discussion here that explained it and post a link as a edit in a moment.

Thank you! I'll try it out in a second and let you know how it goes!
Does it need to be 'cin' or 'fin'??

Oh! Got it working! Thank you!! :)

Glad to hear, you used fin then i assume. Sorry for the late reply i had to attend to some things about the house.

Happy coding :)

edit: If your done here save people time and mark this as solved thanks :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.