Passing 2D char array to function

So when I do my first pass using the readfromfile function, it returns with the correct information, that is, firstn[100][30] is a 2D array with 100 spots for names and 30 spots for the characters in each name. When debugging it returns properly. However, once I pass it to the next function written, the sortingfunc, when it arrives inside the function the array is now a 1D array firstn[30] showing only the characters of the first name (firstn[0] of the 2D array). Here is the code. If I am passing improperly please inform me, thanks.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  #include<iostream>
#include<fstream>
#include<string>
using namespace std;
#define LEN1 100
#define LEN2 30
void sortingfunc(char[][LEN2], char[][LEN2], char [][LEN2], char [][LEN2],char [255], int);
void readfromfile(char firstn[LEN1][LEN2], char lastn[LEN1][LEN2], char phonen[LEN1][LEN2], char birthd[LEN1][LEN2], char [255]);
void searchfunc(char firstn[][LEN2], char lastn[][LEN2], char phonen[][LEN2], char birthd[][LEN2],char filename[255]);

void main()
{
	int choice, n=0, i=0, j=0;
	char filename[255]= "data.txt", 
	temp[LEN1][LEN2]={0}, search[30]={0}, firstn[LEN1][LEN2]={0}, lastn[LEN1][LEN2]={0}, phonen[LEN1][LEN2]={0}, birthd[LEN1][LEN2]={0};
	readfromfile(firstn, lastn, phonen, birthd, filename);
	cout << "Enter a number to choose an option:\n1. Find a person's information\n2. Add a person to the database\n3. Edit a person's information\n4. Display all records to the screen\n5. Quit\n";
	cin >> choice;
	switch (choice)
	{
	case 1:
		{
		}
	case 2:
		{
		}
	case 3:
		{
		}
	case 4:
		{
		}
	case 5:
		{
			sortingfunc(firstn, lastn, phonen, birthd, filename, n);
			return;
		}
	}
}


void readfromfile(char firstn[LEN1][LEN2], char lastn[LEN1][LEN2], char phonen[LEN1][LEN2], char birthd[LEN1][LEN2], char filename[255])
{ 
	int i=0, n=0;
	string line;
	ifstream file;
	file.open(filename);
	if (file.is_open())
		{
			while (!file.eof())
			{
				getline(file,line);
				for (i=0;i<line.length();i++)
				{
				firstn[n][i] = line[i];
				}
				getline(file,line);
				for (i=0;i<line.length();i++)
				{
				lastn[n][i] = line[i];
				}
				getline(file,line);
				for (i=0;i<line.length();i++)
				{
				phonen[n][i] = line[i];
				}
				getline(file,line);
				for (i=0;i<line.length();i++)
				{
				birthd[n][i] = line[i];
				}
				getline(file,line);
				n++;
			}
		}
		file.close();
}

void sortingfunc(char firstn[][LEN2], char lastn[][LEN2], char phonen[][LEN2], char birthd[][LEN2], char filename[255], int n)
{
	int iol=0, i;
	char temp[LEN1][LEN2]={0};
	ofstream file;
	file.open(filename);
	if (file.is_open())
	{
			n=n-1;
			do
			{
				iol=0;
				for (i=0; i<=n; i++)
				{
				if (strcmp(lastn[iol],lastn[i])<0)
				{
					iol=i;
				}
				}
				strcpy_s(temp[0],lastn[n]);
				strcpy_s(lastn[n],lastn[iol]);
				strcpy_s(lastn[iol],temp[0]);

				strcpy_s(temp[0],firstn[n]);
				strcpy_s(firstn[n],firstn[iol]);
				strcpy_s(firstn[iol],temp[0]);

				strcpy_s(temp[0],phonen[n]);
				strcpy_s(phonen[n],phonen[iol]);
				strcpy_s(phonen[iol],temp[0]);

				strcpy_s(temp[0],birthd[n]);
				strcpy_s(birthd[n],birthd[iol]);
				strcpy_s(birthd[iol],temp[0]);
				n--;
			} while (n>0);
			file.close();
		}
}

closed account (2UD8vCM9)
You really should use strings for this. It'd make more sense and be a lot easier to manage. Otherwise you'll have to deal with using pointers to go through your names that have a limited size, and it's just a lot more work for no advantage.

Edit: Besides you #include <string> anyways might as well use them
Last edited on
With an array I can compare last names and sort them that way, but how would I store a large amount of strings and compare the last names? Could I store each string as firstname[i], or does i indicate the position in a single string?
closed account (2UD8vCM9)
Can you post an example of what your .txt file would look like that is storing the names? I'm going to go out for a smoke, but when I come back in if you've posted an example of what the .txt file would look like i'll rewrite your code with strings and comment it so you can understand how that would work.

Make sure there's at least 2 persons entered please

Thanks
an example of the text file would be like this:

Bob
Smith
phone#
dateofbirth

John
Doe
phone#
dateofbirth

The program must be able to sort by last name and then rewrite the text file in alphabetical order.
closed account (2UD8vCM9)
Sorry it took so long. Had a bit of confusion with making the function to check whether the names need to be switched.
Here's what I came up with
Let me know what you don't understand

Oh also I changed the way the text file works
The way it works now is the very first line is the total # of entries
then the entries come after
so for example here is what it might look like

2
Bob
Smith
8553110593
03031990
Billy
Thornton
4830195830
03031940

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <string>
#include <iostream>
#include <fstream>

using namespace std;

bool NamesNeedToBeSwitched(string previousname, string nextname);
bool ReadFromFile(string firstname[], string lastname[], string dateofbirth[], string phonenumber[], int &TotalEntries, string filename);
void SortData(string firstname[], string lastname[], string dateofbirth[], string phonenumber[], int TotalEntries);

