【问题标题】:Making getline() in C在 C 中制作 getline()
【发布时间】:2019-01-12 17:32:09
【问题描述】:

我想在 C 中创建自己的 getline() 类函数,这就是我想出的:

void getstring(char *string)
{ 
    fgets(string,STRING_LENGTH,stdin);
    string[strlen(string)-1]='\0';
}

如果键入的字符数不超过 STRING_LENGHT(在本例中为 100)就足够了,但一旦超过,它上面的所有内容都会留在缓冲区中并跳转到下一个读取字符串。

我已经尝试使用以下过程刷新缓冲区:

void flush_buffer()
{
    char c;
    while((c = getchar()) != '\n' && c != EOF)
        /* discard */ ;
}

它在所描述的情况下完成了它的工作,但是一旦字符串不超过 STRING_LENGHT,我需要在继续之前输入任何内容。

有什么方法可以读取字符串以便我知道是否超过了 STRING_LENGHT 以便我可以调节冲洗?

如果有更好的方法来制作类似 getline() 的函数,那就更好了。

【问题讨论】:

  • 首先确保您的系统没有getline function
  • 还有一个很好的方法可以知道the fgets function是否读取了最大字符数:字符串中是否有换行符?您还需要处理错误以及实际上没有读取换行符的情况。
  • @Someprogrammerdude 为什么要确保系统还没有一个?我认为他这样做是出于教育目的,以了解如何编写这样的函数。
  • 您的函数与标准的getline() 完全不同。 string参数应该是char **,这样函数就可以调用malloc()realloc()来分配足够的空间。
  • getline() 的全部意义在于该行可以是任意长度,没有预定义的LINE_LENGTH 限制。调用者不必分配缓冲区,函数自己分配。

标签: c string buffer getline


【解决方案1】:

有什么方法可以读取字符串以便我知道是否超过了 STRING_LENGHT 以便我可以调节冲洗?

fgets() 读取的字符数量不会达到或超过STRING_LENGHT

但是要找出是否还有更多的行未读,通常的方法是检测读取的字符串是否具有最大长度并且不包含'\n'。

// return EOF, 0 (not all line was read) or 1 (all the line was read)
int getstring(char *string) { 
  if (fgets(string,STRING_LENGTH,stdin) == NULL) {
    return EOF;
  }
  int retval = 1;
  size_t sz = strlen(string);
  if (sz + 1 == STRING_LENGTH && string[sz-1] != '\n') {
    int c;
    while((c = getchar()) != '\n' && c != EOF) {
      retval = 0;
    } 
  }
  return retval;
}

更健壮地传递大小

// int getstring(char *string) { 
//  if (fgets(string,STRING_LENGTH,stdin) == NULL) {

int getstring(char *string, int sz) { 
  if (fgets(string,sz,stdin) == NULL) {

但要与getline() 相同,还需要进行更多更改。 @Barmar


当 char 无符号且文件结尾为真时,OP 的 flush_buffer() 是一个无限循环。使用int

void flush_buffer(void) {
    // char c;
    int c;
    while((c = getchar()) != '\n' && c != EOF)
        /* discard */ ;
}

string[strlen(string)-1]='\0'; 是未定义的行为 (UB),如果 fgets() 读取的第一个字符是空字符 - 一个很好的小漏洞可以避免。

fgets(string,STRING_LENGTH,stdin);
if (*string) {
  string[strlen(string)-1]='\0';
}

另见Removing trailing newline character from fgets() input

【讨论】:

  • 与 Barmar 的观察一样,请注意 getlinefgets 不同,它允许输入包含 NUL 字符,因为它显式返回读取的字符数。这使得使用fgets 无法正确实现。
  • @rici 回复 fgets(),空字符和“无法正确实现”,请参阅 Is it possible to read null characters correctly using fgets or gets_s?fgets() 不是关于空字符的最佳工具 - 但“不可能”是值得商榷的。
  • 好吧,“不费吹灰之力”:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多