【问题标题】:Why isn't this code compressing spaces correctly?为什么这段代码不能正确压缩空格?
【发布时间】:2017-06-07 01:43:12
【问题描述】:

我正在研究 K&R 的C 编程语言。我在这里做一个练习,上面写着“编写一个程序,将其所有输入复制到其输出,将一个或多个空格的每个字符串替换为一个空格。”

我相信我已经解决了。有些。当第一次使用a.out 运行程序时,我可以输入一个带有多个空格的数字,然后返回一个空格。但是,当我转到下一行并重试时,它会返回完全没有空格的数字。此外,如果我输入一串字母,例如“33 33 33”,它将只为整行留下一个空格。它变成“33 3333”。

我知道我可以只用 Google 搜索练习本身的答案,但我认为这不会帮助我了解我的代码为何如此运行。任何帮助将不胜感激。

main()
{
    int c, nl, upper;
    nl = 0;
    upper = 2;
    while( ( c = getchar() ) != EOF )
    {
        if( c == ' ' )
        { 
            ++nl;
            if( nl >= upper )
            {
                --c;
                --nl;
            }
        }
        putchar(c);
    }
}

【问题讨论】:

  • K&R 的C 编程语言 是一本非常过时的书,随着现代 C 语言的显着发展,它现在已经过时了。上一版发布于 1988 年 - 但从那时起,我们就有了 C89、C90、C11 和许多特定于编译器的变体。我的建议是把书收起来,然后从你的图书馆借一本更新的书籍,尤其是关注 C11 的书籍(以及反对原始 C 标准库的许多 unsafe 特性的书籍,喜欢gets:stackoverflow.com/questions/4588581)
  • 它对我有用。我使用标准的包含文件吗?
  • 是的,我相信我使用的是标准包含文件。我正在使用 。对我来说,它只在第一个“双空间”上起作用。 “hello__cold__World”,其中每个 _ 都是空白,返回“hello_coldWorld”,我不知道为什么。
  • c -= ' ' 的目的是什么?这相当于c = c - 32
  • dai,其实我已经改了,会在我的主帖里修改为--c,但是问题还是出现了

标签: c


【解决方案1】:

不错的尝试。 但是你犯了一些错误。

遇到空格以外的字符时,您没有将计数器设置为初始值。因此,如果您的输入在非空白字符(如33 33 33)之间有多个空白,则将打印第一个空白并跳过其他空白。所以输出将是33 3333

您必须了解 char 数据类型仅以 ASCII 编码存储单个字符 &。当您对 char 应用算术运算时,它只会更改字符值。因此,当您减少 char 变量时,它指的是另一个字符。所以最终它会打印垃圾值。

试试这个。

while ((c = getchar()) != EOF){
    if (c == ' '){
        ++nl;
        if (nl >= upper){
            continue;
        }
    }
    else{
        nl=0;
    }
    putchar(c);
}

逻辑很简单...
如果有多个空格,请放置第一个空格并跳过其他空格。

【讨论】:

  • 啊,好吧,这很有意义,真的有助于回答我的整个问题。谢谢。
  • @Bearz42 如果您的问题回答正确,则通过接受答案或提出查询来关闭问题,以便其他人可以尝试解决它。这就是堆栈溢出的工作原理。
【解决方案2】:
int main()
{
    int c, nl;
    nl = 0;
    while ((c = getchar()) != EOF)
    {
        if (c == ' ')
        {
            nl ++;
        }
        else
        {
            nl = 0;
        }

        if (nl <= 1)
        {
            putchar(c);
        }
    }
    return 0;
}

【讨论】:

    【解决方案3】:

    您发布的解决方案比它需要的更复杂-您还执行了一些对我来说似乎毫无意义的操作,例如c -= ' '

    我认为你应该练习设计算法和解决一般问题,而不是使用任何特定语言进行编程。想想你自己会怎么做

    在伪代码中,最小的解决方案如下:

    1. Read character C from input (if there is no input, end program)
    2. If character is a space character:
        2.1. Was the last printed character a space character too? If so, don't print anything and loop back to step 1.
    3. Else, print character C and loop back to step 1.
    

    在 C 中,这可以最低限度地(在 C11 中)写成:

    int main( void )
    {
        bool last_char_was_space = false;
        int c;
        while( ( c = getchar() ) != EOF )
        {
            if( last_char_was_space )
            {
                if( c == ' ' ) continue; // don't print anything
                else
                {
                    putchar( c );
                    last_char_was_space = false;
                }
            }
            else
            {
                putchar( c );
                if( c == ' ' )
                {
                    last_char_was_space = true;
                }
            }
        }
    
        return 0;
    }
    

    这个程序是“有限状态机”的一个简单示例,它是有状态算法的一个示例,也是正则表达式和其他类型解析器等事物的基础构建块。如果您想编写一个能够以最高性能和最低内存使用量快速处理数据的程序,那么这是您熟悉的一项基本技术。

    【讨论】:

    • 感谢您的反馈戴。我评论并编辑了我的帖子以将c -= ' ' 更改为--c 但我有点困惑为什么你说它没有意义。删除后,程序根本不会删除多余的空格。
    • @Bearz42 你的程序不应该“擦除”以前的输出——想想老式的计算机打印机输出(C 早于计算机显示器!)——在那些日子里你不能擦除任何东西——而是想想根据您已经处理的输入,您接下来应该输出的内容(以“仅向前”的方式) - 例如,这就是正则表达式的工作方式。
    • 哦,有道理。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 2023-03-11
    相关资源
    最近更新 更多