I/O file issues

Apr 15, 2013 at 7:45pm
I have the assignment to read files from a .txt file named names.txt that contains names like this...
Marcus Smith
Jane Doe
Abe Lincoln

I must then return this into a new file named sortednames.txt in the format of Last,First.

We received code that sorts integers, but right now I am having issues writing a function that reads the file and puts each name into an array. I am not quite sure what the best way to do this is, but we haven't learned multidimensional arrays yet. So here is the function I have started... all help is much appreciated
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  void readFile (string& firstName, string& lastName, char lastFirst[])
{
	//VARIABLE
	string name;
	int counter = 0;

	ifstream myfile("names.txt.");

	if (myfile.fail())
	{
		cout << "Unable to open file" << endl;
	}
	else
	{
		while (!myfile.eof())
		{
			getline (cin,firstName);
			getline (cin,lastName);
			myfile.close;
//From this point on I am not sure how to put the received names into an array
				
		}

	}
}
Apr 15, 2013 at 9:11pm
Read the documentation of std::vector and std::pair.

Edit:
1. firstName and lastName are reference parameters. Why?
2. getline gets a whole line, not first word. Getting a line is good, but you have to split it into forename and surname.
3. closing file after first two lines does not look intentional.
Last edited on Apr 15, 2013 at 9:18pm
Apr 15, 2013 at 9:27pm
I am not sure if we are allowed to use vectors because we haven't learned them.

I am going to work on a solution and I will post my new function soon.
Last edited on Apr 15, 2013 at 9:27pm
Apr 15, 2013 at 9:41pm
Im still lost, because I need to put the first word of a line into the firstName string and then stop at the whitespace. Then take the next work and put it into the lastName string and then stop at the enter. And continue with this as a loop..

PLEASE HELP!
Apr 15, 2013 at 9:47pm
Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <string>
#include <fstream>

void foo()
{
    const int MAXSZ = 128 ;
    std::string names[MAXSZ] ;

    int cnt = 0 ; // number of names read

    std::ifstream file( "names.txt" ) ;
    std::string first_name, last_name ;

    while( file >> first_name >> last_name ) // for each name read
    {
        // place it in the array as last_name, first_name
        names[cnt] = last_name + ", " + first_name ;
        ++cnt ; // increment the cnt of names read
        if( cnt == MAXSZ ) break ; // the array is full; we can't read any more
    }

    // at this point names[0] ... names[cnt-1] contains 'cnt' names
    // in the form last_name, first_name

    // TODO: sort the names

    // TODO: write the sorted names to the ouput file
}

Apr 15, 2013 at 9:51pm
what part of this code changes the names from..

Joe Buck
Jane Doe

to...

Buck, Joe
Doe, Jane

because I see where you ifstream the file and then call the string and follow it with first_name, last_name. I am wondering if that will work? is that where the program will take the first word and put it into a variable first_name then the next into last_name? because if so wouldn't it need to also be in the loop?
Last edited on Apr 15, 2013 at 9:53pm
Apr 15, 2013 at 9:59pm
for instance this is my while loop

1
2
3
4
while (!myfile.eof())
		{
			getline (myfile,name);	
		}


how would I tell it to grab the text until there is whitespace?
Apr 15, 2013 at 10:10pm
getline reads a whole line, whitespace and all.
>> skips whitespace (by default) and only reads one word.

file >> first_name >> last_name
Evaluates from left to right. Therefore, it does "file >> first_name" first. That reads one word from file and stores it into first_name. The expression returns a reference to the file-object. Thus, the second operation is actually "file >> last_name".

Having done that, two words (i.e. one line) has been read and you have the parts of one name in the two variables.
Apr 15, 2013 at 10:16pm
Do not write this kind of loop in this manner:
1
2
3
4
5
while (!myfile.eof())
		{
			getline (myfile,name);	
                        // ...
		}


Instead write it this way:
1
2
3
4
while ( getline(myfile,name) )
		{
			// ...	
		}


Since you need to seperate the name into first_name and last_name, it is much simpler if you do that as part of the input operation:
1
2
3
4
5
6
7
    while( file >> first_name >> last_name ) // for each name read
    {
        // place it in the array as last_name, first_name
        names[cnt] = last_name + ", " + first_name ;
        ++cnt ; // increment the cnt of names read
        if( cnt == MAXSZ ) break ; // the array is full; we can't read any more
    }



