Thread: Number Sorting Issue... again

  1. #1
    Registered User
    Join Date
    Feb 2017
    Posts
    11

    Number Sorting Issue... again

    We were given an assignment with some code already built in that reads a file with a list of student ID numbers (1-46) and 5 of their grades on exams. Problem one is to design a function that averages those grades out. The second part is to sort them along with their ID number in descending order.

    Code:
    // ECE103 Homework 5
    
    #define _CRT_SECURE_NO_WARNINGS
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void sort(int b[46], int mat[46][2])
    {
        float temp1, temp2;
        int k;
    
        for (int m = 0; m <= 46; m++)
        {
            for (k = 0; k <= 46; k++)
            {
                if (b[k] < b[m])
                {
                    temp1 = b[m];
                    b[m] = b[k];
                    b[k] = temp1;
    
                    temp2 = mat[m][0];
                    mat[m][0] = mat[k][0];
                    mat[k][0] = temp2;
                }
            }
        }
        for (int m = 0; m <= 46; ++m) {
            printf("%4d %4d\n", mat[m][0], mat[k][1]);
        }
    }
    
    float average(int a[6])
    {
        int j;
        float sum = 0;
        for (j = 1; j <= 5; j++)
        {
            sum = sum + a[j];
        }
        sum = sum/ 5;
    
        return(sum);
    }
    
    
    
    int main(void) {
    
        //declare variables
        FILE *data_file;
        char filename[] = "dataAssignments.txt";
        char comma;
        int i, j;
        int num_students = 46;
        int num_grades = 5;
        int temp;
        //function average variables
    
        //initialize matrix
        int mat[46][6] = { 0 }; // 46 rows for students, 1 column for ID, and  5 columns for assignments  
    
        //open file for reading
        data_file = fopen(filename, "r");
    
        //print an error and end program if file cannot be opened
        if (data_file == 0) {
            printf("Error opening file: %s", filename);
            return(-1);
        }
    
        //read file by moving left to right in each row
        //then moving to the next row
        for (i = 0; i < num_students; i++) 
        {
            for (j = 0; j <= num_grades; j++) // first column is for ID, hence, <=
            {
                fscanf(data_file, "%d", &temp);
                fscanf(data_file, "%c", &comma);
                mat[i][j] = temp;
            }
        }
    
        //close the file
        fclose(data_file);
    
        //debugging code to print multidimensional array after it
        //is read from the file
        
        int b[46];
        
        for (i = 0; i < num_students; i++) 
        {
            for (j = 0; j <=num_grades; j++) 
            {
                printf("%4d ", mat[i][j]);
            }
        printf("%g\n", average(mat[i])); ///ADDED CODE HERE
    }
        
        /*  WRITE YOUR CODE BELOW   */
        
        
        sort(b[46], mat[46][2]);
    
        /*  WRITE YOUR CODE ABOVE   */
    
        getchar();
        return(0);
    }

    When I run it it breaks at line 17 and 105. I think the issue is that the for loops in the sort function are both starting at 0, at least for line 17.

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    This line is likely the problem.

    Code:
    sort(b[46], mat[46][2]);
    I suggest brushing up on how to call functions.

    My guess is

    Code:
    sort(b, mat);
    It really is a guess; I never really found a time to use 2 dim arrays in C.
    Never saw a real world problem that needed it.

    Tim S.
    Last edited by stahta01; 03-03-2017 at 07:07 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    The sort function is also garbage; I hope the instructor did NOT write it thinking it was good code.

    Code:
    for (int m = 0; m <= 46; m++)
    For a 46 element array in C the valid indexes are 0 to 45; this means this code will likely crash when it tries index 46. But, it could also do nothing at all.

    Edit: This is the first of many problems in the sort function. I dread magic number programmers.
    Magic number (programming) - Wikipedia

    Tim S.
    Last edited by stahta01; 03-03-2017 at 07:54 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  4. #4
    CIS and business major
    Join Date
    Aug 2002
    Posts
    287
    Just briefly looking at your code:

    b[k] = temp1;

    Aren't you trying to set an int[] to a float? They are two different types of variables.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    No, you just read it wrong. Assignment works from right to left. b[k] would be type int, because it's a particular integer in the array.

    What happens when you assign a float to an int is well-defined, too, there's no problem with that. It's just bad design because you shouldn't need a float - a bigger number type - just to move numbers around.
    Last edited by whiteflags; 03-03-2017 at 11:35 PM.

  6. #6
    Registered User
    Join Date
    Feb 2017
    Posts
    11
    For sure. Thanks for the advice, everyone. And yeah, calling functions is something I could use more practice with.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by whiteflags View Post
    It's just bad design because you shouldn't need a float - a bigger number type - just to move numbers around.
    Bigger in some sense, potentially smaller in another. If both int and float are 32-bits, then you could loose precision putting an int into a float since the float needs some bits for its mantissa (as well as a totally separate sign bit as opposed to the 2's complement scheme).

    In fact a single-precision float only has 23-bits for the "fractional" part (effectively 24 since a leading 1 bit is implied), 8-bits for the exponent and 1 for the sign.
    Code:
    #include <stdio.h>
    #include <limits.h>
    
    int main() {
        int n;
        float f;
    
        printf("Sizes:  n: %zu  f: %zu\n", sizeof n, sizeof f);
    
        n = 1000;
        printf("\nn before: %d\n", n);
        f = n;
        printf("f       : %f\n", f);
        n = f;
        printf("n after : %d\n", n);
    
        n = INT_MAX / 2;
        printf("\nn before: %d\n", n);
        f = n;
        printf("f       : %f\n", f);
        n = f;
        printf("n after : %d\n", n);
    
        n = INT_MAX;
        printf("\nn before: %d\n", n);
        f = n;
        printf("f       : %f\n", f);
        n = f;
        printf("n after : %d\n", n);
    
        n = 0x4000000f;
        printf("\nn before: %d\n", n);
        f = n;
        printf("f       : %f\n", f);
        n = f;
        printf("n after : %d\n", n);
    
        return 0;
    }
    Output for me:
    Code:
    Sizes:  n: 4  f: 4
    
    n before: 1000
    f       : 1000.000000
    n after : 1000
    
    n before: 1073741823
    f       : 1073741824.000000
    n after : 1073741824
    
    n before: 2147483647
    f       : 2147483648.000000
    n after : -2147483648
    
    n before: 1073741839
    f       : 1073741824.000000
    n after : 1073741824
    Last edited by algorism; 03-04-2017 at 10:55 AM.

  8. #8
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Another program to play with. Output:
    Code:
    Sizes:  n: 4  f: 4
    
    n before:  2147483647
    Bits    : 01111111 11111111 11111111 11111111 
    f       :  2147483648
    Bits    : 01001111 00000000 00000000 00000000 
    Sign    :           0
    Exponent:         158
    Fraction:           0
    n after : -2147483648
    
    n before:  1073741887
    Bits    : 01000000 00000000 00000000 00111111 
    f       :  1073741824
    Bits    : 01001110 10000000 00000000 00000000 
    Sign    :           0
    Exponent:         157
    Fraction:           0
    n after :  1073741824
    The first case is rounded up (by 1) which then overflows the int and yields INT_MIN (on our common 2's complement machines).
    The second case is rounded down (by 63!).

    Recall that the fraction generally has an implicit 1 in front of the represented bits (all the represented bits generally considered to be to the right of the binary point) and the exponent is excess-127, so you need to subtract 127 from it, e.g., 157-127 = 30, so the second number is 2 to the power of 30. (The overall rules are more complicated, of course.)

    Code:
    #include <stdio.h>
    #include <limits.h>
    
    // Return n bits from pos. p down to pos. p-n+1
    unsigned getbits(unsigned x, int p, int n) {
        return (x >> (p-n+1)) & ~(~0 << n);
    }
    
    void bits_u(unsigned u) {
        unsigned mask = ~0u ^ (~0u >> 1);
        for (int n = 0; mask; mask >>= 1, n++) {
            putchar('0' + !!(u & mask));
            if (n % 8 == 7) putchar(' ');
        }
        putchar('\n');
    }
    
    void bits_f(float f) {
        unsigned u = *(unsigned*)&f;
        bits_u(u);
        printf("Sign    : %11u\n", getbits(u, 31,  1));
        printf("Exponent: %11u\n", getbits(u, 30,  8));
        printf("Fraction: %11u\n", getbits(u, 22, 23));
    }
    
    void n_to_f(int n) {
        float f;
        printf("\nn before: %11d\n", n);
        printf("Bits    : ");
        bits_u((unsigned)n);
        f = n;
        printf("f       : %11.0f\n", f);
        printf("Bits    : ");
        bits_f(f);
        n = f;
        printf("n after : %11d\n", n);
    }
    
    int main() {
        printf("Sizes:  n: %zu  f: %zu\n",
               sizeof(int), sizeof(float));
        n_to_f(INT_MAX);
        n_to_f(0x4000003f); // worst case (7 low bits lost)
        return 0;
    }
    Last edited by algorism; 03-04-2017 at 12:37 PM.

  9. #9
    Registered User
    Join Date
    Feb 2017
    Posts
    11
    Alright, I've re-approached the problem and scrapped the portion of the program that was my instructor's since the advanced language was only serving to confuse me. I've avoided the breaking issues that were coming with my previous code and managed to get an output. The issue is now that the numbers are printing wrong. What I'm trying to do with the sort function is check if the subsequent average is larger than the previous and if so, swap the two as well as the index number that goes with them (first column in mat[][]).

    Code:
    #include <stdio.h>
    
    float average(int avg[6]) 
    {
        int j;
        float sum = 0;
        for (j = 1; j <= 5; j++)
        {
            sum = sum + avg[j];
        }
        sum = sum / 5;
    
        return(sum);
    
    }
    
    void sort(int sorta[46],int sortb[46])
    {
        float temp1;
        int temp2;
        
        for (int i = 0; i <= 45; i++)
        {
            if (sortb[i] < sortb[i + 1])
            {
                temp1 = sortb[i];
                sortb[i] = sortb[i+1];
                sortb[i + 1] = temp1;
    
                temp2 = sorta[i];
                sorta[i] = sorta[i + 1];
                sorta[i + 1] = temp2;
            }
        }
        for (int i = 0; i <= 45; i++)
        {
            printf("%4i %4d\n", sorta[i], sortb[i]);
        }
    }
    
    int main(void)
    {
        int mat[46][6] = { 
        { 1,82,45,53,55,69 },
        {2,91,65,78,14,18},
        {3,12,71,94,86,37},
        {4,92,76,13,62,63},
        {5,63,27,57,35,78},
        {6,9,68,47,51,8},
        {7,28,66,1,40,93},
        {8,55,16,34,7,78},
        {9,96,12,16,24,49},
        {10,97,50,80,12,44},
        {11,15,96,31,18,45},
        {12,98,34,53,24,30},
        {13,96,59,16,42,51},
        {14,49,22,60,5,51},
        {15,80,75,26,91,82},
        {16,14,25,66,95,80},
        {17,42,51,69,49,65},
        {18,92,70,75,49,38},
        {19,80,89,45,34,81},
        {20,96,96,8,90,53},
        {21,66,55,23,37,35},
        {22,3,14,92,11,94},
        {23,85,15,15,78,88},
        {24,94,26,83,39,55},
        {25,68,84,54,24,62},
        {26,76,25,100,40,59},
        {27,75,82,7,9,20},
        {28,39,24,44,13,30},
        {29,66,93,10,95,47},
        {30,17,35,97,96,23},
        {31,71,19,0,58,85},
        {32,3,25,78,6,19},
        {33,27,62,82,23,22},
        {34,4,47,87,35,17},
        {35,9,35,8,82,22},
        {36,83,83,40,1,44},
        {37,70,59,26,4,31},
        {38,32,55,80,17,93},
        {39,95,92,43,65,43},
        {40,3,28,91,73,18},
        {41,44,76,18,65,91},
        {42,38,76,26,45,98},
        {43,77,38,14,55,44},
        {44,80,57,13,29,11},
        {45,18,7,87,75,26},
        {46,49,5,58,19,41} };
    
        int i, j;
    //Print first matrix with averages
        for (i = 0; i <= 45; i++)
        {
            for (j = 0; j <= 5; j++)
            {
                printf("%4d ", mat[i][j]);
    
            }
            printf("%g \n", average(mat[i])); 
        }
    //Assemble average into 46 array to be sent to function
        int avg[46];
    
            for (i = 0; i <= 45; i++)
            {
                avg[i] = average(mat[i]);
            }
    
            sort(mat, avg);
    
    
    
        getchar();
        return(0);
    }

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    So, you want to arrange the matrix such that the lowest average row is first, followed by the second lowest, and third lowest, and so on.

    You can't trivially swap arrays in C, at a minimum you need this:
    Code:
    void swapArray(int *A, int *B, size_t n)
    {
       size_t i;
       for (i = 0; i < n; i++)
       {
          int temp = A[i];
          A[i] = B[i];
          B[i] = temp;
       }
    }
    Now instead of manipulating mat directly, call swap(sorta[i],sorta[i + 1],6);

    Altho stahta01 has a point about magic numbers...
    Last edited by whiteflags; 03-04-2017 at 06:51 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Number Sorting Function Issue
    By rklein in forum C Programming
    Replies: 3
    Last Post: 03-02-2017, 10:04 PM
  2. sorting values in array issue
    By LATCH808 in forum C++ Programming
    Replies: 1
    Last Post: 02-08-2015, 08:35 PM
  3. Sorting issue...
    By alphasil in forum C Programming
    Replies: 3
    Last Post: 07-12-2012, 03:58 PM
  4. Sorting issue
    By Ssalty in forum C++ Programming
    Replies: 1
    Last Post: 05-18-2011, 10:03 AM
  5. compare issue while sorting
    By Micko in forum C++ Programming
    Replies: 1
    Last Post: 03-06-2004, 10:34 AM

Tags for this Thread