Displaying correct output (with Pointers)

Hi so I wanted to display the correct output by using a for loop at the end of my code, but for some reason it's not working correctly. Sorry in advance if I'm not using the correct terms either. I'm bearly beginning C++ and I can't really wrap my head around this one. Can anybody tell me what I'm doing wrong on my last for loop (the one with 2 for loops together). Thank You!

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
#include <iostream>

using namespace std;

int main()
{
    int* ipArray[3];

    for(int i = 0; i < 3; i++)
    {
        ipArray[i] = new int [5];
    }

    int* walker;

     walker = ipArray[0];

    for(int i = 0; i < 5; i++)
    {
        *walker = i;

        cout<<*walker<<" ";
    }

    cout<<endl;

     walker = ipArray[1];

    for(int i = 0; i < 5; i++)
    {
        *walker = i+10;

        cout<<*walker<<" ";
    }

    cout<<endl;

     walker = ipArray[2];

    for(int i = 0; i < 5; i++)
    {
        *walker = i+20;

        cout<<*walker<<" ";
    }


    cout<<endl<<endl;


    //suppose to print out result
    for(int rows = 0; rows < 3; rows++)
    {
        for(int cols = 0; cols < 5; cols++)

            cout<<*walker<<" ";
            cout<<endl;
    }



    delete [] ipArray[0];
    delete [] ipArray[1];
    delete [] ipArray[2];


    cout <<endl<<endl<<endl<< "END!" << endl;

    cout<<endl;

    return 0;
}




Here's my output:
0 1 2 3 4
10 11 12 13 14
20 21 22 23 24

24 24 24 24 24
24 24 24 24 24
24 24 24 24 24



END!

Press <RETURN> to close this window...


1
2
3
4
5
6
7
8
    //suppose to print out result
    for(int rows = 0; rows < 3; rows++)
    {
        for(int cols = 0; cols < 5; cols++)

            cout<<*walker<<" ";
            cout<<endl;
    }



sorry, what I wanted to do is pretty much match my 1st out put like 0 1 2 3 4 but my 2nd output only outputs 24's and I don't know why. Please let me know what I'm not doing right or what I'm missing. Thank You again!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

    for(int i = 0; i < 5; i++)
    {
        *walker = i+20;

        cout<<*walker<<" ";
    }
// When this loop ends *walker is set to i(4)+20 so is 24

    cout<<endl<<endl;


    //suppose to print out result
    for(int rows = 0; rows < 3; rows++)
    {
        for(int cols = 0; cols < 5; cols++)

            cout<<*walker<<" "; //here for all 15 (3*5) loops you just output the the value of *walker 
            cout<<endl;         // which in the previous loop you set as 24
    }



Dont know what you are actually trying to do, so i cant help you with that but this is why you get the output you get.

Hope this helps :)


edit: didnt read the bottom

1
2
3
4
5
6
   
 for(int i = 0; i < 5; i++)
    {
        *walker = i; // here you set *walker to i.
        cout<<*walker<<" "; //here you output the new value of *walker
    }

so say for every loop you set *walker to the value of i and then output the new value of *walker meaning you could just output i.

The problem i think youre having is you think you are changing the where the pointer is pointing to but youre just changing the value at the address that it points to.
You have to increment where the pointer points to each time

for example

1
2
3
4
5
6
7
8
9
10
    *walker = 10;
    cout << *walker << endl;
    *walker = 12 << *walker << endl;
    //the value at walkers address changes from 10 to 12
    //12 is now the only value at walker
    *(walker+1) = 20
    cout << *(walker+1) << endl;
    // value at walker is still 12
    // value one  int from walker is 20


So you have to increment the pointer (it will increment as many bytes as the data type you have set it to) similarly to an array

Hope this helps :)
Last edited on
walker should be dereferenced using the subscript operator [ ],
not through *, i don't know how did that worked ( although i dont know if my statement is correct, i haven't been using 2d dynamic arrays since )
So your first 3 assignment & printing loops should be :
1
2
3
4
5
    for( int i = 0; i < 5; i++ ) // std::size_t or unsigned would be better instead of int
    {
        walker[ i ] = i; // dereference and assign i
        cout << walker[ i ] << " "; // dereference and print
    }


and in your nested for loop, it should be something like :
1
2
3
4
5
6
7
8
9
10
11
    for( size_t rows = 0; rows < 3; rows++ ) // i used size_t instead of int rows = 0
    {
        walker = ipArray[ rows ];

        for( size_t cols = 0; cols < 5; cols++)
        {
            cout << walker[ cols ] << " ";
        }

        cout << endl;
    }


On the other hand, I advise you to use functions to print the array contents or to assign something to it

maybe something like :
1
2
3
4
5
6
void print( int* p, size_t N )
{
    for( size_t i = 0; i < N; ++i )
        cout << p[ i ] << " ";
    cout << endl;
}

to print the contents of an array

