你很近。这是您的代码的工作版本。请注意,scanf()
从 ... 的数字中留下换行符fgets()
,因为您将永远不会gets()
再次使用,对吗?...因此您需要阅读scanf()
. 当然,还有一个有趣的问题,“为什么人们认为由人类计算比让计算机计算更好?” 不理会计数会更明智。请注意,修改后的代码会验证n
以确保它不大于 50。
修改后的代码适用于长度为 9 或更短的行
#include <assert.h>
#include <stdio.h>
#include <string.h>
void sort(char s[50][10], int);
int main(void)
{
int i;
int n = 0;
char s[50][10];
char line[11];
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Failed to read a number\n");
return 1;
}
if (n <= 0 || n > 50)
{
fprintf(stderr, "%d is out of the range 1..50\n", n);
return 1;
}
// Gobble rest of first line
while ((i = getchar()) != EOF && i != '\n')
;
for (i = 0; i < n; i++)
{
if (fgets(line, sizeof(line), stdin) == 0)
break;
// Remove newline from input
size_t len = strlen(line);
assert(len > 0 && len <= sizeof(s[i]));
line[len-1] = '\0';
strcpy(s[i], line);
}
n = i; // In case the file was shorter than stated!
printf("Before:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
sort(s, n);
printf("After:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
return 0;
}
void sort(char s[50][10], int n)
{
int i, j, cmp;
char tmp[10];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(s[j], s[j+1]);
if (cmp > 0)
{
strcpy(tmp, s[j+1]);
strcpy(s[j+1], s[j]);
strcpy(s[j], tmp);
}
}
}
}
此代码将行读入一个足够长的字符串,最多可容纳 9 个数据字符、一个换行符和终端 null。它删除换行符,最多留下 9 个数据字符和一个终端空值。
样品运行:
Before:
Number 34
Number 39
Number 32
Number 30
Number 22
Number 34
Number 57
Number 28
Number 30
Number 47
Number 43
Number 23
Number 22
After:
Number 22
Number 22
Number 23
Number 28
Number 30
Number 30
Number 32
Number 34
Number 34
Number 39
Number 43
Number 47
Number 57
适用于长度为 8 或更短行的原始代码
#include <assert.h>
#include <stdio.h>
#include <string.h>
void sort(char s[50][10], int);
int main(void)
{
int i;
int n = 0;
char s[50][10];
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Failed to read a number\n");
return 1;
}
if (n <= 0 || n > 50)
{
fprintf(stderr, "%d is out of the range 1..50\n", n);
return 1;
}
// Gobble rest of first line
while ((i = getchar()) != EOF && i != '\n')
;
for (i = 0; i < n; i++)
{
if (fgets(s[i], sizeof(s[i]), stdin) == 0)
break;
// Remove newline from input
size_t len = strlen(s[i]);
assert(len > 0);
s[i][len-1] = '\0';
}
n = i; // In case the file was shorter than stated!
printf("Before:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
sort(s, n);
printf("After:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
return 0;
}
void sort(char s[50][10], int n)
{
int i, j, cmp;
char tmp[10];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(s[j], s[j+1]);
if (cmp > 0)
{
strcpy(tmp, s[j+1]);
strcpy(s[j+1], s[j]);
strcpy(s[j], tmp);
}
}
}
}
“大”变化是声明和定义函数数组参数的方式。您要传递一个包含 50 行的数组,每行 10 个字符,因此只需在函数中指定即可。您可以在不改变程序行为的情况下从函数参数的维度中删除 50。
样本输入:
8
fed
abc
cba
def
hij
cba
xyz
aaa
示例运行:
$ ./srt < data
Before:
fed
abc
cba
def
hij
cba
xyz
aaa
After:
aaa
abc
cba
cba
def
fed
hij
xyz
$
这需要修改的事实表明测试限制(并仔细定义限制)的重要性。
修改后的代码仍然不是通用代码。最多 50 行输入的固定限制、作为输入的一部分所需行数的计数以及每行最多 10 个字符的固定行长度都使其成为玩具代码。因此,GIGO(garbage in,garbage out)并不是一个不合理的反应。如果数据文件包含过长的行,你会得到你所得到的。代码不会崩溃,但输出可能没有多大意义。