【问题标题】:Unexpected '%' appearing in console控制台中出现意外的“%”
【发布时间】:2017-02-20 22:27:29
【问题描述】:

我正在阅读 K&R C 编程书籍,我刚刚完成了练习 1-13,您可以在其中打印输入单词长度的直方图。我的水平直方图很好,但我的垂直直方图末尾出现了一个“%”符号,我不知道为什么会一直这样。这是我认为导致问题的循环:

for (i = 0; i < array_length; i++) {
    printf("%-4d", i + 1);
}

如果array_length为7,我会在第7个位置后有一个'%'符号,如下所示:

                |           
                |   |       
                |   |       
                |   |       
                |   |       
                |   |       
|   |   |       |   |       
|   |   |   |   |   |       
|   |   |   |   |   |   |   
|   |   |   |   |   |   |   
|   |   |   |   |   |   |   
1   2   3   4   5   6   7   % 

如果我删除这个循环,垂直条打印得很好,我只是没有得到每个下面的编号。

这里发生了什么?据我猜测,printf 会在 'i' 中使用垃圾数据额外运行一次,但我不知道为什么或如何发生这种情况。

我在 Ubuntu 上使用 gcc 进行编译,如果这有什么不同的话。

这是完整的代码供您参考:

#include <stdio.h>

#define IN  1
#define OUT 0
#define ARRAY_SIZE 1000

int main() {

  int c, current_word_length, state, i, j, current_word, largest, array_length, top;
  int word_lengths[ARRAY_SIZE];

  current_word_length = current_word = largest = 0;
  state = OUT;

  for (i = 0; i < ARRAY_SIZE; i++) {
    word_lengths[i] = 0;
  }

  printf("Enter up to 1000 words and this program will calculate their length.\n");
  printf("Please enter a newline, tab, or space before the last word entered, then EOF to print summary.\n\n");

  while ((c = getchar()) != EOF) {

    if (c == ' ' || c == '\t' || c == '\n') {
      if (state == IN) {
        word_lengths[current_word++] = current_word_length;
        if (current_word_length > largest) {
          largest = current_word_length;
        }
        current_word_length = 0;
        state = OUT;
      }
    } else {
      state = IN;
      current_word_length++;
    }

  }

  array_length = current_word;

  printf("\nWord Lengths Histogram Horizontal:\n\n");

  for (i = 0; i < array_length; i++) {
    printf("%-4d: ", i + 1);
    for (j = 0; j < word_lengths[i]; j++) {
      printf("=");
    }
    printf("\n");
  }

  printf("\nWord Lengths Histogram Vertical:\n\n");

  top = largest;

  while (top > 0) {

    for (i = 0; i < array_length; i++) {
      if (word_lengths[i] >= top) {
        printf("%-4c", '|');
      } else {
        printf("%-4c", ' ');
      }
    }

    printf("\n");

    top--;
  }

  for (i = 0; i < array_length; i++) {
    printf("%-4d", i + 1);
  }

  return 0;
}

这就是我期望使用这个输入字符串“Bacon ipsum dolor amet frankfurter landjaeger ham”发生的事情:

Enter up to 1000 words and this program will calculate their length.
Please enter a newline, tab, or space before the last word entered, then EOF to print summary.

Bacon ipsum dolor amet frankfurter landjaeger ham

Word Lengths Histogram Horizontal:

1   : =====
2   : =====
3   : =====
4   : ====
5   : ===========
6   : ==========
7   : ===

Word Lengths Histogram Vertical:

                |           
                |   |       
                |   |       
                |   |       
                |   |       
                |   |       
|   |   |       |   |       
|   |   |   |   |   |       
|   |   |   |   |   |   |   
|   |   |   |   |   |   |   
|   |   |   |   |   |   |   
1   2   3   4   5   6   7

【问题讨论】:

  • 你确定 % 不只是你的 shell 提示符吗?在循环之后添加printf("\n");puts(""); (就在return 0; 之前)
  • 好的,解决了!所以,我仍然在学习很多关于 shell 工作原理的知识,你能向我解释发生了什么或给我指出一个资源吗?
  • 好吧,你打印出了数字 1 到 7,然后你的程序就结束了。所以 shell 从你停止打印的地方开始。通过在程序结束之前打印一个换行符,shell 会在新的新行处开始它正在执行的操作,而不是在最后一个数字 7 之后。
  • 我运行了你的程序并输入了一个长度为 1 到 9 的字符串,但不是按顺序输入的。它没有打印流氓%,但直方图是幻想。长度为 1 的 3,长度为 2 的 5,依此类推。是时候拿出调试器了。
  • @WeatherVane 数字不是长度,而是输入的字数。接下来我会尝试做一个基于字长的版本,我可能误解了作业!

标签: c console printf


【解决方案1】:

好的,正如 cmets 中的 nos 和 chqrlie 所指出的,我需要在我的程序末尾添加一个换行符,以便在程序完成运行后 shell 提示符将出现在换行符上。

在 main() 末尾添加 putchar() 调用解决了我的问题:

  for (i = 0; i < array_length; i++) {
    printf("%-4d", i + 1);
  }

  putchar('\n');

  return 0;
} // end main()

【讨论】:

  • 也可以使用putchar('\n');输出换行符。它的开销比printf("\n"); 少。
  • @JonathanLeffler:原则上我同意,但现代编译器为printf("\n");puts("");fputchar('\n'); 生成相同的代码
  • 这本身不是 shell 问题,程序用换行符完成输出总是更好,因为 unix shell 通常不会在提示符之前打印一个。在您的情况下,shell 提示符是 % 并且它出现在您的程序输出之后。添加putchar() 会使shell 提示出现在下一行的开头。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
相关资源
最近更新 更多