Im having trouble making a jagged char-2D-array program. I need some help

Pages: 12
The names are stored in a file.

1
2
3
4
5
6
7
8
9
kamil
saad
muhammad
alexander
alina
taylor
jack
nikita
katya



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
#include <iostream>
#include <fstream>
using namespace std;
int main(){
    ifstream fin("names.txt");
    if(!fin.is_open())
    {
    	cout << "File not open";
	}

    int row = 0;
    int col = 0;
    char ch = '\0';
    char ** names = new char * [1];
    names[0] = new char [1];
    cout << "Hello";
    while(!fin.eof())
	{
        fin.get(ch);
        //cout << ch;
        if(ch != '\n')
		{
            names[row][col] = ch;
            col++;
            
            char *temp = new char [col + 1];
            for(int i = 0; i < col; ++i)
            {
            	temp[i] = names[row][i];
			}
            delete [] names[row];
            names[row] = temp;
        }
		else
		{
            names[row][col] = '\0';
            row++;
            char ** temp2 = new char * [row];
            for(int i = 0; i < row; ++i)
            {
        		temp2[i] = names[i];
			}
            delete [] names;
            names = temp2;
            col = 0;
            names[row] = new char [col + 1];
        }
    }

    for(unsigned int i = 0; i <= row; ++i)
    {
		cout << names[i] << endl;
	}

    return 0;
}


This program isn't running properly. Can anyone please point out the errors? This program has drained everything out of me.
You can use fin.getline to read a whole name and store it in a char array[100].
Then through strlen(array) find out its length. After that simply make a new dynamic char array of size length.

I hope this code works.
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
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream fin("names.txt");
    if(!fin.is_open())
    {
    	cout << "File not open";
	}

	char ** names, onename[100] = {'\0'};
	int size=1, index=0, length = 0;

	names = new char * [size];
	fin.getline(onename, 100);
	length = strlen(onename)+1;

	names[index] = new char [length];
	names[index] = onename;

	//for next interations
	size++;
	index++;

	while(!fin.eof())
	{
		cout << "reading" << endl;
		char ** temp = new char * [size]; //size is one more than the existing array because of size++

		for(int i=0; i<size-1; i++)	  //size-1 because last index is for the new input
		{
			temp[i] = names[i];
		}

		fin.getline(onename, 100);
		
		length = strlen(onename)+1;
		temp[index] = new char [length];
		temp[index] = onename;

		names = temp;
		size++;
		index++;
	}

	for(int i=0; i<size-1; i++)
	{
		cout << names[i] << endl;
	}
	system("pause");
	return 0;
}
Why are you using all of that dynamic memory? You really should be using a vector to hold your strings.

Something like:

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
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    ifstream fin("names.txt");
    if(!fin)
    {
    	cerr << "File not open";
    	return(1);
    }

    vector<string> names;
    string line;
    while(getline(fin, line))
    {
        names.push_back(line);
    }

    for(auto& itr : names)
    {
        cout << itr << endl;
    }

    return 0;
}
Last edited on
@jlb - Judging from the difficulty level of the question, I'm guessing its for a homework. Also, this part of forum is for beginners so that's why I tried to keep it as relevant to his code and as simple as possible.

Thanks. :)
jlib i cant use vectors. im only supposed to use pointers.

taha ilyas, your code isn't working properly. it only displays one name. The problem seems to be in between line 39 & 41. I don't know why its over righting the previous name
@taha ilyas I didn't see your post before I posted my post so my code has nothing to do with the code you provided.

However I realize that this is for homework, however using C-strings and arrays is not really the best way to accomplish this assignment, so I gave a better way of accomplishing the assignment. If the OP can't, for some strange reason, use C++ to accomplish the assignment I'll let him tell me that in a later post. Then after the vector and string have been eliminated one can move on to the horrible C-string and dynamic memory allocations.

By the way your program doesn't compile for me since you failed to #include a required header file. There are also other problems with your code having to do with your dynamic memory and memory leaks.
jlib it isnt my homework. Im just trying to do it on my own for practice. My teacher said "On the initial stage, you should target your logic building and stay away from shortcuts which are provided in different libraries".
Thats why im trying to not use vector and use pointers for that.

I still cant figure out why the previous name is being over-written at line 41.
Last edited on
My teacher said "On the initial stage, you should target your logic building and stay away from shortcuts which are provided in different libraries".

IMO using the STL is not a shortcut, I feel learning to properly use this library is one of the most important aspects of learning C++. Also IMO you shouldn't consider the STL a "different library". If you're trying to learn C++ start with C++ standard features which includes things as vector and string. Wait to learn pointers until you have the basics down and then start slowly. Pointers can be very confusing and error prone, this is why the Standard Template Library, and the string class were developed, to help reduce errors.

The way you appear to be going seems to be learn the C "features", then learn the proper C++ features, which IMO is backwards. If you want to learn C++ learn C++!

taha ilyas, your code isn't working properly. it only displays one name. The problem seems to be in between line 39 & 41. I don't know why its over righting the previous name

Actually the problem starts earlier, on line 30.

As I said start simpler, avoid the dynamic memory until you have your basic premise working. Something like:
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
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream fin("names.txt");
    if(!fin.is_open())
    {
    	cout << "File not open";
    	return(1);
    }

    char names[100][40];

    int index = 0;

    while(fin.getline(names[index], 40) && index < 100)
    {
        index++;
    }

    for(int i = 0; i < index; i++)
    {
        cout << names[i] << endl;
    }

    return 0;
}
Last edited on
closed account (48T7M4Gy)
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
#include<iostream>
#include<fstream>