and something like :
1
2
3
4
5
void assign( int* p, size_t N, int number_to_add = 0 )
{
    for( size_t i = 0; i < N; ++i )
        p[ i ] = i + number_to_add;
}

to assign a value to the array contents

or maybe another function to call both

So in the end, you can have 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
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 namespace std;

void print( int* p, size_t N )
{
    for( size_t i = 0; i < N; ++i )
        cout << p[ i ] << " ";
    cout << endl;
}

void assign( int* p, size_t N, int number_to_add = 0 )
{
    for( size_t i = 0; i < N; ++i )
        p[ i ] = i + number_to_add;
}

void assign_and_print( int* p, size_t N, int number_to_add = 0 )
{
    assign( p, N, number_to_add );
    print( p, N );
}
   
int main()
{
    const int N = 5;
    
    int* ipArray[3];

    for( int i = 0; i < 3; i++ )
    {
        ipArray[i] = new int [ N ];
    }

    int* walker = ipArray[ 0 ];
    
    assign_and_print( walker, N );
    
    walker = ipArray[ 1 ];
    assign_and_print( walker, N, 10 );
    
    walker = ipArray[ 2 ];
    assign_and_print( walker, N, 20 );
    
    cout << endl;
    
    //suppose to print out result
    for( size_t rows = 0; rows < 3; rows++ )
    {
        walker = ipArray[ rows ];
        for( size_t cols = 0; cols < 5; cols++)
        {
            cout << walker[ cols ] << " ";
        }
        cout << endl;
    }

    delete [] ipArray[0];
    delete [] ipArray[1];
    delete [] ipArray[2];

    cout << endl << endl << endl << "END!" << endl;

    return 0;
}
0 1 2 3 4 
10 11 12 13 14 
20 21 22 23 24 

0 1 2 3 4 
10 11 12 13 14 
20 21 22 23 24 


This can actually be simplified again, you should avoid very long lines of code ( make a function instead if it is repeatedly done or simplify it if it exceeds to about 25 lines )

pheww
Last edited on
@nvrmnd

Why does everyone on this forum feel the need to overcomplicate everything

Does PaddlePow really need 4 functions to learn about pointers ?

why use the size_t data type ? Is PaddlePow going to be mass producing this program and needs to save 2 bytes ?

Clearly they are trying to learn about pointers so why not explain things about the pointers instead of adding more complexity to a program they are already struggling with ?


Sighh, okay if it is what you want :

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
#include <iostream>

using namespace std;

int main()
{
    int* ipArray[3];

    for(int i = 0; i < 3; i++)
    {
        ipArray[i] = new int [5];
    }

    int* walker;

    walker = ipArray[0];

    for(int i = 0; i < 5; i++)
    {
        walker[ i ] = i;

        cout << walker[ i ] << " ";
    }

    cout<<endl;

    walker = ipArray[1];

    for(int i = 0; i < 5; i++)
    {
        walker[ i ] = i + 10;

        cout << walker[ i ] << " ";
    }

    cout<<endl;

    walker = ipArray[2];

    for(int i = 0; i < 5; i++)
    {
        walker[ i ] = i+20;

        cout << walker[ i ] << " ";
    }

    cout<<endl<<endl;

    //suppose to print out result
    for(int rows = 0; rows < 3; rows++)
    {
        walker = ipArray[ rows ];
        for(int cols = 0; cols < 5; cols++)
            cout<<walker[ cols ] <<" ";
        cout<<endl;
    }

    delete [] ipArray[0];
    delete [] ipArray[1];
    delete [] ipArray[2];

    cout <<endl<<endl<<endl<< "END!" << endl;

    cout<<endl;

    return 0;
}


LOL, Ok, You might be right that it is indeed an overkill for a homework, but there was nothing wrong in saying what should be the proper way.

PaddlePow, you can view my other answer as a recommendation, someday, i hope you will find it useful
Last edited on
Hey
I realise you were trying to help and your code would be helpful if they werent learning and Just wanted to improve their code.
Its just i was learning not too long ago(still realllly far from being an expert on the subject though) and it just makes it more difficult to learn something when new concepts are added and not specified if they are necessary or not.
Sorry if i seemed like a ****. :)

Also wouldnt using unsigned char be more efficient than size_t ?
Well, it's okay. I am no expert also, i consider myself a novice programmer.

Also wouldnt using unsigned char be more efficient than size_t ?

Well, it depends

size_t, btw, is an alias for unsigned int
Last edited on
nvrmnd wrote:
size_t, btw, is an alias for unsigned int

Sometimes. On my compiler, size_t is an alias for unsigned long. size_t (AFAIK) is defined to be any unsigned integral type. It is normally used with arrays and the like, hence the name (size_t). Using size_t can sometimes make your code more clear, and specifies more explicitly what it is that you are doing.

Also, using functions just makes sense. Even when learning, it is better to put things in functions, as not only does it prevent code duplication, functions have names. This is good because it means that if you don't comment your code, when you look over your code some time in the future to work out what it was you can easily see that this code prints, this code assigns, etc., and use those functions in other code.

