读取一行输入 c

reading a line of input c

我正在尝试编写一个 C99 程序(如果可能的话不使用 GNU 扩展)需要从用户那里获取任意长度的输入。这是我到目前为止所拥有的,它在第 26 行保持 SEGFAULT-ing。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>

int get_line(char* buffer, FILE* fp) {
    int bufread = 0;
    int bufsize = LINE_MAX;
    if(buffer == NULL) {
        buffer = (char*)malloc(sizeof(char)*bufsize);
        strcpy(buffer, "");
    }

    while(true) {
        if(bufread == bufsize) {
            bufsize += LINE_MAX;
            buffer = (char*)realloc(buffer, sizeof(char)*bufsize);
        }

        char character = fgetc(fp);

        if(character == '\n') {
            break;
        } else {
            strcat(buffer, character);
            bufread += 1;
        }
    }

    return bufread;
}

int main() {
    printf("Enter a string: ");
    char* string = NULL;
    int chars_read = get_line(string, stdin);
    printf("The number of chars read is %d\n", chars_read);
    printf("The string you entered was %s\n", string);
    return 0;
}

get_line

   buffer = (char*)malloc(sizeof(char)*bufsize);
   strcpy(buffer, "");
  • 执行 strcpy 将第一个字符设置为 0 是一种复杂的方法,只需执行 *buffer = 0;.

  • sizeof(char) 根据定义为 1

  • 你不需要做转换

还要注意,如果 buffer 在参数中没有给出 NULL 行为是危险的并且可以是未定义的,因为代码假设给定的缓冲区至少有 LINE_MAX 个字符.

  char character = fgetc(fp);

你无法检测到 EOF,需要是一个 int

   if(character == '\n') {
       break;

您没有检测到 EOF

您错过了在 buffer 末尾添加空字符,在 while

之后

strcat(buffer, character);

这是无效的,因为 strcat 的第二个参数必须是 char*strcat 连接两个字符串,而不是带有一个字符的字符串

假设有一个strcat来追加一个字符,这样每次都会搜索字符串的末尾来追加字符,只需使用 bufread gic 索引

因为函数的配置文件是

int get_line(char* buffer, FILE* fp) {

当您离开 get_line 时,您丢失了 buffer 的当前值,造成内存泄漏,并且在 main printf("The string you entered was %s\n", string); 打印空指针。为避免这种情况,您可以将字符串作为输出参数,让您仍然 return 新长度 :


提议:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>

size_t get_line(char ** buffer, FILE* fp) {
  size_t bufsize = LINE_MAX;
  size_t bufread = 0;

  *buffer = malloc(bufsize);

  if (*buffer == NULL)
    return 0;

  while (true) {
    if (bufread == bufsize) {
      bufsize += LINE_MAX;
      *buffer = realloc(*buffer, bufsize);
    }

    int character = fgetc(fp);

    if ((character == '\n') || (character == EOF)) {
      (*buffer)[bufread] = 0;
      /* note you can do : *buffer = realloc(*buffer, bufread + 1); to only use the needed memory */
      return bufread;
    }

    (*buffer)[bufread++] = character;
  }
}

int main() {
  printf("Enter a string: ");

  char * string = NULL;
  size_t chars_read = get_line(&string, stdin);

  if (string != NULL) {
    printf("The number of chars read is %zu\n", chars_read);
    printf("The string you entered was '%s'\n", string);
    free(string);
  }
}

编译与执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra p.c
pi@raspberrypi:/tmp $ ./a.out
Enter a string: is it working ?
The number of chars read is 15
The string you entered was 'is it working ?'
pi@raspberrypi:/tmp $ ./a.out
Enter a string: 
The number of chars read is 0
The string you entered was ''

valgrind下:

pi@raspberrypi:/tmp $ valgrind ./a.out
==20382== Memcheck, a memory error detector
==20382== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20382== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==20382== Command: ./a.out
==20382== 
Enter a string: what about memory leak ?
The number of chars read is 24
The string you entered was 'what about memory leak ?'
==20382== 
==20382== HEAP SUMMARY:
==20382==     in use at exit: 0 bytes in 0 blocks
==20382==   total heap usage: 3 allocs, 3 frees, 4,096 bytes allocated
==20382== 
==20382== All heap blocks were freed -- no leaks are possible
==20382== 
==20382== For counts of detected and suppressed errors, rerun with: -v
==20382== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)