int main()
{
    std::fstream inFile("jagged_array.txt");
    
    if (inFile.is_open())
    {
        // Count how many names
        long count = 0;
        char temp[100];
        
        while (inFile >> temp)
            count++;
        
        std::cout << "Number of names: " << count << std::endl;
        
        // Reset file to beginning
        inFile.clear();
        inFile.seekg(0, inFile.beg);
        
        // Create jagged array pointers
        char** name = new char*[count]; // "Rows"
        int i = 0;
        long size = 0;
        
        // Create array for each name
        while (inFile >> temp)
        {
            size = std::strlen(temp);
            name[i] = new char[size + 1]; // "Columns"
            
            for (int j = 0; j < size; j++)
                name[i][j] = temp[j];
            name[i][size + 1] = '\0'; // Add terminator
            
            i++;
        }
        
        // Display names and show jagged nature
        for( int i = 0; i < count; i++ )
            std::cout << strlen(name[i]) << " " << name[i] << "*" << std::endl;
    }
    else
        std::cout << "Unable to open file.\n";
    
    inFile.close();
    return 0;
}


Number of names: 9
5 kamil*
4 saad*
8 muhammad*
9 alexander*
5 alina*
6 taylor*
4 jack*
6 nikita*
5 katya*


Building on taha ilya's work. The asterisk is there to show the jagged nature (at least in theory - I await the thunder-critique-blitz). I couldn't be bothered doing a strlen() or similar). Strings are for the convenience of not dealing with getline but either way it's just a means to an end. Somebody can do the delete cleanup of course.
Last edited on
I know how to do this with string. Im trying to do the same thing with char-array just to enhance my skills
closed account (48T7M4Gy)
I know how to do this with string.

Excellent. So there's your challenge!

It's only a minor modification to use getline() and drag the names in as a c-string. strtok() is another c-string function that springs to mind.

Or you can read the file in character-by-character and manipulate the input.

It's all much the same. I look forward to seeing your solution. :)
Last edited on
teacher wrote:
My teacher said "On the initial stage, you should target your logic building and stay away from shortcuts which are provided in different libraries".


kamilhassaan wrote:
I know how to do this with string. Im trying to do the same thing with char-array just to enhance my skills


I agree with jlb

In education, teachers get their students implement their own sort routines or data structures such as linked lists, so they can understand how they work in detail, rather than blindly using std::sort or std::list say. I think this is what the Teacher meant by that comment. But I think it is a bit of a backward step to delve into char arrays, that is the domain of C programming. As jlb says: if you want to learn C++, then learn C++. That is not to say one can't learn C at some stage - it is handy to know that stuff eventually.

So maybe your time might be better spent implementing your own linked list or queue using classes. In my mind that would be better than messing around with char arrays.

closed account (48T7M4Gy)
And the value-add in that is?
Hi kemort :+)

Good to see you back again after a break. :+)

To me the "value add" is to learn about classes, and to achieve something by making a data structure.
closed account (48T7M4Gy)
Hey TIM :)
closed account (48T7M4Gy)
Now there's no strings.
This is what i tried to do

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
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
int main()
{
	ifstream fin("names.txt");
	if(!fin.is_open())
	{
		cout << "File not open" << endl;
	}
	else
	{
		cout << "Open" << endl << endl;
	}
	const char null = '\0';
	
	char temp[100] = {null};
	
	int numofrows = 0;
	
	while(!fin.eof())
	{
		fin.getline(temp , 100);
		numofrows++;
	}
	temp[100] = null;	
	
	fin.close();
	fin.open("names.txt");
	
	int len = 0;
	
	char **names;
	names = new char*[numofrows];
	
/*	for(int i = 0; i < numofrows; i++)
	{
		fin.getline(temp , 100);
		cout << temp << endl;
	}
*/	
	for(int i = 0; i < numofrows; i++)
	{
		fin.getline(temp , 100);
		len = strlen(temp);
		names[i] = new char[len];
		len = 0;
		temp[100] = null;
	}
	
	int row_index = 0;
	
	while(!fin.eof())
	{
		fin.getline(temp , 100);
		cout << temp;
		names[row_index] = temp;
		cout << names[row_index];
		temp[100] = null;
		row_index++;
	}
	
	for(int i = 0; i < numofrows; i++)
	{
		cout << names[i] << endl;
	}
}


I tried this. It doesn't seem to work.
Last edited on
Here is the result of CPPCheck:
[Main.cpp:30]: (error) Array 'temp[100]' accessed at index 100, which is out of bounds.
[Main.cpp:52]: (error) Array 'temp[100]' accessed at index 100, which is out of bounds.
[Main.cpp:63]: (error) Array 'temp[100]' accessed at index 100, which is out of bounds.
[Main.cpp:71]: (error) Memory leak: names


In line 47 you allocate the memory for the name but why don't you copy the name to the array?
With the use of the stl the whole exercise would be pointless.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main ()
{
  ifstream fin ("names.txt");

  if (!fin)
  {
    perror("Error: ");
    exit (EXIT_FAILURE);
  }
  vector<string> names;
  copy (istream_iterator<string> (fin), istream_iterator<string> (),
        back_inserter(names));

  copy (names.begin (), names.end (), ostream_iterator<string> (cout, "\n"));

  system ("pause");
}


With two copy commands you have your file in a vector.
Pages: 12