C程序对字符串中的字符进行排序

时间:2010-10-14 02:08:53

标签: c

我在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

我有两个问题:

  1. 输出文件的开头有一堆换行符(即实际文本开始前大约5-7个空行)
  2. 为什么最后两次打印'ter'?
  3. PS - 我知道这些都是非常基本的问题,但我刚刚开始使用C / bash上课,我不确定我哪里出错了。

1 个答案:

答案 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,大多数专业程序员会做一些从笑到大喊你的事情:)我只是在这里使用它来说明这一点)

我发现一个方便的提示是在一张纸上绘制我的数组,变量等,然后追踪我的代码的每一行(再次,在纸上)来调试它的工作原理。