问题:求n (n<10 ^50)中的数字产生的最大和最小的数。我试过像下面这样,但在某些情况下,它是错误的
例如:
情形1:输入2015
输出5210
案例2:Input47356359122
Output(错误答案)请帮帮我,我不知道为什么我得到了错误的答案!!
#include <stdio.h>
#include <string.h>
void max(char s[]) {
int l = strlen(s);
int i, key, j;
for (i = 1; i < l; i++) {
key = s[i];
j = i - 1;
while (j >= 0 && s[j] > key) {
s[j + 1] = s[j];
j = j - 1;
}
s[j + 1] = key;
}
s[l - 1] = ' ';
printf("%sn", s);
}
int main() {
char s[100];
fgets(s, sizeof(s), stdin);
max(s);
}
你的方法是正确的:按降序排序,从这些数字中产生最大的数字。
你的实现有缺陷:
-
实际上是按递增顺序排序的。您应该将
while (j >= 0 && s[j] > key)
更改为while (j >= 0 && s[j] < key)
-
空终止符设置在错误的位置:您清除
s
中的最后一个字符。如果从stdin
中读取的行以换行符结束,则可能擦除它,除非用户键入了TAB字符,但如果输入仅由数字组成,则将删除最后一个。将代码改为:s[l - 1] = ' ';
这是另一种使用计数排序的方法:
#include <stdio.h>
void max_number(char s[]) {
/* array to store the number of occurrences of each digit */
int count[10] = { 0 };
int i, d, c;
/* enumerate all characters from the string, stop at the null terminator */
for (i = 0; s[i]; i++) {
/* only count digits from '0' to '9' */
if (s[i] >= '0' && s[i] <= '9') {
/* increase the digit count for this digit */
count[s[i] - '0']++;
}
}
/* output the digits from highest to lowest */
for (i = 0, d = 10; d --> 0;) {
for (c = count[d]; c --> 0;)
s[i++] = '0' + d;
}
if (i == 0) {
/* there were no digits in the string: store a 0 */
s[i++] = '0';
}
if (s[0] == '0') {
/* there were only zeroes in the string: keep a single 0 */
i = 1;
}
/* set the null terminator */
s[i] = ' ';
printf("%sn", s);
}
int main() {
char s[100];
if (fgets(s, sizeof(s), stdin))
max_number(s);
return 0;
}
用户chqrlie已经提供了一个很好的一般性答案。下面是一种更简单、效率略低的方法。
注意到没有必要实际地将结果存储在一个新的字符串中,您也可以在找到数字时打印数字——从高到低。这个程序在输入字符串上循环10次,首先打印所有的9
s,然后是所有的8
s,等等。
#include <stdio.h>
void max(char *str) {
for (char digit = '9'; digit >= '0'; --digit) // Assume ASCII
for (char *strCp = str; *strCp != ' ' ; ++strCp)
if (*strCp == digit)
putchar(digit);
putchar('n');
}
int main(void) {
char s[100];
if (fgets(s, sizeof(s), stdin) != NULL)
max(s);
}
注意:
- 不使用
strlen
功能,因此不再需要string.h
标头。 - 将
main
签名修改为int main(void)
,在不使用参数的情况下,这是标准建议的。 - 检查
fgets
的返回值,使程序可以处理空输入和输入失败。
对于初学者,该函数不应该输出任何消息。决定是否输出消息的是函数的调用者。
函数应返回一个修改后的字符串,该字符串按降序排序为数字。
当一个空字符串被传递给
函数时,你的函数可以调用未定义的行为void max(char s[]) {
int l = strlen(s);
int i, key, j;
//...
s[l - 1] = ' ';
printf("%sn", s);
}
因为在这个语句中
s[l - 1] = ' ';
试图访问传入字符串之外的内存。一般来说,这个语句是错误的,因为结束的零必须出现在位置l
。
不需要设置终止零字符' '
,因为它已经存在于字符串中。所以上面的语句是多余的。
实际上,由于if语句中的条件,您正在尝试使用插入排序方法按升序对字符串中的字符进行排序。
while (j >= 0 && s[j] > key) {
在这种情况下,在调用函数fgets
之后出现在字符串中的新行字符'n'
将被移动到字符串的开头。
您必须按降序对字符串进行排序。
在调用函数之前,应该从字符串中删除新的行字符'n'
。
函数可以如下例中所示的方式声明和定义。
#include <stdio.h>
#include <string.h>
char * max_number( char *s )
{
if ( *s )
{
for ( char *p = s + 1; *p; ++p )
{
char c = *p;
char *q = p;
for ( ; q != s && *( q - 1 ) < c; --q )
{
*q = *( q - 1 );
}
if ( q != p ) *q = c;
}
}
return s;
}
int main(void)
{
char s[100];
fgets( s, sizeof( s ), stdin );
s[ strcspn( s, "n" ) ] = ' ';
puts( max_number( s ) );
return 0;
}
如果使用fgets
输入数字47356359122
,则程序输出将为
97655433221