modifying char** in a function (pass by pointer?)

Hi:
This is for native C++, a Win32 Console Application; I'm working in Visual Studio 2010.

I'm trying to do an exercise where the goal is to keep the variables for an index and a name in the main program function, but to use a function to add names and indexes, and a separate function to output these names and indexes. Here's my code, which compiles and runs, but has unexpected output:

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
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void add_data(int id, int* p_id, char* name, char** p_name, int num_datapoints)
{
	cout << "num_datapoints = " << num_datapoints << endl;
	cout << "in add_data, name: " << name << endl;
	*(p_id + num_datapoints-1) = id;
	*(p_name + num_datapoints-1) = name;

	return;
}

void output_data(int* p_id, char** p_names, int num_datapoints)
{
	cout << "id\tname\n";
	for(int i = 0 ; i < num_datapoints ; i++)
	{
		cout << p_id[i] << "\t" << p_names[i] << endl;
	}
	return;
}

int main(void)
{
	const int MAX(15);
	int num_datapoints = 0;
	int array_size = 5;
	int* p_id = new int[array_size];
	char** p_names = new char*[array_size];

	for(;;)
	{
		int id = 0;
		cout << "Id number: ";
		cin >> id;
		if(!id)
			break;
		
		char myname[MAX];
		cout << "Name: ";
		cin.clear();
		cin.sync();
		cin.getline(myname,MAX,'\n');

		if(++num_datapoints > array_size)
		{
			array_size += 5;

			int* p_temp_id = new int[array_size];
			for(int i = 0 ; i < num_datapoints ; i++)
				p_temp_id[i] = p_id[i];
			delete p_id;
			p_id = p_temp_id;
			p_temp_id = nullptr;
		}
		add_data(id, p_id, myname, p_names, num_datapoints);
	} 
	
	output_data(p_id, p_names, num_datapoints);
	
	return 0;
}



Here's the output:

Id number: 1
Name: Alex
num_datapoints = 1
in add_data, name: Alex
Id number: 2
Name: Barry
num_datapoints = 2
in add_data, name: Barry
Id number: 3
Name: Colin
num_datapoints = 3
in add_data, name: Colin
Id number: 0
id      name
1       Colin
2       Colin
3       Colin
Press any key to continue . . .


What's unexpected is that the last name entered is repeated! I'd expected:

id      name
1       Alex
2       Barry
3       Colin


I think there's something not right with the add_data() function. But I'd really like to understand why it's not working. I'd really appreciate any advice and help. Thanks so much, and sorry for the newbie question!
char myname[MAX];
What do you think happens when myname goes out of scope?
Hi Peter87:

Thanks - but that does not seem to be the issue. I tried acting on your suggestion by moving myname (and also id) to the scope of main() (rather than being local to the for loop). Here's the code:

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
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void add_data(int id, int* p_id, char* name, char** p_name, int num_datapoints)
{
	cout << "num_datapoints = " << num_datapoints << endl;
	cout << "in add_data, name: " << name << endl;
	*(p_id + num_datapoints-1) = id;
	*(p_name + num_datapoints-1) = name;

	return;
}

void output_data(int* p_id, char** p_names, int num_datapoints)
{
	cout << "id\tname\n";
	for(int i = 0 ; i < num_datapoints ; i++)
	{
		cout << p_id[i] << "\t" << p_names[i] << endl;
	}
	return;
}

int main(void)
{
	const int MAX(15);
	int num_datapoints = 0;
	int array_size = 5;
	int* p_id = new int[array_size];
	char** p_names = new char*[array_size];
	int id = 0;
	char myname[MAX];

	for(;;)
	{
		cout << "Id number: ";
		cin >> id;
		if(!id)
			break;
		
		cout << "Name: ";
		cin.clear();
		cin.sync();
		cin.getline(myname,MAX,'\n');

		if(++num_datapoints > array_size)
		{
			array_size += 5;

			int* p_temp_id = new int[array_size];
			for(int i = 0 ; i < num_datapoints ; i++)
				p_temp_id[i] = p_id[i];
			delete p_id;
			p_id = p_temp_id;
			p_temp_id = nullptr;
		}
		add_data(id, p_id, myname, p_names, num_datapoints);
	} 
	
	output_data(p_id, p_names, num_datapoints);
	
	return 0;
}


Here's the output:
Id number: 1
Name: alice
num_datapoints = 1
in add_data, name: alice
Id number: 2
Name: brenda
num_datapoints = 2
in add_data, name: brenda
Id number: 3
Name: clare
num_datapoints = 3
in add_data, name: clare
Id number: 0
id      name
1       clare
2       clare
3       clare
Press any key to continue . . .


i.e., the unexpected output still occurs. I'd expected:
id      name
1       alice
2       brenda
3       clare
You never make a copy of the input buffer. You just happily insert it's address into your array of c-string addresses over and over while you reuse it to get new input (overwriting what was in it previously.)

Btw, this would become much simpler if you availed yourself of std::vector and std::string.
Last edited on
Hi Cire:

You're absolutely right. I stepped through the debugger and what you said was spot-on. Thank you so much! I really appreciate your help.

Here's my corrected code:
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
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void add_data(int id, int* p_id, char* name, char** p_name, int num_datapoints)
{
	cout << "num_datapoints = " << num_datapoints << endl;
	cout << "in add_data, name: " << name << endl;
	*(p_id + num_datapoints-1) = id;
	*(p_name + num_datapoints-1) = name;

	return;
}

void output_data(int* p_id, char** p_names, int num_datapoints)
{
	cout << "id\tname\n";
	for(int i = 0 ; i < num_datapoints ; i++)
	{
		cout << p_id[i] << "\t" << p_names[i] << endl;
	}
	return;
}

int main(void)
{
	const int MAX(15);
	int num_datapoints = 0;
	int array_size = 5;
	int* p_id = new int[array_size];
	char** p_names = new char*[array_size];

	for(;;)
	{
		int id = 0;
		char* myname = new char[MAX];

		cout << "Id number: ";
		cin >> id;
		if(!id)
			break;
		
		cout << "Name: ";
		cin.clear();
		cin.sync();
		cin.getline(myname,MAX,'\n');

		if(++num_datapoints > array_size)
		{
			array_size += 5;

			int* p_temp_id = new int[array_size];
			for(int i = 0 ; i < num_datapoints ; i++)
				p_temp_id[i] = p_id[i];
			delete p_id;
			p_id = p_temp_id;
			p_temp_id = nullptr;
		}
		add_data(id, p_id, myname, p_names, num_datapoints);
	} 
	
	output_data(p_id, p_names, num_datapoints);
	
	return 0;
}


And the output is exactly as expected:
Id number: 1
Name: Adam
num_datapoints = 1
in add_data, name: Adam
Id number: 2
Name: Britney
num_datapoints = 2
in add_data, name: Britney
Id number: 3
Name: Cee-Lo
num_datapoints = 3
in add_data, name: Cee-Lo
Id number: 0
id      name
1       Adam
2       Britney
3       Cee-Lo
Press any key to continue . . .
Last edited on
Topic archived. No new replies allowed.