C语言 擦除显示的字符



我正在做Brian W. Kernighan和Dennis M. Ritchie的">C编程语言"第2版练习。

练习1.9让我感到困惑。所以这里是:

"编写一个程序将其输入复制到输出,将每个字符串替换为一个空格"。

我对此感到困惑。我在这里发布我的问题,因为其他学习者没有像我想做的那样做这个练习。在这里,使用 - 表示空白:

Input: ----hello
Output: -hello

但我想要这个:

Input: ----hello
Output: ----hello
Input: ----
Output: -

所以这是我的程序:

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int character; /* input character */
 int non_blank = 0; /* is any non blank character */
 while ((character = getchar()) != EOF) {
    if (character != 'n') {
      putchar(character);
      if (character != ' ') {
          non_blank = 1;
      }
    }
    else {
      if (non_blank == 0 ) {
        putchar('b'); /* go to previous line (blablan|cursor|) (blabla|cursor|n) */
        putchar('r'); /* carriage return */
        putchar(' '); /* put one space */
        putchar(''); /* and put the end of line */
      }
      non_blank = 0;
    }
 }
 return EXIT_SUCCESS;
}

但空间不会被擦除。

Input: ------|n
Output: -|----- 

这是我对转义序列的实验:

#include <stdio.h>
#include <stdlib.h>
int main()
{
  printf("bbbbbbbbbbbbbbb");
  putchar('b'); /* jump to previous line */
  putchar('r');
  putchar('b');
  putchar('');
  return EXIT_SUCCESS;
}  

|是一个游标。

Output: b|

但是当我添加换行符时,它不起作用。如何使其与换行符一起使用?

代码的问题在于,一旦处理字符,就会打印字符,一旦检测到必须将它们压缩到一个空格,就会尝试擦除它们。

您的方法是有效的,但您必须首先知道b只会使光标返回一个空格(不擦除(,因此正确的方法是发出b b(一个退格,一个覆盖字符的空间和另一个退格键将光标留在正确的位置(

另一种方法是等待打印任何内容,直到我们知道该行是以非空字符串结尾还是仅以n字符结束。

以下代码对空白字符进行计数,并管理两种状态来应对这种情况。 当然,您将能够遵循代码,我试图用注释来记录它。

#include <stdio.h>
int main()
{
    int c;
    int state = 0;
    int nblanks = 0;
    /* read chars up to EOF */
    while((c = getchar()) != EOF) {
        switch (state) {
        case 0: /* no nonblank character read */
            switch (c) {
            /* accumulate number of blanks to be printed in case
             * we see a nonblank char before n */
            case ' ': nblanks++; break;
            /* in this case we have seen nblanks before a n, so
             * we have to print only one blank and n */
            case 'n':
                      puts(" "); /* just one space */
                      nblanks = 0; /* reset counter */
                      break;
            /* nonblank char */
            default:
                      /* print all the blanks up to here */
                      printf("%*s%c", nblanks, "", c);
                      state = 1; /* switch state */
                      break;
            } /* switch */
            break;
        /* we have read at least a nonblank char, so we must
         * echo the line until the end. */
        case 1: 
            if (c == 'n') {
                state = 0;
                nblanks = 0;
            } /* if */
            putchar(c);
            break;
        } /* switch */
    } /* while */
} /* main */

与K&R第二版完全兼容,所以你只需要编译它并运行。

也许最难遵循的陈述是中间的printf()线。 星号*允许我使用 printf 参数指定字段的宽度,传递空字符串""允许我打印包含nblanks空格的字符串。 最后的%c格式是打印刚刚读取的非空白字符。 这导致了一个紧凑而高效的代码。

最后,你有一些错误的想法:

  • b只返回终端中的一个字符(一个字符,而不是一行(。 我不仅在打印到终端或打印机时工作。 它不适用于文件(文件将获得退格符作为普通字符(
  • r使光标转到第一个显示列。 这仅适用于屏幕和打印机。 它在文件中不起作用,它作为普通字符包含在文件中。
  • 是 C 程序用来完成字符串的字符(以了解它们在内存中的位置完成( 它不是输出设备的特殊字符,也不执行任何操作(它是 ASCII NUL 字符,在输出终端上不执行任何操作(
  • 最后,如果您尝试在打印机上遵循b b方法,它不会擦除动漫,因为空间不会擦除已打印的内容。 因此,您必须遵循第二种方法。

所需的算法应该是这样的:

implement a state machine with two states.  NotInSpaces and InSpaces
(with just two states, a boolean would work)
no special treatment for 'n'
set state to NotInSpaces
Loop: (exit loop on EOF)
    getchar
    if char is space 
    then if state is NotInSpaces
         then set state to InSpaces
              output space
         endif
    else
         output char
    endif
end Loop:
output 'n' // to force output buffer flush

最新更新