我在C中编写了这个程序,它逐行读取文件(每行只有一个单词),对字母进行排序,然后在每行显示排序后的单词和原始单词。
#include<stdio.h>
int main()
{
char line[128];
int i=0;
int j;
int length;
while(fgets(line,sizeof line,stdin) != NULL)
{
char word[128];
for (i=0; line[i] != '\0'; i++)
{
word[i]=line[i];
}
while (line[i] != '\0')
i++;
length=i;
for (i=length-1; i >=0; i--)
{
for (j=0; j<i; j++)
{
if (line[j] > line[i])
{
char temp;
temp = line[j];
line[j] = line[i];
line[i]=temp;
}
}
}
printf("%s %s",line,word);
}
return 0;
}
我正在使用以下bash命令编译并运行它。
gcc -o sign sign.c
./sign < sample_file | sort > output
原始文件(sample_file)如下所示:
computer
test
file
stack
overflow
输出文件是:
ackst stack
cemoprtu computer
efil file
efloorvw overflow
er
estt test
ter
ter
我有两个问题:
答案 0 :(得分:2)
问题1
在此代码之后,变量line
包含一行文本,包括字符串末尾的换行符
while(fgets(line,sizeof line,stdin) != NULL)
{
这就是你获得“额外”换行的原因。换行的ASCII值小于'A'的ASCII值。这就是为什么一旦你对字符进行排序,换行就会在每个字符串的开头结束。例如。 “computer \ n”变为“\ ncemoprtu”。
要解决此问题,您可以在for循环
之后删除字符串末尾的换行符if(i > 0 && word[i-1] == '\n')
{
word[i-1] = '\0';
line[i-1] = '\0';
--i;
}
...
printf("%s %s\n",line,word); /* notice the addition of the newline at the end */
这也解决问题2,但请继续阅读,看看有什么问题。
问题2
循环后
for (i=0; line[i] != '\0'; i++) { /* */ }
字符串word
不会以空值终止(除非是运气不好,因为它是随机的未初始化内存)。这就是你获得“ter”的原因,因为这是你将“计算机”一词复制到word
时留下的数据的一部分。
问题3
循环后
for (i=0; line[i] != '\0'; i++) { /* */ }
line[i] != '\0'
的值始终为false。这意味着此代码将不执行任何操作
while (line[i] != '\0')
i++;
如果我用基本相同的代码替换for循环和while循环,使用goto可能会使问题更加明显:
i=0;
begin_for_loop:
if(line[i] != '\0')
{
{
word[i]=line[i];
}
i++;
goto begin_for_loop;
}
begin_while_loop:
if(line[i] != '\0')
{
i++;
goto begin_while_loop;
}
(顺便说一句,如果你提到使用goto,大多数专业程序员会做一些从笑到大喊你的事情:)我只是在这里使用它来说明这一点)
我发现一个方便的提示是在一张纸上绘制我的数组,变量等,然后追踪我的代码的每一行(再次,在纸上)来调试它的工作原理。