Counting sort in C

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












EDIT: I have posted a follow-up to this question.



I have implemented counting sort in C. This program takes its input as integers from command line arguments, sorts the integers with counting sort, then outputs the sorted array.



This is my first attempt at implementing this and I would really like to see what I could do better in this code.



#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int max(int* arr, int len)
int out = arr[0];
for (int i = 0; i < len; i++)
if (arr[i] > out)
out = arr[i];
return out;


void sort(int** in, int** out, size_t length)
int* inputs = *in;
int* outputs = *out;

// this is the size of the array of counts
int greatest = max(inputs, length); // find the greatest number in the array

// allocate the array of counts
int* counts = calloc(greatest + 1, sizeof(int));

// count numbers in input array
for (int i = 0; i < length; i++)
counts[inputs[i]]++;


int counter = 0; // keep track of where we are in output array

// loop through all the counts
for (int i = 0; i < (greatest + 1); i++) // for every count in array
for (int j = 0; j < counts[i]; j++) // loop that many times
outputs[counter++] = i; // add the integer being counted to the output array


free(counts);


int main(int argc, char** argv)
int *inputs, *outputs;
size_t length = argc - 1; // number of integers to sort
inputs = malloc(sizeof(int) * (argc - 1));
outputs = malloc(sizeof(int) * (argc - 1));

for (int i = 1; i < argc; i++)
inputs[i - 1] = atoi(argv[i]); // assign arguments to array


sort(&inputs, &outputs, length);

for (size_t i = 0; i < (length); i++)
printf("%d ", outputs[i]); // print space separated sorted numbers

printf("n");

free(inputs);
free(outputs);

return 0;







