Before you aim for brevity, you should focus on clarity. Your function is obfuscated enough, without trying to shorten it. The code will become somewhat shorter as you extract common snippets into functions. The key is not to aim for the minimum number of characters in the source code, but to limit each function to a reasonable number of lines.
STL vectors are easier to work with than arrays. Since you did not use vectors, I'll assume that you are deliberately avoiding them as a beginner.
Correctness
- Handling of zero: I would consider zero to be a number consisting of one even digit. You treat it as a zero-digit number. Worse, you say that the smallest odd digit is 0 and the largest number that can be formed using the odd digits is also 0.
- Handling of negative integers: If the input is negative, I think that the digit analysis should act on the absolute value of the number. Instead, your program seems to have a concept of "negative digits".
Maintainability
- Problem decomposition: You should decompose the problem into functions; otherwise you end up with a god-awful
main()
function that contains everything. I realize that this problem doesn't naturally lend itself to decomposition due to its eclectic nature, but still, it is possible. I'll discuss this further below.
- Variable naming: I'll just echo everyone else's complaints.
- Variable declarations: Declare your variables as close as possible to the point of use. There is no reason to declare all variables at the beginning of the function in C++. (The same goes for C since the C99 standard.)
- Magic number: Your arrays have size 10, a "magic number". At the least, you should explain in a comment that
long
can be up to 10 digits in your C++ environment. (This assumption is not portable!) The correct approach is to use std::numeric_limits<long>::digits10
(which is defined in #include <limits>
).
Data Types
Array indices should be of type size_t
.
I suggest treating base-10 digits as unsigned short
. Furthermore, typedef unsigned short digit
would be handy.
You can templatize the code to handle even larger inputs, such as long long
. I'll use template <typename T>
below, but you could just continue to use long
.
Decomposition
The most obvious code that you can immediately extract is your sorting routine. If you used STL std::vector
to store the digits, then it would be easiest to call std::sort()
. If you use plain arrays, then you could call qsort()
(in #include <cstdlib>
) with one of the following comparators:
static int ascending_digits(const void *pa, const void *pb) {
digit const &a = *static_cast<digit const *>(pa);
digit const &b = *static_cast<digit const *>(pb);
return (a < b) ? -1 :
(a > b) ? +1 : 0;
}
static int descending_digits(const void *pa, const void *pb) {
return -ascending_digits(pa, pb);
}
Other than that, I would recommend that the problem be decomposed into the following functions.
/**
* Extracts the base-10 digits of number into an array. The caller must
* provide an array that is large enough for any value of type T, i.e.
* it should have a size of at least std::numeric_limits<T>::digits10
* (which is defined in #include <limits>).
*
* If number is negative, its absolute value is considered.
*
* The digits array will be filled, least-significant digit first.
* Returns the actual number of digits in the number.
*/
template <typename T>
static size_t number_to_digits(T number, digit digits[]);
/**
* Interprets an array of base-10 digits (least-significant digit first)
* as a number.
*/
template <typename T>
static T digits_to_number(const digit digits[], size_t ndigits);
/**
* Given an array of digits, copies just the odd digits (when parity=1)
* or just the even digits (when parity=0). The size of both the input
* digits array and the output filtered array is specified by ndigits.
*
* Returns the number of digits copied into the filtered array.
*/
static size_t filter_digits(bool parity, const digit digits[], digit filtered[], size_t ndigits);
/**
* Prints the label, followed by '\n', followed by n space-delimited digits,
* followed by std::endl.
*
* Returns out for chaining convenience.
*/
static std::ostream &output_digits(std::ostream &out, const char *label, const digit digits[], size_t n);
/**
* Prints the analysis of the number.
*/
template <typename T>
void analyze(T number, std::ostream &out);
int main() {
long long number;
std::cout << "Enter a number: " << std::endl;
std::cin >> number;
analyze(number, std::cout);
}