Thread: Sorting a 2d vector, pointer trouble

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    16

    Sorting a 2d vector, pointer trouble

    Hi. Iīm kinda new to the pointer and multidimensional arrays. I need an input for the number and dimensions of an array. Than scan these and, sort the vectors and print them again. Only, every time I run the programm, it gets stuck and stops.

    Hereīs my code
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    void swap (double **p, double **q);                             /* wissel de pointer waardes om */
    double length (double v[], int dim);                            /* bepaal de lengtes van de vectoren */
    
    int main (void)
    {
        static int dim, num;
        int i, j;
        double **w, *v;
    
        scanf ("%d %d", &dim, &num);                                /* read N and M */
        w = calloc (num, sizeof (double *));                        /* allocate array of M pointers */
        v = calloc (num, sizeof (double ));
    
        for (i = 0; i < num; i++)
        {
            /* allocate space for N dimensional vector */
            w[i] = calloc (dim, sizeof (double));
            /* read the vector */
            for (j = 0; j < dim; j++)
            {
                scanf ("%le", &w[i][j]);
            }
        }
    
        for (i = 0; i < num; i++){
            v[i] = length(w[i], dim);
        }
    
      /* acces the lengths and swap length and w vector in order*/
        for (i = 0; i < num - 1; ++i){
            for (j = num - 1; j > i; --j){
                    if (v[j-1] > v[j])
                    {
                        swap(&w[j-1], &w[j]);
                    }
            }
        }
    
        for (i = 0; i < num; ++i){
            for(j = 0; j < dim; ++j){
                printf("%le", w[i][j]);
            }
        }
    
        return 0;
    }
    
    void swap(double **p, double **q)
    {
        double *tmp = 0;
    
        *tmp = **p;
        **p = **q;
        **q = *tmp;
    }
    
    double length (double v[], int dim)
    {
        int i;
        double wl = 0.0;
    
        for (i = 0; i < dim; ++i)
            {
                wl += ((v[i]) * (v[i]));
            }
            wl = sqrt(wl);
    
        return wl;
    }
    Iīve been stuck on this for quite a while. Thanks in advance!

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Try printing out using %lf. Also put a space after it. Also I would suggest putting in a new-line so that the output looks more like a matrix...
    Code:
        for (i = 0; i < num; ++i){ 
            for(j = 0; j < dim; ++j){ 
                printf("%lf ", w[i][j]); 
            } 
        printf("\n");
        }
    You might want to look into making sure the output gets shown before the window disappears which is what I think is happening.

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    I changed the printing part to

    Code:
        for (i = 0; i < num; i++){
            for(j = 0; j < dim; j++){
                printf("%lf ", w[i][j]);
            }
            printf("\n");
        }
    so itīll also print more in a matrix, but it gives back only zeros. Also the assignment is in scientific notation, but that is the least of my worries right now, but thanks, the printing seems neater now

  4. #4
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I would use %lf in the scanf. I don't know what %le does.

  5. #5
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    The scanf part was the bit that was assigned as a task to us, so that should be righ. It scans in as a long e notation, so the scientific 0.0000000e00

  6. #6
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    In swap() you declare tmp and point it to 0 (NULL). You then attempt to dereference tmp and assign a value to the address of 0. All you need to do is swap pointers, not values. Try
    Code:
    tmp = *p ;
    and so on.

  7. #7
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    Iīm sorry, that was actually the part that I already changed whilst waiting for reply, and it still doesnīt work. Hereīs the code I have currently

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    void swap (double **p, double **q);                             /* wissel de pointer waardes om */
    double length (double v[], int dim);                            /* bepaal de lengtes van de vectoren */
    
    
    int main (void)
    {
        static int dim, num;
        int i, j;
        double **w, *v;
    
        scanf ("%d %d", &dim, &num);                                /* read N and M */
        w = calloc (num, sizeof (double *));                        /* allocate array of M pointers */
        v = calloc (num, sizeof (double ));
    
        for (i = 0; i < num; i++)
        {
            /* allocate space for N dimensional vector */
            w[i] = calloc (dim, sizeof (double));
            /* read the vector */
            for (j = 0; j < dim; j++)
            {
                scanf ("%lf", &w[i][j]);
            }
        }
    
        for (i = 0; i < num; i++){
            v[i] = length(w[i], dim);
        }
    
      /* acces the lengths and swap length and w vector in order*/
        for (i = 0; i < num - 1; ++i){
            for (j = num - 1; j > i; --j){
                    if (v[j-1] > v[j])
                    {
                        swap(&w[j-1], &w[j]);
                    }
            }
        }
    
        for (i = 0; i < num; i++){
            for(j = 0; j < dim; j++){
                printf("%lf ", w[i][j]);
            }
            printf("\n");
        }
    
        return 0;
    }
    
    void swap(double **p, double **q)
    {
        double *tmp;
    
        tmp = *p;
        *p = *q;
        *q = tmp;
    }
    
    double length (double v[], int dim)
    {
        int i;
        double wl = 0.0;
    
        for (i = 0; i < dim; ++i)
            {
                wl += ((v[i]) * (v[i]));
            }
            wl = sqrt(wl);
    
        return wl;
    }

  8. #8
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    What does "it doesn't work" mean? It works for me just fine now. Are the results not as expected? If so, what is your sample data?

    By the way, whenever you dynamically allocate memory, there is a chance at failure. Whenever there is a chance of failure on something, you should be checking for it. So check that every call to calloc doesn't return NULL.

  9. #9
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    At first it didnīt finish the program at all. Now it only returns 0īs, while I need the scanned values, but I canīt find anything wrong with the scan or print functions. Iīll check the callocs, u mean by using assert?

  10. #10
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    I inserted the asserts, but the outcome of the code did not change.

    My program once more:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <assert.h>
    
    void swap (double **p, double **q);                             /* wissel de pointer waardes om */
    double length (double v[], int dim);                            /* bepaal de lengtes van de vectoren */
    
    
    int main (void)
    {
        static int dim, num;
        int i, j;
        double **w, *v;
    
        scanf ("%d %d", &dim, &num);                                /* read N and M */
        w = calloc (num, sizeof (double *));                        /* allocate array of M pointers */
        assert (w != NULL);
        v = calloc (num, sizeof (double ));
        assert (v != NULL);
    
        for (i = 0; i < num; i++)
        {
            /* allocate space for N dimensional vector */
            w[i] = calloc (dim, sizeof (double));
            assert (w[i] != NULL);
            /* read the vector */
            for (j = 0; j < dim; j++)
            {
                scanf ("%lf", &w[i][j]);
            }
        }
    
        for (i = 0; i < num; i++){
            v[i] = length(w[i], dim);
        }
    
      /* acces the lengths and swap length and w vector in order*/
        for (i = 0; i < num - 1; ++i){
            for (j = num - 1; j > i; --j){
                    if (v[j-1] > v[j])
                    {
                        swap(&w[j-1], &w[j]);
                    }
            }
        }
    
        for (i = 0; i < num; i++){
            for(j = 0; j < dim; j++){
                printf("%lf ", w[i][j]);
            }
            printf("\n");
        }
    
        return 0;
    }
    
    void swap(double **p, double **q)
    {
        double *tmp;
    
        tmp = *p;
        *p = *q;
        *q = tmp;
    }
    
    double length (double v[], int dim)
    {
        int i;
        double wl = 0.0;
    
        for (i = 0; i < dim; ++i)
            {
                wl += ((v[i]) * (v[i]));
            }
            wl = sqrt(wl);
    
        return wl;
    }
    my input is:
    3 5
    4 4 4
    2 4 2
    1 1 9
    -1 -2 5
    1 1 1

    and my output should then be

    1.00000e+00 1.00000e+00 1.00000e+00
    2.00000e+00 4.00000e+00 2.00000e+00
    -1.00000e+00 -2.00000e+00 5.00000e+00
    4.00000e+00 4.00000e+00 4.00000e+00
    1.00000e+00 1.00000e+00 9.00000e+00

    I know I should change the lf to le then, but thats not my biggest concern at the moment. My concern is, my output is:
    0.00000e+00 0.00000e+00 0.00000e+00
    0.00000e+00 0.00000e+00 0.00000e+00
    0.00000e+00 0.00000e+00 0.00000e+00
    0.00000e+00 0.00000e+00 0.00000e+00
    0.00000e+00 0.00000e+00 0.00000e+00

  11. #11
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    New and improved code:

    Code:
    void swap (double **p, double **q);                             /* wissel de pointer waardes om */
    double length (double v[], int dim);                            /* bepaal de lengtes van de vectoren */
    
    int main (void)
    {
        static int dim, num;
        int i, j;
        double **w, *v;
    
        scanf ("%d %d", &dim, &num);                                /* read N and M */
        w = calloc (num, sizeof (double *));                        /* allocate array of M pointers */
        assert (w != NULL);
        v = calloc (num, sizeof (double ));
        assert (v != NULL);
    
        for (i = 0; i < num; i++)
        {
            /* allocate space for N dimensional vector */
            w[i] = calloc (dim, sizeof (double));
            assert (w[i] != NULL);
            /* read the vector */
            for (j = 0; j < dim; j++)
            {
                scanf ("%le", &w[i][j]);
            }
        }
    
        for (i = 0; i < num; i++){
            v[i] = length(w[i], dim);
        }
    
      /* acces the lengths and swap length and w vector in order*/
        for (i = 0; i < num - 1; ++i){
            for (j = num - 1; j > i; --j){
                    if (v[j-1] > v[j])
                    {
                        swap(&w[j-1], &w[j]);
                        swap(&v[j-1], &v[j]);
                    }
            }
        }
    
        for (i = 0; i < num; i++){
            for(j = 0; j < dim; j++){
                printf("%e ", w[i][j]);
            }
            printf("\n");
        }
    
        return 0;
    }
    
    void swap(double **p, double **q)
    {
        double *tmp;
    
        tmp = *p;
        *p = *q;
        *q = tmp;
    }
    
    double length (double v[], int dim)
    {
        int i;
        double wl = 0.0;
    
        for (i = 0; i < dim; ++i)
            {
                wl += ((v[i]) * (v[i]));
            }
            wl = sqrt(wl);
    
        return wl;
    }
    I tested the scanning, it works now, the printing is fine as well. Even the calculating of the vector length works. The problem is that the vector gets sorted, but kinda half baked. The problem has to be in the bubble sort or the swap, can anyone help???

  12. #12
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    for clarity, my outcome is:
    2.00000e+000 4.00000e+000 2.00000e+000
    4.00000e+000 4.00000e+000 4.00000e+000
    1.00000e+000 1.00000e+000 9.00000e+000
    1.00000e+000 1.00000e+000 1.00000e+000
    -1.00000e+000 -2.00000e+000 5.00000e+000

  13. #13
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    You can't use swap() on v[] as it is an array of doubles, not double pointers. Do you need 2 separate arrays or can you just eliminate v[] and calloc dim+1 for w[]? Then one element is reserved for the length and is bound to the data when you swap.

  14. #14
    Registered User
    Join Date
    Apr 2011
    Posts
    16
    Thank you so much! It works now!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Having trouble sorting an Array that has a zero in it.
    By Cgmgator in forum C Programming
    Replies: 17
    Last Post: 06-29-2011, 09:19 PM
  2. sorting a vector
    By acosgaya in forum C++ Programming
    Replies: 3
    Last Post: 01-09-2008, 12:30 PM
  3. Trouble sorting a list
    By pliang in forum C++ Programming
    Replies: 1
    Last Post: 07-17-2005, 06:54 AM
  4. Trouble with array sorting
    By dcj1978 in forum C++ Programming
    Replies: 3
    Last Post: 09-19-2003, 12:16 PM
  5. Sorting STL vector
    By TonyP in forum C++ Programming
    Replies: 7
    Last Post: 02-10-2003, 04:38 PM