C语言程序设计,第一章练习1.10(Getchar和Putchar)

8

我已经在做这个问题2个小时了,但还是卡住了...我在网上找到了答案,但这并不能帮助我理解我显然缺失的概念。

提示:编写一个程序,将其输入复制到其输出,用\t替换每个制表符,用\b替换每个退格符,用\\替换每个反斜杠。这将以一种明确的方式显示制表符和退格符。

这是我想出的代码,它没有将tab\替换为指定的putchar,而只是在它前面添加了它。(我没有做退格键,因为我真的无法输入退格键...)

这是我读代码的方式。我漏掉了什么?

"有一个整数c。当输入不等于文件结尾时,c 等于输入。如果输入是制表符,则输出\t。如果输入是\,则输出\\。将输入输出到控制台。"

int c;

while((c=getchar())!=EOF)
{
    if(c=='\t')
        {
            putchar('\\');
            putchar('t');
        }

    if(c=='\\')
        {
            putchar('\\');
            putchar('\\');
        }
    putchar(c);
}

如果输入是制表符,则输出\t。如果输入是\,则输出\。将输入输出到控制台。如果这些情况同时发生怎么办? - Jim Balter
8个回答

9
你的主要问题在于,无论你是否已经输出了字符的翻译,你都会输出该字符。那些if语句会按照你的期望执行,但是在它们目前的形式下,它们只是简单地跳过到下一条语句。
因此,你需要寻找更像这样的解决方案:
while ((c = getchar()) != EOF) {
    // Detect/translate special characters.

    if (c == '\t') {
        putchar ('\\');
        putchar ('t');
        continue;              // Go get next character.
    }

    if (c == '\b') {
        putchar ('\\');
        putchar ('b');
        continue;              // Go get next character.
    }

    if (c == '\\') {
        putchar ('\\');
        putchar ('\\');
        continue;              // Go get next character.
    }

    // Non-special, just echo it.

    putchar (c);
}

另一种更简洁的可能性是:
while ((c = getchar()) != EOF) {
    // Detect/translate special characters, otherwise output as is.

    switch (c) {
        case '\t': putchar ('\\'); putchar ('t');  break;
        case '\b': putchar ('\\'); putchar ('b');  break;
        case '\\': putchar ('\\'); putchar ('\\'); break;
        default:   putchar (c);
    }
}

3
你可以使用else if代替if,这样就不需要使用那么多的continue了。 - theharshest
谢谢!你是我的英雄。 - user3505236
@theharshest,我更喜欢在开头使用一致的条件组而不是可能的缩进地狱 :-) 无论如何,我可能会自己实现(新的) switch 变量。 - paxdiablo

4

我知道我来晚了,但这个问题在第一章中就出现了,在介绍elsecasecontinue和函数之前。

这里有一个可以解决练习1-10的工作方案,只涉及到练习点之前介绍的概念。你需要跟踪是否找到了转义字符,然后仅在没有找到时显示复制的字符。

#include <stdio.h>

int main() {

  int input;

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

    int escaped = 0;

    if(input == '\t'){
        putchar('\\');
        putchar('t');
        escaped = 1;
    }

    if(input == '\b'){
        putchar('\\');
        putchar('b');
        escaped = 1;
    }

    if(input == '\\'){
        putchar('\\');
        putchar('\\');
        escaped = 1;
    }

    if(escaped == 0){
      putchar(input);
    }
  }
}

1

我是一名新手。但考虑到他们在那时所教授的,我得出了这个答案。

#include <stdio.h>

main() 
{
    int c;

    c = getchar();

    while (c != EOF) {
        if (c == '\t') {
            putchar('\\');
            putchar('t');
        }
        else if (c == '\b') {
            putchar('\\');
            putchar('b');
        }
        else if (c == '\\') {
            putchar('\\');
            putchar('\\');
        }
        else {
            putchar(c);
        }  
        c = getchar();  
    }
}

1

有许多方法可以实现这一点,paxdiablo提供了几种好方法。这里是一个通过函数分解展示DRY原则的例子:

void putesc(char c)
{
    putchar('\\');
    putchar(c);
}

void ioloop(void)
{
      for (int c;;)
          switch (c = getchar())
          {
               case EOF:  return;
               case '\t': putesc('t'); break;
               case '\b': putesc('b'); break;
               case '\\': putesc(c); break;
               default:   putchar(c); break;
          }
 }

1

添加另一个解决方案!对于我们这些新手来说,这很有用,可以丰富我们的知识,看到不同的解决方案。

#include <stdio.h>

/* a program to copy its input to its output, replacing tab by \t,
    backspace by \b, backslash by \\  */
    
/* need double backslash to output a single backslash */

int main(){
    
    int c;          /*  to store next character from getchar() */
        
    while((c = getchar()) != EOF){
        if( c != '\t' && c != '\b' && c != '\\')        /* print all characters except special one's */
            putchar(c);                             
            
        else{
            if(c == '\t'){          /* replacing tab by \t */
                putchar('\\');
                putchar('t');
                }
            
            if(c == '\b'){          /* replace backspace by \b */ 
                putchar('\\');
                putchar('b');
                }
                
            if(c == '\\'){          /* replace backslash by \\ */
                putchar('\\');
                putchar('\\');
                }       
        }
        
    }

}

0
    #include <stdio.h>

    int main(int argc, const char * argv[]) {
    
        int c;
        int tab = 't';
        int backspace = 'b';
        int backslash = '\\';

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

            if (c == '\t'){
                putchar('\\');
                putchar(tab);
            }
            else if(c == '\b'){
                putchar('\\');
                putchar(backspace);
            }
            else if(c == '\\'){
                putchar('\\');
                putchar(backslash);
            }
            else{  // All other characters EXCLUDING "tab, backspace and backslash"
                  // will always be printed.
                putchar(c);
            }
        }

       return 0;
   }

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0
你已经非常接近了。只需将每个块中的第二个 "putchar()" 更改为赋值语句,就可以得到正确的输出。
int c;

while((c=getchar())!=EOF)
{
    if(c=='\t')
        {
            putchar('\\');
            c = 't';
        }

    if(c=='\\')
        {
            putchar('\\');
            c = '\\';
        }
    putchar(c);
}

-2
在练习之前,书中提到了ASCII码而不是更高级的语句。因此,我认为解决方案是针对使用ASCII进行定向的。
    int c;
    while ( (c = getchar()) != EOF ){
        //92 is the ASCII code for the backslash \
        if ( c == '\t'){
            putchar(92);
            putchar('t');
        }else if ( c == '\\' ) {
            putchar(92);
            putchar(92);
        }else if ( c == '\b' ) {
            putchar(92);
            putchar('b');
        }else{
            putchar(c);
        }
    }

1
这本书还说,对于阅读代码的程序员来说,使用'A'而不是65更好、更有用。 - knoftrix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接