Как сделать функцию строки с пользовательским вводом в C? - PullRequest
0 голосов
/ 21 сентября 2018

Я знаю, как сделать функцию с int, double, float с пользовательским вводом внутри (я сейчас использую scanf).

int getData(){
    int a;
    scanf("%i",&a);
    return a;
}

, но как сделать функцию с строковым типом и пользовательским вводом внутри, тогда мывернуть это значение с типом string?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Расширение Арку подход к неограниченному размеру (фактически он ограничен SIZE_MAX - 1 символ) в качестве ввода:

#include <stdlib.h>
#include <string.h>

#define BUFFER_MAX (256)

int read_string(FILE * pf, char ** ps)
{
  int result = 0; 

  if (!ps)
  {
    result = -1;
    errno = EINVAL;
  }
  else
  {
    char buffer[BUFFER_MAX];
    size_t len = 0;

    *ps = NULL;
    while (NULL != fgets(buffer, sizeof buffer, pf))
    {
      len += strlen(buffer);

      {
        void * p = realloc(*ps, len + 1);
        if (!p)
        {
          int es = errno;
          result = -1;
          free(*ps);
          errno = es;
          break;
        }

        *ps = p;
      }

      strcpy(&(*ps)[len], buffer);
    }

    if (ferror(pf))
    {
      result = -1;
    }
  }

  return result;
}

Назовите это так:

#include <stdlib.h>
#include <stdlio.h>

int read_string(FILE * pf, char ** ps);

int main(void);
{
  char * p;

  if (-1 == read_string(stdin, &p)) /* This read from standard input, 
                                       still any FILE* would do here. */
  {
    perror("read_string() failed");
    exit(EXIT_FAILURE);
  }

  printf("Read: '%s'\n", p);

  free(p); /* Clean up. */
}
0 голосов
/ 21 сентября 2018

Строка AC - это массив char, оканчивающийся нулевым (нулевым) байтом.Массивы обычно передаются как указатели на первый элемент.Проблема с возвратом этого из функции заключается в том, что указанный адрес должен оставаться действительным в течение срока действия функции, что означает, что он должен быть либо буфером static (который затем перезаписывается при любых последующих вызовах той же функции,нарушает ранее возвращенные значения) или распределяется функцией, и в этом случае вызывающая сторона отвечает за ее освобождение.

Упомянутый вами scanf также проблематичен для чтения интерактивного пользовательского ввода, например, он может оставить вводв неожиданном состоянии, например, когда вы не используете символ новой строки в конце строки, вызов next на scanf (возможно, в несвязанной функции) может неожиданно не дать ожидаемого результата, когда онвстречается с новой строкой.

Часто построчно считывать ввод в буфер, например, с fgets, а затем анализировать строку оттуда.(Некоторые входные данные вы можете анализировать без буфера, просто читая символ за символом, но такой код часто становится длинным и трудным для быстрого следования.)

Пример чтения любой строки, которая может содержать другие пробелычем символ новой строки, будет выглядеть примерно так:

/// Read a line from stdin and return a `malloc`ed copy of it without
/// the trailing newline. The caller is responsible for `free`ing it.
char *readNewString(void) {
    char buffer[1024];
    if (!fgets(buffer, sizeof buffer, stdin)) {
        return NULL; // read failed, e.g., EOF
    }
    int len = strlen(buffer);
    if (len > 0 && buffer[len - 1] == '\n') {
        buffer[--len] = '\0'; // remove the newline
        // You may also wish to remove trailing and/or leading whitespace
    } else {
        // Invalid input
        //
        // Depending on the context you may wish to e.g.,
        // consume input until newline/EOF or abort.
    }
    char *str = malloc(len + 1);
    if (!str) {
        return NULL; // out of memory (unlikely)
    }
    return strcpy(str, buffer); // or use `memcpy` but then be careful with length
}

Другой вариант заключается в том, чтобы вызывающая сторона предоставляла буфер и его размер, а затем просто возвращала тот же буфер в случае успеха и NULL в случае ошибки.Преимущество этого подхода заключается в том, что вызывающая сторона может решить, когда буфер используется повторно и нужно ли скопировать строку или просто прочитать ее один раз и забыть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...