【问题标题】:Reading characters into a limited buffer size将字符读入有限的缓冲区大小
【发布时间】:2013-08-12 17:14:40
【问题描述】:

我有一个程序,它接收字符并将它们读入有限大小的缓冲区(在本例中为 64)。如果用户输入的字符超过 64 个,它必须拒绝整个输入字符串,警告用户输入的字符过多,然后重新开始。如果用户点击ctrl-D,这是一个文件结尾,程序必须退出。

所以我的设计如下:将实际的底层缓冲区设置为 65 个字符以容纳换行符。如果最后一个字符不是换行符,则用户点击ctrl-D,因此程序退出。如果缓冲区被填满(即它包含 65 个字符)并且最后一个不是换行符,则程序假定给定的字符太多,因此它进入一个循环并不断将输入读入缓冲区,直到缓冲区读取in 以换行符结尾(在这种情况下,它会警告用户限制并重新开始),或者它被缩短而不以换行符结尾(在这种情况下程序终止)。

我的问题是,我该如何处理用户输入正好 65 个字符(或 65 的某个整数倍),然后点击 ctrl-D 的情况?就目前的程序而言,当缓冲区被填满并且没有以换行符结束时,它假定存在溢出,但在这种情况下,我希望程序终止。如何让程序在收到 65 个字符的标量倍数和ctrl-D 时终止?

#include <string.h>
#include <unistd.h>

#define BUFSIZE ( 65 )


int main( int argc, char* argv[] ) {
    char* prompt = "myshell->";
    char* tooMany = "Max characters (64) exceeded.\n";
    int numInput;
    int done = 0;
    char input[ BUFSIZE ];
    while( !done ) {
        int cont = 0;

        write( STDOUT_FILENO, prompt, strlen( prompt ) );
        numInput = read( STDIN_FILENO, input, BUFSIZE );
        if( input[ numInput - 1 ] == '\n' ) {
            cont = 1;
        } else {
            if( numInput != BUFSIZE ) {
                done = 1;
                write( STDOUT_FILENO, "\n", strlen( "\n" ) );
            } else {
                int spill = 1;
                while( spill ) {
                    numInput = read( STDIN_FILENO, input, BUFSIZE );
                    if( input[ numInput - 1 ] == '\n' ) {
                        spill = 0;
                        write( STDOUT_FILENO, tooMany, strlen( tooMany ) );
                    } else {
                        if( numInput != BUFSIZE ) {
                            spill = 0;
                            done = 1;
                            write( STDOUT_FILENO, "\n", strlen( "\n" ) );
                        }
                    }
                }
            }
        }

        /*done ingesting input. Now do something with it...*/
        if( cont ) {
            write( STDOUT_FILENO, input, numInput );
        }

    }
    return 0;
}

约束:我只能使用readwrite 函数,但不能使用&lt;stdio.h&gt; 中的任何函数。

【问题讨论】:

  • 我相信你不应该限制输入行的大小。使用getline
  • @BasileStarynkevitch 可以,但我只能对 IO 使用系统调用。
  • 然后确保增加缓冲区以始终适合其中的一行(可能使用malloc ...)
  • @BasileStarynkevitch 但是那如何解决区分缓冲区溢出和完整缓冲区后跟ctrl-D的问题?
  • @Ataraxia 嗯? write()read() 也是 包装系统调用的 stdlib 函数。 puts() 和朋友们什么都不做。还是只能写内联汇编!?

标签: c input system-calls


【解决方案1】:

你真的应该接受任意大小的线条。请注意,阅读 tty -e.g.在终端中 - 与阅读不同,例如一些管道。 (伪tty-s 是一个复杂的话题:一些行缓冲发生在内核中)。

你应该有一些缓冲 - 你可能经常有read 比你需要的更多的字节,所以将额外的字节保留在缓冲区中以备将来使用。

所以你应该malloc 缓冲区(并在太小时重新分配它)。如果您的老师不允许malloc,请使用mmap 实现您自己的分配器

仔细阅读read(2) 手册页。不要忘记它可以在错误时返回 -1,在文件结束时返回 0,或者在成功时返回一些计数。

【讨论】:

  • 好的,我澄清了这个问题并删除了一些分散注意力的元素(比如提到这是一个外壳)。感谢您的帮助,但我相信我可能没有尽可能清楚地提出问题。
【解决方案2】:

如果这真的是一个外壳,那么为什么不处理更长的数据输入流呢?

如果您的缓冲区限制为 65/64 字节,则编写“读取/处理或解析文本/读取解析/等”。循环。

当您的代码最终收到一个 CTRL-D 时,然后执行所有解析的结果。

【讨论】:

  • 这回答了“什么是制作外壳的一种方法?”,但是您对如何解决我在如何在收到正好 65 个字节后终止执行的问题中提出的问题有任何建议由ctrl-D?
  • @Ataraxia,我们正在谈论程序员和程序员分析师之间的区别。程序员只会做他/她被告知要做的事情,而分析师将检查问题的需求并找到提供最多功能的最简单的解决方案。我认为您的用户不会喜欢输入 66 个字符的信息。然后被告知重新开始!
  • 是的,我同意字数限制太小。但不幸的是,在这种特殊情况下,设计限制并不取决于我。所以我不能在这里做程序员分析师..
  • 没有字数限制,尽管有人告诉你! (除非您没有提到会改变此类评论的关键事实)。理论上,您可以一次发出一个读取一个字符的系统调用。这一直在编译器的解析器中编码。如果没有别的,一次读取一个字符,当字符数 = 65 并且没有找到 ctrl-d 时,然后惩罚用户。
  • 我负责制作的程序中有一个字符限制,我的程序负责执行。
猜你喜欢
  • 2022-11-11
  • 2011-05-26
  • 2012-03-16
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多