在C中实现getchar问题

时间:2016-07-05 19:31:09

标签: c

我实施ConcurrentDictionary<K,V>getchar()有两个问题,当我使用BUFF_SIZE时,1024读取所有字符并返回一个字符丢弃其余的部分。这在循环中不起作用。

getchar()

当我将#ifndef BUFF_SIZE #define BUFF_SIZE 1024 #endif int my_getchar(void) { static char buff[BUFF_SIZE]; static char *chr; int ret; if ((ret = read(STDIN_FILENO, buff, BUFF_SIZE)) > 0) { chr = buff; return (*chr); } return (EOF); } int get_line(char **line) { char *text = malloc(sizeof(char) * 4092); int position = 0; int c; if (!text) return (-1); while (1) { c = my_getchar(); if (c == EOF || c == '\n') { text[position] = '\0'; *line = text; return (1); } else text[position] = c; position++; } return (0); } 设置为BUFF_SIZE时,它在循环内工作正常,并且在循环外无法正常工作。我怎么解决这个问题?

1

enter image description here

5 个答案:

答案 0 :(得分:0)

您的my_getchar()跳过每个调用的BUF_SIZE - 1个字符。每次调用它时 - 它会从BUF_SIZE读取stdin个字符(如果我们位于文件的末尾,则会更少)并返回第一个字符。所有其他都被删除了,因为当你下次再次调用它时它再次读取BUF_SIZE个字符而不是从先前读取的缓冲区返回下一个字符。

答案 1 :(得分:0)

当你将BUFF_SIZE设置为1时,你正在调用这样的读取:

 read(STDIN, buff, 1)

但是,由于STDIN连接到终端,因此允许read()在返回第一个字符之前等待输入一行。因此,该函数的行为正确(如所写)。

好消息是,如果你使用printf("%c\n", getchar());,你会发现getchar()的行为方式相同。

您的版本的主要问题是它构建在read()之上 - 真正的getchar()位于<stdio.h>,并且可以与使用中的调用混合FILE*及其缓冲。因此,除非您重新实现所有stdio,否则在其基元(例如fread)上构建它可能是有意义的。

如果要重新实现所有<stdio>,那么你应该实现一些等效于FILE的缓冲区所在的位置(不在函数内部的静态变量中)。

答案 2 :(得分:0)

OP的代码读取BUFF_SIZE char s,仅返回1.

需要有选择地阅读。仅在以前的字符被填充时读取。

注意:最好将结构指针传递给状态buff, index,count),而不是使用static变量,但要遵循OP的方法:< / p>

int my_getchar(void) {
    static unsigned char buff[BUFF_SIZE];
    static int index = 0;
    static int count = 0;

    if (index >= count) {
      index = 0;
      count = read(STDIN_FILENO, buff, BUFF_SIZE);
      if (count == 0) return EOF;  // end-of-file
      if (count < 0) return EOF;  // I/O error
    }
    return buff[index++];
  }

注意:阅读unsigned char缓冲区以区分EOF和输入租船人非常重要。

根据STDIN_FILENO属性,read()的返回值0可能只是意味着输入目前不可用。然后使用

      // count = read(STDIN_FILENO, buff, BUFF_SIZE);
      // if (count == 0) return EOF;  // end-of-file
      do {
        count = read(STDIN_FILENO, buff, BUFF_SIZE);
      } while (count == 0);

答案 3 :(得分:-1)

您的my_getchar功能存在问题。问题在这里:

/* When you do return *char only first char is returned */
if ((ret = read(STDIN_FILENO, buff, BUFF_SIZE)) > 0)
{
    chr = buff;
    return (*chr); 
}

您正在执行return (*chr);只返回char中的第一个buff,这样就不会返回\n,因此您的get_line是受影响因为它取决于\n返回。这可以通过添加一个额外的静态变量来跟踪返回的最新char的位置来解决这个问题,如下所示。

int my_getchar(void)
{
    static char buff[BUFF_SIZE];
    static char *chr;
    static int pos = 0;  /* New static variable to track position */
    static int ret = 0;  /* Changed this to static */

    if (pos >= ret) { /* if all data in buffer has been returned */
            if ((ret = read(STDIN_FILENO, buff, BUFF_SIZE)) > 0)
            {
                    chr = buff;
                    pos = 0;
                    return *(chr + pos++); /* return one char and update pos */
            } else {  /* if no more to read from stdin */
                    return EOF;
            }
    } else { /* if data still in buffer */
            return *(chr + pos++); /* return one char and update pos */
    }
}

现在,当my_getchar到达缓冲区中\n的邮件时,pos将返回\n,因此get_line将在新版本之前获取所有字符线字符。

答案 4 :(得分:-2)

您的代码会尽可能多地读取字符:

read(STDIN_FILENO, buff, BUFF_SIZE)

最多BUFF_SIZE,然后只返回第一个字符。

为了使其按预期工作,您的缓冲区大小必须为1。