> what part of this code changes the names from..

> Joe Buck
> Jane Doe

> to...

> Buck, Joe
> Doe, Jane

This part: last_name + ", " + first_name ;

For instance, for the line
Joe Buck
1
2
3
first_name == "Joe"
last_name == "Buck"
( last_name + ", " + first_name ) == "Buck, Joe"


> is that where the program will take the
> first word and put it into a variable first_name then the next into last_name

Yes.


> if so wouldn't it need to also be in the loop?

It is in the loop. file >> first_name >> last_name is evaluated afresh each time through the loop.


> I am wondering if that will work?

The best way to be sure would be to try it out.
Apr 15, 2013 at 10:16pm
thank you for that explanation!

however... I have run into yet another problem...

when writing this code

1
2
3
4
5
6
7
8
9
		while (!myfile.eof()) //
		{
			myfile >> firstName >> lastName;
			cout << firstName;
			cout << lastName;
			lastFirst[counter] = lastName + ", " + firstName;
			cout << lastFirst;
			counter ++;
		}


*the cout's are just for checking that the correct things were being input into the files*

unfortunately I am getting random gibberish in the lastFirst string... I am not sure why?
Apr 15, 2013 at 10:22pm
Do not, repeat do not, repeat DO NOT write the loop this way:

1
2
3
4
5
6
7
8
while (!myfile.eof()) //
		{
			myfile >> firstName >> lastName;
                        // what happens when this input fails?
                        // firstName  and lastName will contain gibberish

                       // ...
		}


Write is this way:
1
2
3
4
    while( file >> first_name >> last_name ) 
    {
         // ...
    }
Apr 16, 2013 at 12:17am
alright so I have completed the function that takes in any number of names that are listed First Last and then puts them into another string that is Last, First. The code for that function is..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void readFile (string lastFirst[], int counter)
{
	//VARIABLE
	string name;
	string firstName;
	string lastName;

	ifstream myfile("names.txt.");

	if (myfile.fail())
	{
		cout << "Unable to open file" << endl;
	}
	else
	{
		while (myfile >> firstName >> lastName) //
		{
			lastFirst[counter] = lastName + ", " + firstName;
			cout << lastFirst [counter];
			counter ++;
			cout << counter;
		}

	}
}


The next issue I am having is transforming a swap function that our teacher gave to us...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void sort (int values[], int numElements)
{ 	
 	bool swapped = true;  // values were swapped last pass
 	int temp = 0;         // temp swap variable
  	// "bubble" large values to the top until no more swapping occurs
  	while (swapped)
  	{ 		
 		swapped = false; 
 		// reset after each complete pass through list 
		for (int i = 0; i < numElements - 1; i++) 
 		{ 			
 			if (values[i] < values[i+1]) 
			{    
 				// swap the two values
 				temp = values[i]; 
				values[i] = values[i+1]; 
				values[i+1] = temp; 
				swapped = true; 
			} 
		} 
	}
 } 


Into code that will work for string functions. So here is where I am at so far...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void sort (string values[], int numElements)
{ 	
 	bool swapped = true;  // values were swapped last pass
 	string temp = 0;         // temp swap variable
  	// "bubble" large values to the top until no more swapping occurs
  	while (swapped)
  	{ 		
 		swapped = false; 
 		// reset after each complete pass through list 
		for (int i = 0; i < numElements - 1; i++) 
 		{ 			
 			if (values[i] < values[i+1]) 
			{    
 				// swap the two values
 				temp = values[i]; 
				values[i] = values[i+1]; 
				values[i+1] = temp; 
				swapped = true; 
			} 
		} 
	}
 }


Please Advise
Apr 16, 2013 at 6:21am
Have you tested that? Was there a problem?

Do not initialize string to 0. std::string has a default constructor that initializes it to empty string, and that is fine.

Will you call 'sort' within 'readFile'? If not, you must pass 'counter' to 'numElements'. A reference would make sense there.
Topic archived. No new replies allowed.