【问题标题】:Reading each character at a time - C一次读取每个字符 - C
【发布时间】:2016-10-13 01:39:14
【问题描述】:

对于下面的question

练习 12336 - 从程序的标准输入中一次读取一个字符的普通文本,并将其打印出来,每行从左到右颠倒。阅读直到遇到数据结束`

您可能希望通过键入`来测试程序

      prog5rev | prog5rev

查看是否重新创建了原始输入的精确副本。要将字符读取到数据末尾,请使用循环,例如`

   char ch;
   while( ch = getchar(), ch >= 0 ) /* ch < 0 indicates end-of-data */
    or
    char ch;
    while( scanf( "%c", &ch ) == 1 ) /* one character read */

这是我的解决方案:

#include  <stdio.h>

void f(char *);
int main(void)
{
    char ch = getchar();
    f(&ch);

    return 0;
}

void f(char *ch){
    if(*ch < 0)
        return;
    else{
        char character = getchar();
        f(&character);
    }
    putchar(*ch);
}

输入:

abc | abc

输出:

cba | cba

问题:

问题说:print it with each line reversed from left to right.

这个解决方案正确吗?

【问题讨论】:

  • 在规定中,我认为prog5rev是程序的名称,而不是样本输入。他们建议运行程序两次(将结果通过管道传输到另一个),并提供一些其他输入,并期望输出与输入相同,因为它被反转了两次。您似乎将其误解为在程序输入中键入 | 的意思。

标签: c getchar


【解决方案1】:

这是一个非常聪明的解决方案,我真的不想破坏它,但是使用堆栈来解决它有一些限制。确切地说是内存限制。如果您有超过一定的、相对少量的输入,它将达到限制并以一种或另一种方式崩溃,例如:分段错误。来自古腾堡的完整莎士比亚的所有 5,560,737 个字符都没有通过,它在字符 654,337 处出现段错误。

抱歉,您需要使用堆来进行更大的输入。

【讨论】:

  • 我无条件地偏向递归。总是试图找到奇怪的方法来给出递归解决方案。这对我来说是个大问题
  • @overexchange 只要你知道它的局限性,这种方法绝对没有问题。
【解决方案2】:

是的,这按预期工作。

你读入一个字符并调用f。如果没有读取 EOF,请再次调用 f,然后打印读取的字符。因为您在递归调用之后打印字符,所以字符以相反的顺序打印。

但是,您应该进行的一项更改是使用int 而不是char 作为数据类型。 getchar 函数返回 int 以便可以正确检测到 EOF。 putchar 函数接受 int,因此您无需担心。

此外,由于调用函数没有更改它,因此无需传递读取到的变量的地址。您可以简单地传递变量的值并相应地更改函数。

【讨论】:

    【解决方案3】:

    问题的陈述已经给出了解决方案的提示:

       char ch;
       while( ch = getchar(), ch >= 0 ) /* ch < 0 indicates end-of-data */
        or
        char ch;
        while( scanf( "%c", &ch ) == 1 ) /* one character read */
    

    您必须使用循环从stdin 读取数据,然后在循环内测试是否有新行,然后才从右到左打印该行(恢复字符串)。

    以下是一个以简单方式完成任务的代码,它可能需要一些改进,但它可以工作。

    请阅读 cmets 并尝试了解其中发生的情况,如果您有任何问题,请询问他们。

    #include <stdio.h>
    #include <string.h> // for memset
    
    void f(char *, int);
    
    int main(void)
    {
        char ch;
        char buffer[1024] = { 0 }; // 1024 = max supported line length
        int i; // ieterator
    
        i = 0;
        while( scanf( "%c", &ch ) == 1 ) { // while there is input
            if ( ch == '\n' ) { // if there is a new line
                f(buffer, i); // print the line (inverted)
                i = 0; // reset iterator
                memset(buffer, 0, 1024); // reset buffer
            } else {
                buffer[i++] = ch; // append read char to the buffer
            }
        }
    
        return 0;
    }
    
    void f(char *str, int n) {
        // just print from right to left (easier than reversing and then printing the string)
        while (n >= 0) {
            putchar(str[n]);
            n--;
        }
        putchar('\n');
    }
    

    更新:本书建议使用

    测试程序
     prog5rev | prog5rev
    

    我建议创建一个输入文件然后运行:

     $ prog5rev < input.txt | prog5rev
    

    前面的语句假设您使用的是 linux(或某些 unix)。

    例子:

    [ichramm@wilderjager][~]$ cat input.txt 
    hello
    world
    [ichramm@wilderjager][~]$ ./test < input.txt  
    olleh
    dlrow
    [ichramm@wilderjager][~]$ ./test < input.txt | ./test 
    hello
    world
    

    【讨论】:

    • 请不要完成他的整个家庭作业...一定要指导和回答尖锐的问题,但放弃整个墨西哥卷饼并不能帮助他学习如何思考实践的重点
    • @ScottStensland 你是认真的吗?规则很明确:答案必须完整。因此,如果答案不完整,您就投反对票,如果答案太完整,您也会投反对票?下定决心!
    猜你喜欢
    • 1970-01-01
    • 2012-09-10
    • 2013-01-11
    • 2021-10-15
    • 1970-01-01
    • 2012-04-08
    • 2013-06-27
    • 2014-03-21
    • 1970-01-01
    相关资源
    最近更新 更多