读取输入c的一行

时间:2019-02-12 17:31:18

标签: c99 getline

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

#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;
}

1 个答案:

答案 0 :(得分:1)

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的机会

您错过了 while

之后的 buffer 末尾添加空字符的操作

strcat(buffer, character);

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

假设有一个 strcat 可以附加一个字符,每次搜索字符串的末尾以附加字符时,只需使用 bufread 即可,索引

因为该功能的配置文件是

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

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


提案:

#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)