bool ReadFromFile(string firstname[], string lastname[], string dateofbirth[], string phonenumber[], int &TotalEntries, string filename) 
{ //Added the parameter int & TotalEntries. We used the & so that way we are passing the variable by reference instead of value. This lets us change the variable from
	//Inside of the function rather than just use its value. If it was an array, we wouldn't have to use the &
	ifstream Databasefile; //Our input file stream object
	Databasefile.open(filename); //Attempt to open the file
	if (Databasefile.is_open()) //If file was successfully opened, we'll read our contents into the string arrays
	{
		Databasefile >> TotalEntries; //Put the # of entries into total entries
		getline(Databasefile, firstname[0]); //This line of code doesn't do anything for our arrays. It just gets us to the next line after we read in the # of total entries

		for (int i=0; i<TotalEntries; i++) //For each entry, fill in a spot in the array
		{

			if(Databasefile.eof()) //If we reach the end of our file
			{
				cout << "Error: Database file is corrupt." << endl;
				Databasefile.close(); //Close our file before we return the function
				return false; //We shouldn't reach the file before we've read in all of our information, so that is why we're checking
			}

			//First we'll read in the firstname
			getline( Databasefile, firstname[i] );
			//Next the lastname
			getline( Databasefile, lastname[i] );
			//etc
			getline( Databasefile, dateofbirth[i] );
			getline( Databasefile, phonenumber[i] );
		}
		Databasefile.close(); //We're done reading in the entries, so we close our file
		return true; //After our for loop is completed, we have read in all of the entries, so we can return true.
	} else //If file wasn't successfully opened, we'll return false so we know that we couldn't open the file
	{
		return false; //Return false to fill our DidWeSuccessfullyReadTheFile boolean
	}
}

void SortData(string firstname[], string lastname[], string dateofbirth[], string phonenumber[], int TotalEntries)
{ //In this function, we pass the value of TotalEntries instead of a reference to the value since this function should not change TotalEntries
	//We will do a nested for loop
	//The inner loop will swap a name with the next name if the next name comes before the previous name in the alphabet
	//The outer loop will be there just to ensure that if a name has to be moved twice or more, it will be moved as many times as necessary
	for (int i=0; i< TotalEntries; i++) //Outer loop
	{
		for (int a=1; a<TotalEntries; a++)
		{
			if (NamesNeedToBeSwitched(lastname[a-1], lastname[a])) //If a previous name comes after the next name then swap their spots
			{														//For function pass the previous name, then the last name
				swap(lastname[a-1],lastname[a]); //swap last names
				swap(firstname[a-1],firstname[a]); //swap first names etc
				swap(dateofbirth[a-1],dateofbirth[a]);
				swap(phonenumber[a-1],phonenumber[a]);
			}
		}
	}
}

bool NamesNeedToBeSwitched(string previousname, string nextname)
{
	if (previousname.size()<=nextname.size())
	{
		//Capitalize all the letters in each string before we compare individual letter's ascii codes
		for (int i=0; i<previousname.size(); i++)
		{
			if (previousname[i]>91)
			{
				previousname[i]-=32;
			}
			if (nextname[i]>91)
			{
				nextname[i]-=32;
			}
		}
		//For loop to check each individual character
		for (int i=0; i<previousname.size(); i++)
		{
			if (previousname[i] > nextname[i]) //If the letter in previous name comes after letter in nextname, return true so they can be switched
			{
				return true;
			}
		}
		//If the for loop completes without returning true, then the names don't need to be switched
		return false;
	}

	//Basically a copy of the above if except with the sizes switched around
	if (nextname.size()<previousname.size())
	{
		//Capitalize all the letters in each string before we compare individual letter's ascii codes
		for (int i=0; i<nextname.size(); i++)
		{
			toupper(previousname[i]);
			toupper(nextname[i]);
		}
		//For loop to check each individual character
		for (int i=0; i<nextname.size(); i++)
		{
			if (previousname[i] > nextname[i]) //If the letter in previous name comes after letter in nextname, return true so they can be switched
			{
				return true;
			}
		}
		//If the for loop completes without returning true, then the names don't need to be switched
		return false;
	}

}

int main()
{
	string firstname[100];
	string lastname[100];
	string dateofbirth[100];
	string phonenumber[100];
	int TotalEntries=0; //This will hold the total # of entries that we currently have. It is used for the ReadFromFile function
	bool DidWeSuccesfullyReadTheFile; //If we did successfully read the file, this boolean value will be true after we set it equal to our ReadFromFile function
	DidWeSuccesfullyReadTheFile = ReadFromFile(firstname, lastname, dateofbirth, phonenumber, TotalEntries, "data.txt"); //This function loads up our database entries
	if (DidWeSuccesfullyReadTheFile == false) //If we can't open the database file, we need to display an error
	{
		cout << "Error: Could not open database file." << endl;
	} else //If we did successfully read from the file
	{
		SortData( firstname, lastname, dateofbirth, phonenumber, TotalEntries); //Then go ahead and sort the data in our array by lastname
	}
	while (true)
	{
		cout << "Enter a number to choose an option:\n1. Find a person's information\n2. Add a person to the database\n3. Edit a person's information\n4. Display all records to the screen\n5. Quit\n";
		int input;
		cin >> input;
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			return 0; //Exits main function which in result exits program
			break;
		}
	}
}
Wow, I am very appreciative of all the work you put into helping me. Using strings makes much more sense to me now and will definitely help me with my program. Thank you very much, that was a lot of work.
Topic archived. No new replies allowed.