EDIT:
jidder wrote:
Also wouldnt using unsigned char be more efficient than size_t ?

Not really. It would make an almost imperceptible difference to the speed of the program, and unless you are REALLY constrained for memory using 1 byte instead of 4 makes no difference, when you consider that you pretty much always have at least 1 MiB (1,048,576 bytes), three bytes isn't going to make a difference.
Last edited on
NT3 wrote:

Also, using functions just makes sense. Even when learning, it is better to put things in functions, as not only does it prevent code duplication, functions have names.

If they were just learning pointers, then functions might literally not make sense, as its unlikely they will know how pointers are passed to functions and how they are different than values passed byValue.
Typically this will be the next lesson after just learning how pointers work in a single function i.e main.

NT3 wrote:

This is good because it means that if you don't comment your code, when you look over your code some time in the future to work out what it was you can easily see that this code prints, this code assigns, etc., and use those functions in other code.

Surely commenting code is better practice than creating functions purely for readability ?
And do you often use functions and code from your practice programs that you made when you were first learning the language ?

Surely its also good practice to use the smallest most efficient data type and i only suggested using char as nvrmd suggested using size_t instead of an int.

Just my opinion :)
jidder wrote:
If they were just learning pointers, then functions might literally not make sense

Perhaps. I'll agree with that, just putting it out there that functions should preferably be used.

jidder wrote:
Surely commenting code is better practice than creating functions purely for readability ?

Sort of. No matter how well a code is commented, you have to spend time reading the comments and processing the code to understand that it is the same thing being done there, just perhaps with different variable names. Functions also allow you to skim through a routine or algorithm and see what it does without the details, which also improves readability.

And do you often use functions and code from your practice programs that you made when you were first learning the language?

Yes. At the very least, even if I don't use the function verbatim, I often look over the functions to see what the algorithm did, so I don't have to work out the algorithm again and can instead focus on optimizing the algorithm with the knowledge I have gained in the meantime.

jidder wrote:
Surely its also good practice to use the smallest most efficient data type

Not really. When programming, the thing that is primary is getting the program to work. Efficiency is secondary, and this case doesn't really improve efficiency anyway. It is good to use fairly large data types as well, simply because that way there is no chance of an overflow or the like if you suddenly require to use bigger numbers. If, after having completed your program and your profiler tells you that that something is a bottleneck in terms of performance or memory usage, THEN you can optimize, but only then.
Last edited on
NT3 wrote:

Yes. At the very least, even if I don't use the function verbatim, I often look over the functions to see what the algorithm did, so I don't have to work out the algorithm again and can instead focus on optimizing the algorithm with the knowledge I have gained in the meantime.

You honestly reuse code from programs that you made when first learning the language ?
So when you were first learning about pointers and made a simple program, you still go back and use functions from it ?
i find it unlikely.
Perhaps on newer programs you make, but i doubt it on practice learning ones.



NT3 wrote:
Not really. When programming, the thing that is primary is getting the program to work. Efficiency is secondary, and this case doesn't really improve efficiency anyway. It is good to use fairly large data types as well, simply because that way there is no chance of an overflow or the like if you suddenly require to use bigger numbers. If, after having completed your program and your profiler tells you that that something is a bottleneck in terms of performance or memory usage, THEN you can optimize, but only then
.

im not an expert programmer.
But i have to deal with programs other people have made in my job.
Say i make a program with ten million lines of code.
It works as intended.
But it uses 99% cpu
Having to go through all the code again is a waste of time and resources.

Im not saying that you should be cutting every corner you can to save space.
But if you can easily use a smaller data type or reduce the size of a function(or save space in any way) in an easy way which isnt going to impact the program then you should.

Why not just use long long ints for everything incase you suddenly require huge numbers ?

Also i realise in this case it does nothing, but its good practice to get into.



jidder wrote:
It works as intended.
But it uses 99% cpu
Having to go through all the code again is a waste of time and resources.

Thats why profilers exist. You don't have to go through the whole code, just the sections of the code that require optimization. Also, I'm not talking about efficient 'design' here, I'm talking about the little things that people insist on using that make their life harder, even though they would be more productive otherwise (like using C-strings rather than std::string, or making their own linked list instead of std::list). Efficient design is a completely different matter, however. It requires you planning your code and its structure to be inherently efficient, as well as being productive and preventing code duplication or dodgy workarounds.

jidder wrote:
Why not just use long long ints for everything incase you suddenly require huge numbers?

You probably could, until you realize that for certain tasks you are never (as in, its not actually possible) are going to use those numbers. For most cases, long (or size_t) are perfectly sufficient. At any rate, only don't have integers that size unless you are certain you won't need it, or you know for sure that it would have a noticable impact on your program (e.g. using an array of unsigned long long when you know that unsigned char is all thats needed). Otherwise, sure, do what you like. Just to make myself clear, I wasn't saying that the use of unsigned char in that situation was bad, just that there is no reason NOT to use size_t.
Topic archived. No new replies allowed.