问题
I have homework where I have to create a C program which sorts 5 numbers from smallest to largest. I know how to easily program this using functions and if statements (using >= and <=).
However, the catch is I am only allowed to use printf and scanf, so I have to calculate all the >= and <= inside the printf. And I'm not allowed to use the ternary operator.
I've been trying to a long time. So I tried to sort just 3 numbers, I still can't even get past sorting the smallest number. It just keeps printing 1.
// This printf is just trying to figure out the smallest number from 3 numbers provided but it keeps printing 1.
printf("The ascending order of the numbers are: %d ",
(
(num1 <= num2 && num1 <= num3) || // Checking if num1 is the smallest
(num2 <= num1 && num2 <= num3) || // Checking if num2 is the smallest
(num3 <= num2 && num3 <= num1) // Checking if num3 is the smallest
));
One possible solution I have come up with is adding the ((num1 + num2 + num3) -1) because if one of the statements is true (for example if num2 is the smallest, it would print 1 because 1 means true). If it is false it prints 0. So I could technically add the statement which is true then -1. So if num2's statement is true, I could do + num2 - 1.
回答1:
Pass 1: Minimum of three distinct values
Note that if a condition evaluates to false, the result is 0; if true, 1. So you can use a trick (as long as multiplication and addition aren't verboten too) — for three distinct values as shown in the question:
printf("The smallest number is: %d ",
(num1 * (num1 <= num2 && num1 <= num3) +
num2 * (num2 <= num1 && num2 <= num3) +
num3 * (num3 <= num1 && num3 <= num2)));
There will be trouble if two values are the same and are also the smaller value.
Pass 2: Minimum of five distinct values
If you need to process 5 values, it is (as noted in a comment) more tedious than difficult.
printf("The smallest number is: %d ",
(num1 * (num1 <= num2 && num1 <= num3 && num1 <= num4 && num1 <= num5) +
num2 * (num2 <= num1 && num2 <= num3 && num2 <= num4 && num2 <= num5) +
num3 * (num3 <= num1 && num3 <= num2 && num3 <= num4 && num3 <= num5) +
num4 * (num4 <= num1 && num4 <= num2 && num4 <= num3 && num4 <= num5) +
num5 * (num5 <= num1 && num5 <= num2 && num5 <= num3 && num5 <= num4)));
This is just for finding the minimum; working it for each of the other cases quickly becomes preposterous. Indeed, the whole exercise is fairly silly, but it is also fairly typical of some courses.
Pass 3: Minimum of three values not necessarily distinct
After a bit of cogitation, I think you can deal with 2 or 3 numbers the same with this (which is basically what user3386109 said in a comment).
#include <stdio.h>
static void print_smallest(int num1, int num2, int num3)
{
printf("The smallest number of (%d, %d, %d) is %d\n",
num1, num2, num3,
(num1 * (num1 <= num2 && num1 <= num3) +
num2 * (num2 < num1 && num2 <= num3) +
num3 * (num3 < num1 && num3 < num2)));
}
int main(void)
{
for (int i = 1; i < 4; i++)
{
for (int j = 1; j < 4; j++)
{
for (int k = 1; k < 4; k++)
print_smallest(i, j, k);
}
}
return 0;
}
Output:
The smallest number of (1, 1, 1) is 1
The smallest number of (1, 1, 2) is 1
The smallest number of (1, 1, 3) is 1
The smallest number of (1, 2, 1) is 1
The smallest number of (1, 2, 2) is 1
The smallest number of (1, 2, 3) is 1
The smallest number of (1, 3, 1) is 1
The smallest number of (1, 3, 2) is 1
The smallest number of (1, 3, 3) is 1
The smallest number of (2, 1, 1) is 1
The smallest number of (2, 1, 2) is 1
The smallest number of (2, 1, 3) is 1
The smallest number of (2, 2, 1) is 1
The smallest number of (2, 2, 2) is 2
The smallest number of (2, 2, 3) is 2
The smallest number of (2, 3, 1) is 1
The smallest number of (2, 3, 2) is 2
The smallest number of (2, 3, 3) is 2
The smallest number of (3, 1, 1) is 1
The smallest number of (3, 1, 2) is 1
The smallest number of (3, 1, 3) is 1
The smallest number of (3, 2, 1) is 1
The smallest number of (3, 2, 2) is 2
The smallest number of (3, 2, 3) is 2
The smallest number of (3, 3, 1) is 1
The smallest number of (3, 3, 2) is 2
The smallest number of (3, 3, 3) is 3
Pass 4: Sorted order for three values not necessarily distinct
Calculating the maximum instead of the minimum is trivial; simply use > in place of < throughout.
Calculating the median turns out to be harder. I suspect there is a better way of doing it than this, but at least this works. Note the subtracted term — omit that, and the median value is doubled when the three values are the same.
#include <stdio.h>
static void print_smallest(int num1, int num2, int num3)
{
printf("The sorted order of (%2d, %2d, %2d) is (%2d, %2d, %2d)\n",
num1, num2, num3,
(num1 * (num1 <= num2 && num1 <= num3) + /* Min1 */
num2 * (num2 < num1 && num2 <= num3) + /* Min2 */
num3 * (num3 < num1 && num3 < num2)), /* Min3 */
(num1 * (num1 >= num2 && num1 <= num3) + /* Med1 */
num2 * (num2 > num1 && num2 <= num3) + /* Med2 */
num3 * (num3 > num1 && num3 < num2) - /* Med3 */
num1 * (num1 == num2 && num1 == num3) + /* Med4 */
num1 * (num1 <= num2 && num1 >= num3) + /* Med5 */
num2 * (num2 < num1 && num2 >= num3) + /* Med6 */
num3 * (num3 < num1 && num3 > num2)), /* Med7 */
(num1 * (num1 >= num2 && num1 >= num3) + /* Max1 */
num2 * (num2 > num1 && num2 >= num3) + /* Max2 */
num3 * (num3 > num1 && num3 > num2)) /* Max3 */
);
}
int main(void)
{
int lo = -7; // +1, -2
int hi = +6; // +4, +4
int jp = +6; // +1, +2
for (int i = lo; i < hi; i += jp)
{
for (int j = lo; j < hi; j += jp)
{
for (int k = lo; k < hi; k += jp)
print_smallest(i, j, k);
}
}
return 0;
}
Output:
The sorted order of (-7, -7, -7) is (-7, -7, -7)
The sorted order of (-7, -7, -1) is (-7, -7, -1)
The sorted order of (-7, -7, 5) is (-7, -7, 5)
The sorted order of (-7, -1, -7) is (-7, -7, -1)
The sorted order of (-7, -1, -1) is (-7, -1, -1)
The sorted order of (-7, -1, 5) is (-7, -1, 5)
The sorted order of (-7, 5, -7) is (-7, -7, 5)
The sorted order of (-7, 5, -1) is (-7, -1, 5)
The sorted order of (-7, 5, 5) is (-7, 5, 5)
The sorted order of (-1, -7, -7) is (-7, -7, -1)
The sorted order of (-1, -7, -1) is (-7, -1, -1)
The sorted order of (-1, -7, 5) is (-7, -1, 5)
The sorted order of (-1, -1, -7) is (-7, -1, -1)
The sorted order of (-1, -1, -1) is (-1, -1, -1)
The sorted order of (-1, -1, 5) is (-1, -1, 5)
The sorted order of (-1, 5, -7) is (-7, -1, 5)
The sorted order of (-1, 5, -1) is (-1, -1, 5)
The sorted order of (-1, 5, 5) is (-1, 5, 5)
The sorted order of ( 5, -7, -7) is (-7, -7, 5)
The sorted order of ( 5, -7, -1) is (-7, -1, 5)
The sorted order of ( 5, -7, 5) is (-7, 5, 5)
The sorted order of ( 5, -1, -7) is (-7, -1, 5)
The sorted order of ( 5, -1, -1) is (-1, -1, 5)
The sorted order of ( 5, -1, 5) is (-1, 5, 5)
The sorted order of ( 5, 5, -7) is (-7, 5, 5)
The sorted order of ( 5, 5, -1) is (-1, 5, 5)
The sorted order of ( 5, 5, 5) is ( 5, 5, 5)
Pass 5: Sorted order for three values, no loops or function
As before, the code in Pass 4 does a thorough test of all combinations of three numbers in their relative positions. If you're required to read three numbers and then sort them (and you're not allowed to use loops or functions other than main(), scanf(), printf(), so be it — you can transplant the printf() statement into your main() immediately after you've read three values:
#include <stdio.h>
int main(void)
{
int num1, num2, num3;
if (scanf("%d%d%d", &num1, &num2, &num3) != 3)
{
fprintf(stderr, "failed to read 3 integers\n");
return 1;
}
printf("The sorted order of (%2d, %2d, %2d) is (%2d, %2d, %2d)\n",
num1, num2, num3,
(num1 * (num1 <= num2 && num1 <= num3) + /* Min1 */
num2 * (num2 < num1 && num2 <= num3) + /* Min2 */
num3 * (num3 < num1 && num3 < num2)), /* Min3 */
(num1 * (num1 >= num2 && num1 <= num3) + /* Med1 */
num2 * (num2 > num1 && num2 <= num3) + /* Med2 */
num3 * (num3 > num1 && num3 < num2) - /* Med3 */
num1 * (num1 == num2 && num1 == num3) + /* Med4 */
num1 * (num1 <= num2 && num1 >= num3) + /* Med5 */
num2 * (num2 < num1 && num2 >= num3) + /* Med6 */
num3 * (num3 < num1 && num3 > num2)), /* Med7 */
(num1 * (num1 >= num2 && num1 >= num3) + /* Max1 */
num2 * (num2 > num1 && num2 >= num3) + /* Max2 */
num3 * (num3 > num1 && num3 > num2)) /* Max3 */
);
return 0;
}
Testing with a random number generator (program name sort3-53) yields:
$ for i in $(range 0 9); do random -n 3 10 99 | sort3-53; done
The sorted order of (66, 62, 70) is (62, 66, 70)
The sorted order of (43, 99, 23) is (23, 43, 99)
The sorted order of (20, 46, 66) is (20, 46, 66)
The sorted order of (87, 82, 19) is (19, 82, 87)
The sorted order of (63, 29, 62) is (29, 62, 63)
The sorted order of (40, 66, 15) is (15, 40, 66)
The sorted order of (17, 13, 58) is (13, 17, 58)
The sorted order of (84, 50, 11) is (11, 50, 84)
The sorted order of (60, 86, 54) is (54, 60, 86)
The sorted order of (37, 33, 96) is (33, 37, 96)
$
You can probably use seq where I use range. I'm not sure there's a standard PRNG program analogous to the random I use (and wrote). The invocation shown generates 3 random numbers between 10 and 99 inclusive.
How it should be done?
The whole process here is preposterous — but that's because of the conditions placed on the techniques that can be used. If you need to sort three or more numbers, put them in an array, sort the array, and print the array. Failing that, you should swap the values to find the sorted order; it would dramatically reduce the number of comparisons needed, and there'd be no multiplications.
回答2:
Here is a simple solution that can be easily adapted for any number of values:
#include <stdio.h>
int main() {
int n[5], o[5], s[5];
while (scanf("%d%d%d%d%d", &n[0], &n[1], &n[2], &n[3], &n[4]) == 5) {
o[0] = (n[0] > n[1]) + (n[0] > n[2]) + (n[0] > n[3]) + (n[0] > n[4]);
o[1] = (n[1] >= n[0]) + (n[1] > n[2]) + (n[1] > n[3]) + (n[1] > n[4]);
o[2] = (n[2] >= n[0]) + (n[2] >= n[1]) + (n[2] > n[3]) + (n[2] > n[4]);
o[3] = (n[3] >= n[0]) + (n[3] >= n[1]) + (n[3] >= n[2]) + (n[3] > n[4]);
o[4] = (n[4] >= n[0]) + (n[4] >= n[1]) + (n[4] >= n[2]) + (n[4] >= n[3]);
s[o[0]] = n[0];
s[o[1]] = n[1];
s[o[2]] = n[2];
s[o[3]] = n[3];
s[o[4]] = n[4];
printf("%d %d %d %d %d\n", s[0], s[1], s[2], s[3], s[4]);
}
return 0;
}
Note that while is only used to repeat the input / sort / output phase. You can get rid of it if no if or while statement is allowed, but then I do not know how to test for successful scanf() conversion, yet undefined behavior can be avoided via initialization:
#include <stdio.h>
int main() {
int n0, n1, n2, n3, n4, s[5];
n0 = n1 = n2 = n3 = n4 = 0;
scanf("%d%d%d%d%d", &n0, &n1, &n2, &n3, &n4);
s[(n0 > n1) + (n0 > n2) + (n0 > n3) + (n0 > n4)] = n0;
s[(n1 >= n0) + (n1 > n2) + (n1 > n3) + (n1 > n4)] = n1;
s[(n2 >= n0) + (n2 >= n1) + (n2 > n3) + (n2 > n4)] = n2;
s[(n3 >= n0) + (n3 >= n1) + (n3 >= n2) + (n3 > n4)] = n3;
s[(n4 >= n0) + (n4 >= n1) + (n4 >= n2) + (n4 >= n3)] = n4;
printf("%d %d %d %d %d\n", s[0], s[1], s[2], s[3], s[4]);
return 0;
}
回答3:
If you are allowed to use int which I presume you do (how else could you store the user input) why not use a precomputed table with the correct sorting?
#include <stdio.h>
int map[2][2] = {
{1, 0},
{0, 1}
};
int main() {
int n[2] = {7, 5};
int tmp = n[0] >= n[1];
printf("1.) %d\n", n[map[tmp][0]]);
printf("2.) %d\n", n[map[tmp][1]]);
}
UPDATE: This seems to work for three numbers:
#include <stdio.h>
int map[2][2][2][3] = {
{
{
{2, 1, 0},
{1, 2, 0}
},
{
{2, 0, 1},
{0, 1, 0}
}
},
{
{
{0, 0, 0},
{1, 0, 2}
},
{
{0, 2, 1},
{0, 1, 2}
}
}
};
int main() {
int n[3] = {30, 59, 100};
int tmp1 = n[0] > n[2];
int tmp2 = n[0] > n[1];
int tmp3 = n[1] > n[2];
printf("1.) %d\n", n[map[tmp1][tmp2][tmp3][0]]);
printf("2.) %d\n", n[map[tmp1][tmp2][tmp3][1]]);
printf("3.) %d\n", n[map[tmp1][tmp2][tmp3][2]]);
}
来源:https://stackoverflow.com/questions/49290953/how-do-i-make-conditions-in-printf-statements