Home > Blockchain >  C Sorting Algorithm Returns in the Quintillions When Given 0
C Sorting Algorithm Returns in the Quintillions When Given 0

Time:10-30

I'm trying to write my first sorting algorithm in C , I'm relatively new to it so this might be an endeavor beyond me but I thought I could handle it. When given the input 0 this code returns numbers such as 701635989630, 6560204700, and 1.8*10^19. This doesn't make sense to me at all, nor the people I have asked IRL.

Edit - @Slava had the best suggestion and with his help I was able to get it to work 4 out of 5 times now, but it still fails on the 5th

#include <cinttypes>

uint64_t descendingOrder(uint64_t a)
{
  std::vector<int> digits;
  for( auto tmp = a; tmp; tmp /= 10 ){
    digits.push_back( tmp % 10 );
  }
  
  bool run = true;
  
  //sort the array
  while (run) {
    bool change = false;
    for (unsigned long z = 1; z < std::size(digits);   z){
      if (digits[z]>digits[z-1]){
        unsigned long temp = digits[z];
        digits[z] = digits[z-1];
        digits[z-1] = temp;
        change = true;
      };
    };
    if (change == false){
      run = false;
    };
  };
  
  int finSort = 0;
  for (unsigned long i = 0; i < std::size(digits); i  ) {
    finSort *= 10;
    finSort  = digits[i];
  }

  return finSort;
}

CodePudding user response:

int arrayLength = sizeof(array); is not what you think. It does not return the size of array, but rather how much bytes that array comsume.

Also, int array[n] is not valid C , because arrays' sizes in C has to be known in compile time. If you want to create an array which sizes are known at runtime, consider using std::vector. You just need to change int array[n] to:

std::vector<int> array;
array.resize(n);

CodePudding user response:

I'd make the following two changes to the code:

int array[20]; // a 64 bit integer won't have more than 20 digits
int arrayLength = n; // we just calculated this

CodePudding user response:

If you use proper tool - std::vector in this case, your code would be simplified and easier to write and read, as std::vector can grow dynamically:

uint64_t descendingOrder(uint64_t a)
{
     std::vector<int> digits;
     for( auto tmp = a; tmp; tmp /= 10 )
          digits.push_back( tmp % 10 );
     // your sorting code is here
}  

Now you have your number digits in vector digits, your array size in digits.size() and you do not need 2 loops. Though digits in vector would be in reverse order but it does not matter in your case as you need to sort it.

CodePudding user response:

There are two mistakes that i can spot just by first looking at your code snippet:

Mistake 1

In C , the size of an array must be a compile time constant. So you cannot write code like:

int n = 10;
int arr[n];    //incorrect

Correct way to write this would be:

const int n = 10;
int arr[n];    //correct

For the same reason the following code is incorrect in your code as well:

int array[n]; //incorrect because n is not a constant expression

Mistake 2

You're calculating the size of the array incorrectly. The correct would be to use std::size with C 17 or use the formula

int arrayLength = sizeof(array)/sizeof(int);//will work with all C   versions

or with C 17:

int arrayLength = std::size(array); //works in C  17 and higher

You can/should instead use a variable size container like std::vector.

CodePudding user response:

C Sorting Algorithm Returns in the Quintillions When Given 0

Sorting algorithms sort things. They don't, as a rule, return integers.

uint64_t descendingOrder(uint64_t a)

This is a function that does three things:

  1. convert an integer into an array of digits
  2. sort the array of digits
  3. convert the sorted array of digits back into an integer

That's two things too many, and only one of them is really relevant to the question. It's clearly not a minimal reproducible example because the bug is in your sorting code, not in your integer-digit-array-conversion code.

Let's rewrite the function so it isn't trying to do too many things:

uint64_t descendingOrder(uint64_t a)
{
    auto digits = integer_to_digits(a);
    bubble_sort(digits);
    return digits_to_integer(digits);
}

You already have working code for integer_to_digits and digits_to_integer so I'm not going to write them out - and anyway, they don't belong in your question in the first place.

Now, we can write the minimal code needed to demonstrate the problem, starting with your existing sorting code:

void bubble_sort(std::vector<int> &digits)
{
  bool run = true;
  
  while (run) {
    bool change = false;
    for (unsigned long z = 1; z < digits.size();   z){
      if (digits[z]>digits[z-1]){
        unsigned long temp = digits[z];
        digits[z] = digits[z-1];
        digits[z-1] = temp;
        change = true;
      }
    }
    if (change == false){
      run = false;
    }
  }
}

and a trivial test harness so we can see it working:

void test_bubble_sort(std::vector<int> &digits)
{
    std::cout << "{";
    std::copy(digits.begin(), digits.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "} -> {";
    bubble_sort(digits);
    std::copy(digits.begin(), digits.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "}\n";
}

int main() {
    std::vector<int> empty;
    test_bubble_sort(empty);
    
    std::vector<int> zero{0};
    test_bubble_sort(zero);
    
    std::vector<int> one{1};
    test_bubble_sort(one);
    
    std::vector<int> inc{1, 2, 3};
    test_bubble_sort(inc);
    
    std::vector<int> dec{3, 2, 1};
    test_bubble_sort(dec);
}

... and the sort itself seems to be fine.

If you have a problem in reality with the integer_to_digits or digits_to_integer, write another test for those, and if necessary ask a question specific to them. Neither the test harness nor the question will have any bubble sorting in them, because these problems are completely unrelated.

When you have a working, tested bubble sort and working, tested integer-digit-array conversion, then you can combine them into a program that does two things.

  • Related