чтение строки ввода c - PullRequest
       10

чтение строки ввода c

0 голосов
/ 12 февраля 2019

Я пытаюсь написать программу на C99 (без расширений GNU, если это вообще возможно), которая должна принимать данные от пользователя произвольной длины.Вот то, что я имею до сих пор, и он держит SEGFAULT-IN на линии 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 голосов
/ 17 марта 2019

In 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

In

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

Вы пропустили обнаружение EOF

Вы пропустили добавление нулевого символа в конце буфера здесь после в то время как

В

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); printf нулевой указатель.Чтобы избежать этого, вы можете указать строку в качестве выходного параметра, что позволит вам по-прежнему возвращать новую длину:


Предложение:

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