C语言:如何使用字符串找到n中数字组成的最大数
C language: How to find the largest number created by digits from n using string
题目:从n (n<10 ^50) 中找出由数字组成的最大数和最小数。
我试过如下,但在某些情况下,这是错误的
例如:
情况 1:输入 2015
输出 5210
情况2:输入47356359122
输出(错误答案)
请帮助我,我不知道为什么我得到了错误的答案!!!
#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] = '[=10=]';
printf("%s\n", 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] = '[=11=]';
这是使用计数排序的替代方法:
#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] = '[=12=]';
printf("%s\n", s);
}
int main() {
char s[100];
if (fgets(s, sizeof(s), stdin))
max_number(s);
return 0;
}
用户 chqrlie 已经提供了一个很好的一般性答案。这是一个更简单、效率稍低的方法。
观察到没有必要将结果实际存储在一个新字符串中,您还可以在找到数字时打印数字(从高到低)。该程序循环输入字符串 10 次,首先打印所有 9
,然后打印所有 8
,等等
#include <stdio.h>
void max(char *str) {
for (char digit = '9'; digit >= '0'; --digit) // Assume ASCII
for (char *strCp = str; *strCp != '[=10=]' ; ++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
header。
- 将
main
签名更改为 int main(void)
,这是标准建议的,以防不使用参数。
- 正在检查
fgets
的return值,所以程序可以处理空输入和输入失败。
对于初学者来说,该函数不应输出任何消息。是否输出消息由函数的调用者决定。
该函数应该return一个修改后的字符串,其中的字符按数字降序排列。
当向函数传递空字符串时,您的函数可以调用未定义的行为
void max(char s[]) {
int l = strlen(s);
int i, key, j;
//...
s[l - 1] = '[=10=]';
printf("%s\n", s);
}
因为在这个语句中
s[l - 1] = '[=11=]';
试图访问传递的字符串以外的内存。一般来说,该陈述是错误的,因为终止零必须出现在 l
.
位置
不需要设置终止零字符'[=16=]'
,因为它已经存在于字符串中。所以上面的说法是多余的。
事实上,由于此 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" ) ] = '[=13=]';
puts( max_number( s ) );
return 0;
}
如果使用 fgets
输入数字 47356359122
那么程序输出将是
97655433221
题目:从n (n<10 ^50) 中找出由数字组成的最大数和最小数。 我试过如下,但在某些情况下,这是错误的
例如:
情况 1:输入 2015
输出 5210
情况2:输入47356359122
输出(错误答案)
请帮助我,我不知道为什么我得到了错误的答案!!!
#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] = '[=10=]';
printf("%s\n", 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] = '[=11=]';
这是使用计数排序的替代方法:
#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] = '[=12=]';
printf("%s\n", s);
}
int main() {
char s[100];
if (fgets(s, sizeof(s), stdin))
max_number(s);
return 0;
}
用户 chqrlie 已经提供了一个很好的一般性答案。这是一个更简单、效率稍低的方法。
观察到没有必要将结果实际存储在一个新字符串中,您还可以在找到数字时打印数字(从高到低)。该程序循环输入字符串 10 次,首先打印所有 9
,然后打印所有 8
,等等
#include <stdio.h>
void max(char *str) {
for (char digit = '9'; digit >= '0'; --digit) // Assume ASCII
for (char *strCp = str; *strCp != '[=10=]' ; ++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
header。 - 将
main
签名更改为int main(void)
,这是标准建议的,以防不使用参数。 - 正在检查
fgets
的return值,所以程序可以处理空输入和输入失败。
对于初学者来说,该函数不应输出任何消息。是否输出消息由函数的调用者决定。
该函数应该return一个修改后的字符串,其中的字符按数字降序排列。
当向函数传递空字符串时,您的函数可以调用未定义的行为
void max(char s[]) {
int l = strlen(s);
int i, key, j;
//...
s[l - 1] = '[=10=]';
printf("%s\n", s);
}
因为在这个语句中
s[l - 1] = '[=11=]';
试图访问传递的字符串以外的内存。一般来说,该陈述是错误的,因为终止零必须出现在 l
.
不需要设置终止零字符'[=16=]'
,因为它已经存在于字符串中。所以上面的说法是多余的。
事实上,由于此 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" ) ] = '[=13=]';
puts( max_number( s ) );
return 0;
}
如果使用 fgets
输入数字 47356359122
那么程序输出将是
97655433221