share|improve this question



























    up vote
    3
    down vote

    favorite












    EDIT: I have posted a follow-up to this question.



    I have implemented counting sort in C. This program takes its input as integers from command line arguments, sorts the integers with counting sort, then outputs the sorted array.



    This is my first attempt at implementing this and I would really like to see what I could do better in this code.



    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>

    int max(int* arr, int len)
    int out = arr[0];
    for (int i = 0; i < len; i++)
    if (arr[i] > out)
    out = arr[i];
    return out;


    void sort(int** in, int** out, size_t length)
    int* inputs = *in;
    int* outputs = *out;

    // this is the size of the array of counts
    int greatest = max(inputs, length); // find the greatest number in the array

    // allocate the array of counts
    int* counts = calloc(greatest + 1, sizeof(int));

    // count numbers in input array
    for (int i = 0; i < length; i++)
    counts[inputs[i]]++;


    int counter = 0; // keep track of where we are in output array

    // loop through all the counts
    for (int i = 0; i < (greatest + 1); i++) // for every count in array
    for (int j = 0; j < counts[i]; j++) // loop that many times
    outputs[counter++] = i; // add the integer being counted to the output array


    free(counts);


    int main(int argc, char** argv)
    int *inputs, *outputs;
    size_t length = argc - 1; // number of integers to sort
    inputs = malloc(sizeof(int) * (argc - 1));
    outputs = malloc(sizeof(int) * (argc - 1));

    for (int i = 1; i < argc; i++)
    inputs[i - 1] = atoi(argv[i]); // assign arguments to array


    sort(&inputs, &outputs, length);

    for (size_t i = 0; i < (length); i++)
    printf("%d ", outputs[i]); // print space separated sorted numbers

    printf("n");

    free(inputs);
    free(outputs);

    return 0;







    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      EDIT: I have posted a follow-up to this question.



      I have implemented counting sort in C. This program takes its input as integers from command line arguments, sorts the integers with counting sort, then outputs the sorted array.



      This is my first attempt at implementing this and I would really like to see what I could do better in this code.



      #include <stdio.h>
      #include <unistd.h>
      #include <stdlib.h>

      int max(int* arr, int len)
      int out = arr[0];
      for (int i = 0; i < len; i++)
      if (arr[i] > out)
      out = arr[i];
      return out;


      void sort(int** in, int** out, size_t length)
      int* inputs = *in;
      int* outputs = *out;

      // this is the size of the array of counts
      int greatest = max(inputs, length); // find the greatest number in the array

      // allocate the array of counts
      int* counts = calloc(greatest + 1, sizeof(int));

      // count numbers in input array
      for (int i = 0; i < length; i++)
      counts[inputs[i]]++;


      int counter = 0; // keep track of where we are in output array

      // loop through all the counts
      for (int i = 0; i < (greatest + 1); i++) // for every count in array
      for (int j = 0; j < counts[i]; j++) // loop that many times
      outputs[counter++] = i; // add the integer being counted to the output array


      free(counts);


      int main(int argc, char** argv)
      int *inputs, *outputs;
      size_t length = argc - 1; // number of integers to sort
      inputs = malloc(sizeof(int) * (argc - 1));
      outputs = malloc(sizeof(int) * (argc - 1));

      for (int i = 1; i < argc; i++)
      inputs[i - 1] = atoi(argv[i]); // assign arguments to array


      sort(&inputs, &outputs, length);

      for (size_t i = 0; i < (length); i++)
      printf("%d ", outputs[i]); // print space separated sorted numbers

      printf("n");

      free(inputs);
      free(outputs);

      return 0;







      share|improve this question













      EDIT: I have posted a follow-up to this question.



      I have implemented counting sort in C. This program takes its input as integers from command line arguments, sorts the integers with counting sort, then outputs the sorted array.



      This is my first attempt at implementing this and I would really like to see what I could do better in this code.



      #include <stdio.h>
      #include <unistd.h>
      #include <stdlib.h>

      int max(int* arr, int len)
      int out = arr[0];
      for (int i = 0; i < len; i++)
      if (arr[i] > out)
      out = arr[i];
      return out;


      void sort(int** in, int** out, size_t length)
      int* inputs = *in;
      int* outputs = *out;

      // this is the size of the array of counts
      int greatest = max(inputs, length); // find the greatest number in the array

      // allocate the array of counts
      int* counts = calloc(greatest + 1, sizeof(int));

      // count numbers in input array
      for (int i = 0; i < length; i++)
      counts[inputs[i]]++;


      int counter = 0; // keep track of where we are in output array

      // loop through all the counts
      for (int i = 0; i < (greatest + 1); i++) // for every count in array
      for (int j = 0; j < counts[i]; j++) // loop that many times
      outputs[counter++] = i; // add the integer being counted to the output array


      free(counts);


      int main(int argc, char** argv)
      int *inputs, *outputs;
      size_t length = argc - 1; // number of integers to sort
      inputs = malloc(sizeof(int) * (argc - 1));
      outputs = malloc(sizeof(int) * (argc - 1));

      for (int i = 1; i < argc; i++)
      inputs[i - 1] = atoi(argv[i]); // assign arguments to array


      sort(&inputs, &outputs, length);

      for (size_t i = 0; i < (length); i++)
      printf("%d ", outputs[i]); // print space separated sorted numbers

      printf("n");

      free(inputs);
      free(outputs);

      return 0;









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jul 19 at 6:44
























      asked Jul 19 at 1:21









      Dmitry Kudriavtsev

      19811




      19811




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          4
          down vote



          accepted










          Why do you pass in and out to sort as int **? You only dereference them to get the underlying pointer. Just pass in the pointers (rather than the address of the pointers) and take the parameters as int *inputs and int *outputs.



          You don't check any of your memory allocations for errors.



          You do free up the memory you allocate, which is good.



          You don't validate your input values at all. If one of the numbers is negative Bad Things will happen when you clobber memory outside of what you've allocated.



          The test i < (greatest + 1) can be restated as i <= greatest.



          If I run the program with no parameters, you run into Undefined Behavior in your max function with arr[0].



          When allocating space for inputs and outputs in main, you use (argc - 1). You've already computed this and stored it in length, which you use elsewhere. You should use this length value when allocating memory for your arrays.






          share|improve this answer























          • I've revised my program to take care of most of these issues, where can I post the revised version?
            – Dmitry Kudriavtsev
            Jul 19 at 4:27






          • 1




            @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
            – Zeta
            Jul 19 at 5:51

















          up vote
          3
          down vote













          This is quite good so most of these comments are niggles / coding style. But...



          #include <stdio.h>
          #include <unistd.h>
          #include <stdlib.h>


          Put #includes in sorted order. If you have a lot of them, it makes it easier to find a header or spot duplicates, and it can help avoid manual merges in a version control system



          int max(int* arr, int len) 



          • I'd avoid that name. I've come across more than one C implementation that provides a max macro, causing great confusion



            int out = arr[0];
            for (int i = 0; i < len; i++)


          • That could be for (int i = 1; - the check below can never succeed for i = 0



          • Please don't omit the braces. People think that the compiler takes account of indenting. It doesn't. And this frequently leads to errors in maintenance (ref the goto fail bug).



             if (arr[i] > out)
            out = arr[i];
            return out;


            void sort(int** in, int** out, size_t length)
            int* inputs = *in;
            int* outputs = *out;


          • Why pass a pointer to a pointer then immediately dereference it



          • in should be a pointer to const, as you aren't altering it. (int const *)



            // this is the size of the array of counts
            int greatest = max(inputs, length); // find the greatest number in the array

            // allocate the array of counts
            int* counts = calloc(greatest + 1, sizeof(int));


          • unlike the other poster, I think calloc is appropriate here as you want zeroised memory and malloc is appropriate in the other places as you initialise them later.



          • You should check if you actually got memory allocated here



            // count numbers in input array
            for (int i = 0; i < length; i++)
            counts[inputs[i]]++;


            int counter = 0; // keep track of where we are in output array

            // loop through all the counts
            for (int i = 0; i < (greatest + 1); i++) // for every count in array
            for (int j = 0; j < counts[i]; j++) // loop that many times
            outputs[counter++] = i; // add the integer being counted to the output array



          • personally I'd avoid using auto-increments as part of an expression and make that two statements. I doubt the compiler would produce worse code, and it saves you having to work out whether the increment is done before or after the value is accessed.



             

            free(counts);


            int main(int argc, char** argv)
            int *inputs, *outputs;
            size_t length = argc - 1; // number of integers to sort


          • declare variables as close as possible to where you use them. These next two lines should be declarations


          • You don't check it the malloc was succesful



          • if argc is 1, then length is 0, and you'll attempt to allocate a very large amount of memory here



            inputs = malloc(sizeof(int) * (argc - 1));
            outputs = malloc(sizeof(int) * (argc - 1));

            for (int i = 1; i < argc; i++)
            inputs[i - 1] = atoi(argv[i]); // assign arguments to array


            sort(&inputs, &outputs, length);

            for (size_t i = 0; i < (length); i++)
            printf("%d ", outputs[i]); // print space separated sorted numbers

            printf("n");



          • arguably printf is overkill. You could use putchar('n') here



             free(inputs);
            free(outputs);

            return 0;



          • Well done for the last 3 lines (freeing up the memory and returning 0)! I've frequently seen one or both of those steps omitted.






          share|improve this answer





















          • It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
            – Toby Speight
            Jul 19 at 8:06










          • I thought that was only C++?
            – Tom Tanner
            Jul 19 at 10:01










          • Both C and C++.
            – Toby Speight
            Jul 19 at 10:06










          • ah, thanks. i'll remember that
            – Tom Tanner
            Jul 19 at 10:07










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f199789%2fcounting-sort-in-c%23new-answer', 'question_page');

          );

          Post as a guest






























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          4
          down vote



          accepted










          Why do you pass in and out to sort as int **? You only dereference them to get the underlying pointer. Just pass in the pointers (rather than the address of the pointers) and take the parameters as int *inputs and int *outputs.



          You don't check any of your memory allocations for errors.



          You do free up the memory you allocate, which is good.



          You don't validate your input values at all. If one of the numbers is negative Bad Things will happen when you clobber memory outside of what you've allocated.



          The test i < (greatest + 1) can be restated as i <= greatest.



          If I run the program with no parameters, you run into Undefined Behavior in your max function with arr[0].



          When allocating space for inputs and outputs in main, you use (argc - 1). You've already computed this and stored it in length, which you use elsewhere. You should use this length value when allocating memory for your arrays.






          share|improve this answer























          • I've revised my program to take care of most of these issues, where can I post the revised version?
            – Dmitry Kudriavtsev
            Jul 19 at 4:27






          • 1




            @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
            – Zeta
            Jul 19 at 5:51














          up vote
          4
          down vote



          accepted










          Why do you pass in and out to sort as int **? You only dereference them to get the underlying pointer. Just pass in the pointers (rather than the address of the pointers) and take the parameters as int *inputs and int *outputs.



          You don't check any of your memory allocations for errors.



          You do free up the memory you allocate, which is good.



          You don't validate your input values at all. If one of the numbers is negative Bad Things will happen when you clobber memory outside of what you've allocated.



          The test i < (greatest + 1) can be restated as i <= greatest.



          If I run the program with no parameters, you run into Undefined Behavior in your max function with arr[0].



          When allocating space for inputs and outputs in main, you use (argc - 1). You've already computed this and stored it in length, which you use elsewhere. You should use this length value when allocating memory for your arrays.






          share|improve this answer























          • I've revised my program to take care of most of these issues, where can I post the revised version?
            – Dmitry Kudriavtsev
            Jul 19 at 4:27






          • 1




            @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
            – Zeta
            Jul 19 at 5:51












          up vote
          4
          down vote



          accepted







          up vote
          4
          down vote



          accepted






          Why do you pass in and out to sort as int **? You only dereference them to get the underlying pointer. Just pass in the pointers (rather than the address of the pointers) and take the parameters as int *inputs and int *outputs.



          You don't check any of your memory allocations for errors.



          You do free up the memory you allocate, which is good.



          You don't validate your input values at all. If one of the numbers is negative Bad Things will happen when you clobber memory outside of what you've allocated.



          The test i < (greatest + 1) can be restated as i <= greatest.



          If I run the program with no parameters, you run into Undefined Behavior in your max function with arr[0].



          When allocating space for inputs and outputs in main, you use (argc - 1). You've already computed this and stored it in length, which you use elsewhere. You should use this length value when allocating memory for your arrays.






          share|improve this answer















          Why do you pass in and out to sort as int **? You only dereference them to get the underlying pointer. Just pass in the pointers (rather than the address of the pointers) and take the parameters as int *inputs and int *outputs.



          You don't check any of your memory allocations for errors.



          You do free up the memory you allocate, which is good.



          You don't validate your input values at all. If one of the numbers is negative Bad Things will happen when you clobber memory outside of what you've allocated.



          The test i < (greatest + 1) can be restated as i <= greatest.



          If I run the program with no parameters, you run into Undefined Behavior in your max function with arr[0].



          When allocating space for inputs and outputs in main, you use (argc - 1). You've already computed this and stored it in length, which you use elsewhere. You should use this length value when allocating memory for your arrays.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Jul 19 at 16:49


























          answered Jul 19 at 3:51









          1201ProgramAlarm

          2,4752618




          2,4752618











          • I've revised my program to take care of most of these issues, where can I post the revised version?
            – Dmitry Kudriavtsev
            Jul 19 at 4:27






          • 1




            @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
            – Zeta
            Jul 19 at 5:51
















          • I've revised my program to take care of most of these issues, where can I post the revised version?
            – Dmitry Kudriavtsev
            Jul 19 at 4:27






          • 1




            @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
            – Zeta
            Jul 19 at 5:51















          I've revised my program to take care of most of these issues, where can I post the revised version?
          – Dmitry Kudriavtsev
          Jul 19 at 4:27




          I've revised my program to take care of most of these issues, where can I post the revised version?
          – Dmitry Kudriavtsev
          Jul 19 at 4:27




          1




          1




          @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
          – Zeta
          Jul 19 at 5:51




          @DmitryKudriavtsev you can ask another question and link back to this topic. See codereview.meta.stackexchange.com/questions/1763/… for more information.
          – Zeta
          Jul 19 at 5:51












          up vote
          3
          down vote













          This is quite good so most of these comments are niggles / coding style. But...



          #include <stdio.h>
          #include <unistd.h>
          #include <stdlib.h>


          Put #includes in sorted order. If you have a lot of them, it makes it easier to find a header or spot duplicates, and it can help avoid manual merges in a version control system



          int max(int* arr, int len) 



          • I'd avoid that name. I've come across more than one C implementation that provides a max macro, causing great confusion



            int out = arr[0];
            for (int i = 0; i < len; i++)


          • That could be for (int i = 1; - the check below can never succeed for i = 0



          • Please don't omit the braces. People think that the compiler takes account of indenting. It doesn't. And this frequently leads to errors in maintenance (ref the goto fail bug).



             if (arr[i] > out)
            out = arr[i];
            return out;


            void sort(int** in, int** out, size_t length)
            int* inputs = *in;
            int* outputs = *out;


          • Why pass a pointer to a pointer then immediately dereference it



          • in should be a pointer to const, as you aren't altering it. (int const *)



            // this is the size of the array of counts
            int greatest = max(inputs, length); // find the greatest number in the array

            // allocate the array of counts
            int* counts = calloc(greatest + 1, sizeof(int));


          • unlike the other poster, I think calloc is appropriate here as you want zeroised memory and malloc is appropriate in the other places as you initialise them later.



          • You should check if you actually got memory allocated here



            // count numbers in input array
            for (int i = 0; i < length; i++)
            counts[inputs[i]]++;


            int counter = 0; // keep track of where we are in output array

            // loop through all the counts
            for (int i = 0; i < (greatest + 1); i++) // for every count in array
            for (int j = 0; j < counts[i]; j++) // loop that many times
            outputs[counter++] = i; // add the integer being counted to the output array



          • personally I'd avoid using auto-increments as part of an expression and make that two statements. I doubt the compiler would produce worse code, and it saves you having to work out whether the increment is done before or after the value is accessed.



             

            free(counts);


            int main(int argc, char** argv)
            int *inputs, *outputs;
            size_t length = argc - 1; // number of integers to sort


          • declare variables as close as possible to where you use them. These next two lines should be declarations


          • You don't check it the malloc was succesful



          • if argc is 1, then length is 0, and you'll attempt to allocate a very large amount of memory here



            inputs = malloc(sizeof(int) * (argc - 1));
            outputs = malloc(sizeof(int) * (argc - 1));

            for (int i = 1; i < argc; i++)
            inputs[i - 1] = atoi(argv[i]); // assign arguments to array


            sort(&inputs, &outputs, length);

            for (size_t i = 0; i < (length); i++)
            printf("%d ", outputs[i]); // print space separated sorted numbers

            printf("n");



          • arguably printf is overkill. You could use putchar('n') here



             free(inputs);
            free(outputs);

            return 0;



          • Well done for the last 3 lines (freeing up the memory and returning 0)! I've frequently seen one or both of those steps omitted.






          share|improve this answer





















          • It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
            – Toby Speight
            Jul 19 at 8:06










          • I thought that was only C++?
            – Tom Tanner
            Jul 19 at 10:01










          • Both C and C++.
            – Toby Speight
            Jul 19 at 10:06










          • ah, thanks. i'll remember that
            – Tom Tanner
            Jul 19 at 10:07














          up vote
          3
          down vote













          This is quite good so most of these comments are niggles / coding style. But...



          #include <stdio.h>
          #include <unistd.h>
          #include <stdlib.h>


          Put #includes in sorted order. If you have a lot of them, it makes it easier to find a header or spot duplicates, and it can help avoid manual merges in a version control system



          int max(int* arr, int len) 



          • I'd avoid that name. I've come across more than one C implementation that provides a max macro, causing great confusion



            int out = arr[0];
            for (int i = 0; i < len; i++)


          • That could be for (int i = 1; - the check below can never succeed for i = 0



          • Please don't omit the braces. People think that the compiler takes account of indenting. It doesn't. And this frequently leads to errors in maintenance (ref the goto fail bug).



             if (arr[i] > out)
            out = arr[i];
            return out;


            void sort(int** in, int** out, size_t length)
            int* inputs = *in;
            int* outputs = *out;


          • Why pass a pointer to a pointer then immediately dereference it



          • in should be a pointer to const, as you aren't altering it. (int const *)



            // this is the size of the array of counts
            int greatest = max(inputs, length); // find the greatest number in the array

            // allocate the array of counts
            int* counts = calloc(greatest + 1, sizeof(int));


          • unlike the other poster, I think calloc is appropriate here as you want zeroised memory and malloc is appropriate in the other places as you initialise them later.



          • You should check if you actually got memory allocated here



            // count numbers in input array
            for (int i = 0; i < length; i++)
            counts[inputs[i]]++;


            int counter = 0; // keep track of where we are in output array

            // loop through all the counts
            for (int i = 0; i < (greatest + 1); i++) // for every count in array
            for (int j = 0; j < counts[i]; j++) // loop that many times
            outputs[counter++] = i; // add the integer being counted to the output array



          • personally I'd avoid using auto-increments as part of an expression and make that two statements. I doubt the compiler would produce worse code, and it saves you having to work out whether the increment is done before or after the value is accessed.



             

            free(counts);


            int main(int argc, char** argv)
            int *inputs, *outputs;
            size_t length = argc - 1; // number of integers to sort


          • declare variables as close as possible to where you use them. These next two lines should be declarations


          • You don't check it the malloc was succesful



          • if argc is 1, then length is 0, and you'll attempt to allocate a very large amount of memory here



            inputs = malloc(sizeof(int) * (argc - 1));
            outputs = malloc(sizeof(int) * (argc - 1));

            for (int i = 1; i < argc; i++)
            inputs[i - 1] = atoi(argv[i]); // assign arguments to array


            sort(&inputs, &outputs, length);

            for (size_t i = 0; i < (length); i++)
            printf("%d ", outputs[i]); // print space separated sorted numbers

            printf("n");



          • arguably printf is overkill. You could use putchar('n') here



             free(inputs);
            free(outputs);

            return 0;



          • Well done for the last 3 lines (freeing up the memory and returning 0)! I've frequently seen one or both of those steps omitted.






          share|improve this answer





















          • It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
            – Toby Speight
            Jul 19 at 8:06










          • I thought that was only C++?
            – Tom Tanner
            Jul 19 at 10:01










          • Both C and C++.
            – Toby Speight
            Jul 19 at 10:06










          • ah, thanks. i'll remember that
            – Tom Tanner
            Jul 19 at 10:07












          up vote
          3
          down vote










          up vote
          3
          down vote









          This is quite good so most of these comments are niggles / coding style. But...



          #include <stdio.h>
          #include <unistd.h>
          #include <stdlib.h>


          Put #includes in sorted order. If you have a lot of them, it makes it easier to find a header or spot duplicates, and it can help avoid manual merges in a version control system



          int max(int* arr, int len) 



          • I'd avoid that name. I've come across more than one C implementation that provides a max macro, causing great confusion



            int out = arr[0];
            for (int i = 0; i < len; i++)


          • That could be for (int i = 1; - the check below can never succeed for i = 0



          • Please don't omit the braces. People think that the compiler takes account of indenting. It doesn't. And this frequently leads to errors in maintenance (ref the goto fail bug).



             if (arr[i] > out)
            out = arr[i];
            return out;


            void sort(int** in, int** out, size_t length)
            int* inputs = *in;
            int* outputs = *out;


          • Why pass a pointer to a pointer then immediately dereference it



          • in should be a pointer to const, as you aren't altering it. (int const *)



            // this is the size of the array of counts
            int greatest = max(inputs, length); // find the greatest number in the array

            // allocate the array of counts
            int* counts = calloc(greatest + 1, sizeof(int));


          • unlike the other poster, I think calloc is appropriate here as you want zeroised memory and malloc is appropriate in the other places as you initialise them later.



          • You should check if you actually got memory allocated here



            // count numbers in input array
            for (int i = 0; i < length; i++)
            counts[inputs[i]]++;


            int counter = 0; // keep track of where we are in output array

            // loop through all the counts
            for (int i = 0; i < (greatest + 1); i++) // for every count in array
            for (int j = 0; j < counts[i]; j++) // loop that many times
            outputs[counter++] = i; // add the integer being counted to the output array



          • personally I'd avoid using auto-increments as part of an expression and make that two statements. I doubt the compiler would produce worse code, and it saves you having to work out whether the increment is done before or after the value is accessed.



             

            free(counts);


            int main(int argc, char** argv)
            int *inputs, *outputs;
            size_t length = argc - 1; // number of integers to sort


          • declare variables as close as possible to where you use them. These next two lines should be declarations


          • You don't check it the malloc was succesful



          • if argc is 1, then length is 0, and you'll attempt to allocate a very large amount of memory here



            inputs = malloc(sizeof(int) * (argc - 1));
            outputs = malloc(sizeof(int) * (argc - 1));

            for (int i = 1; i < argc; i++)
            inputs[i - 1] = atoi(argv[i]); // assign arguments to array


            sort(&inputs, &outputs, length);

            for (size_t i = 0; i < (length); i++)
            printf("%d ", outputs[i]); // print space separated sorted numbers

            printf("n");



          • arguably printf is overkill. You could use putchar('n') here



             free(inputs);
            free(outputs);

            return 0;



          • Well done for the last 3 lines (freeing up the memory and returning 0)! I've frequently seen one or both of those steps omitted.






          share|improve this answer













          This is quite good so most of these comments are niggles / coding style. But...



          #include <stdio.h>
          #include <unistd.h>
          #include <stdlib.h>


          Put #includes in sorted order. If you have a lot of them, it makes it easier to find a header or spot duplicates, and it can help avoid manual merges in a version control system



          int max(int* arr, int len) 



          • I'd avoid that name. I've come across more than one C implementation that provides a max macro, causing great confusion



            int out = arr[0];
            for (int i = 0; i < len; i++)


          • That could be for (int i = 1; - the check below can never succeed for i = 0



          • Please don't omit the braces. People think that the compiler takes account of indenting. It doesn't. And this frequently leads to errors in maintenance (ref the goto fail bug).



             if (arr[i] > out)
            out = arr[i];
            return out;


            void sort(int** in, int** out, size_t length)
            int* inputs = *in;
            int* outputs = *out;


          • Why pass a pointer to a pointer then immediately dereference it



          • in should be a pointer to const, as you aren't altering it. (int const *)



            // this is the size of the array of counts
            int greatest = max(inputs, length); // find the greatest number in the array

            // allocate the array of counts
            int* counts = calloc(greatest + 1, sizeof(int));


          • unlike the other poster, I think calloc is appropriate here as you want zeroised memory and malloc is appropriate in the other places as you initialise them later.



          • You should check if you actually got memory allocated here



            // count numbers in input array
            for (int i = 0; i < length; i++)
            counts[inputs[i]]++;


            int counter = 0; // keep track of where we are in output array

            // loop through all the counts
            for (int i = 0; i < (greatest + 1); i++) // for every count in array
            for (int j = 0; j < counts[i]; j++) // loop that many times
            outputs[counter++] = i; // add the integer being counted to the output array



          • personally I'd avoid using auto-increments as part of an expression and make that two statements. I doubt the compiler would produce worse code, and it saves you having to work out whether the increment is done before or after the value is accessed.



             

            free(counts);


            int main(int argc, char** argv)
            int *inputs, *outputs;
            size_t length = argc - 1; // number of integers to sort


          • declare variables as close as possible to where you use them. These next two lines should be declarations


          • You don't check it the malloc was succesful



          • if argc is 1, then length is 0, and you'll attempt to allocate a very large amount of memory here



            inputs = malloc(sizeof(int) * (argc - 1));
            outputs = malloc(sizeof(int) * (argc - 1));

            for (int i = 1; i < argc; i++)
            inputs[i - 1] = atoi(argv[i]); // assign arguments to array


            sort(&inputs, &outputs, length);

            for (size_t i = 0; i < (length); i++)
            printf("%d ", outputs[i]); // print space separated sorted numbers

            printf("n");



          • arguably printf is overkill. You could use putchar('n') here



             free(inputs);
            free(outputs);

            return 0;



          • Well done for the last 3 lines (freeing up the memory and returning 0)! I've frequently seen one or both of those steps omitted.







          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered Jul 19 at 7:36









          Tom Tanner

          41339




          41339











          • It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
            – Toby Speight
            Jul 19 at 8:06










          • I thought that was only C++?
            – Tom Tanner
            Jul 19 at 10:01










          • Both C and C++.
            – Toby Speight
            Jul 19 at 10:06










          • ah, thanks. i'll remember that
            – Tom Tanner
            Jul 19 at 10:07
















          • It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
            – Toby Speight
            Jul 19 at 8:06










          • I thought that was only C++?
            – Tom Tanner
            Jul 19 at 10:01










          • Both C and C++.
            – Toby Speight
            Jul 19 at 10:06










          • ah, thanks. i'll remember that
            – Tom Tanner
            Jul 19 at 10:07















          It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
          – Toby Speight
          Jul 19 at 8:06




          It's perfectly legitimate to omit return 0; at the end of main() (but no other non-void function).
          – Toby Speight
          Jul 19 at 8:06












          I thought that was only C++?
          – Tom Tanner
          Jul 19 at 10:01




          I thought that was only C++?
          – Tom Tanner
          Jul 19 at 10:01












          Both C and C++.
          – Toby Speight
          Jul 19 at 10:06




          Both C and C++.
          – Toby Speight
          Jul 19 at 10:06












          ah, thanks. i'll remember that
          – Tom Tanner
          Jul 19 at 10:07




          ah, thanks. i'll remember that
          – Tom Tanner
          Jul 19 at 10:07












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f199789%2fcounting-sort-in-c%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods