2016-03-14 4 views
0

Так что я пытаюсь запрограммировать функцию, которая позволяет пользователю вводить неограниченное количество символов. Например:Получение неограниченного ввода в C?

char string[100] 

ограничивает ввод до 100 символов.

код я до сих пор является:

#include<stdio.h> 

char* uinput(){ 
    char *string, *current; 
    int counter = 0; 
    string = (char *) malloc(10 * sizeof(char)); 
    do{ 
     realloc(string, counter * sizeof(char)); 
     current = string + counter; 
     *current = getchar(); 
     counter++; 
    }while(*current != '\n'); 
    return string; 
} 

int main(){ 
    char *s; 
    s = uinput(); 
    printf("\nYou entered: %s", *s); 
    return 0; 
} 

Я новичок на указатели, так что я не знаю, почему это не работает (сбой программы). То, что я пытаюсь сделать, это продолжать чтение символа и продолжать перемещать указатель на строку, чтобы количество байт продолжало увеличиваться до тех пор, пока пользователь не нажимает enter ('\ n').

Благодаря ~ Raf

+0

Функция 'getline' - простой ответ. Первоначально это было расширение glibc (то есть не стандартная библиотека C), но оно также должно поддерживаться в режиме mingw. Если вам когда-либо нужно беспокоиться о кросс-платформе, тогда ее можно переопределить с помощью fgets и realloc. –

+0

@rafaelThedoublemaster есть много проблем с кодом, я пишу ответ. –

ответ

1

Этот подход является нормальным, но есть незначительные детали, которые являются неправильными. Если вы скомпилируете с включенными предупреждениями, вы заметите, что вам не хватает <stdlib.h>; также вы указываете первый символ на printf вместо указателя на буфер.

Тогда существует очевидная ошибка, что размер сбрасывается до 0, и вы casting the return value of malloc, используя char для хранения результата getchar() который также является неправильным, потому что вы не можете проверить на EOF. Вы не сохраняете указатель ed; и вы не завершаете строку правильно. По второстепенным деталям вы должны удвоить размер буфера в каждом realloc, потому что realloc необходимо потенциально скопировать всю строку, поэтому со временем она становится медленнее и медленнее по мере роста длины строки.

Таким образом, мы получаем:

#include <stdio.h> 
#include <stdlib.h> 

char* uinput() { 
    char *string; 
    // number of characters in the buffer 
    size_t counter = 0; 

    // size of allocated buffer 
    size_t allocated = 16; 

    int c; 
    string = malloc(allocated); // sizeof(char) is 1 
    do { 
     c = getchar(); 
     if (c == EOF) { 
      break; 
     } 
     // if our buffer is too small, double the allocation 
     if (counter + 2 <= allocated) { 
      size_t new_size = allocated * 2; 
      char *new_buffer = realloc(string, new_size); 
      if (! new_buffer) { 
       // out of memory? try smaller increment 
       new_size = allocated + 16; 
       new_buffer = realloc(string, new_size); 
       if (! new_buffer) { 
        // really out of memory: free old block 
        free(string); 
        return NULL; 
       } 
      } 
      allocated = new_size; 
      string = new_buffer; 
     } 
     // store the character 
     string[counter++] = c; 
    } while (c != '\n'); 

    // terminate the buffer properly 
    string[counter] = 0; 
    return string; 
} 

int main() { 
    char *s = uinput(); 
    if (!s) { 
     // possibly out of memory in uinput 
     perror("Error reading input"); 
     exit(EXIT_FAILURE); 
    } 
    printf("\nYou entered: %s", s); 
    free(s); 
    return EXIT_SUCCESS; 
} 
+0

Надеюсь, что я не делал слишком много UB в шахте. Я думаю, что мне нужно обеспечить реализацию PD getline: D –

+0

Wow спасибо за ответ: D Так много больше материала мне нужно узнать о C. Кстати, вы можете объяснить EOF? Первый раз я видел его –

+0

Конец файла. Если вы нажмете 'ctrl-d' в Linux или' ctrl-z' на windows; или если вы хотите использовать такой подход для файлов (вы можете использовать 'fgetc' вместо' getchar') –

2

Хорошо, я думаю, что это проблема

вы повторно allocing

realloc(string, counter * sizeof(char));

какой будет размер строки в первой итерации? Это будет 0.

Теперь вы пишете указатель, который содержит 0 байт и, следовательно, segfault.

Изменение его на while loop может помочь устранить его. Вы также можете изменить начальное значение счетчика, чтобы исправить его

+0

Ошибка за один раз, хорошо видно. –

+0

хорошо заметил: D Я просто попробовал сменить счетчик на 1, но программа все еще терпит крах (не отвечает) –

0

Вы могли бы попробовать что-то вроде следующего:

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

struct person{ 
    char *name; 
}pers; 

void addMem(void); 

int main(void){ 
    addMem(); 

    printf("\nYour name is:> %s\n",pers.name); 
    free(pers.name); 
    pers.name = NULL; 
    return 0; 
} 

void addMem(void){ 
    unsigned int length = 6; 
    size_t newLength = 0; 
    unsigned int newSize = 0; 
    unsigned int i =0; 
    char *name; 
    int c; 

    name = malloc(length); 
    if(name == NULL){ 
     exit(1); 
    } 
    newSize = length; 

    printf("Enter your name:> "); 

    while ((c = getchar()) != '\n' && c!=EOF){ 
     name[i++]=(char)c; 

     if(i == newSize){ 
      newSize = i+length; 
      name = realloc(name, newSize); 
     } 
    } 

    name[i] = '\0'; 

    newLength = strlen(name)+1; 
    pers.name = malloc(newLength); 

    memcpy(pers.name, name, newLength); 

    free(name); 
    name = NULL; 
} 
+0

Никогда не вызывайте 'realloc' следующим образом:' name = realloc (name, newSize) '- он не работает, тогда у вас есть утечка памяти - используйте временный указатель, пока не узнаете, удалось ли« realloc »или нет. –

0

Другой подход заключается в использовании fgets(), который получает строку в размера буфера из входного потока; если он имеет полный ввод, то строка заканчивается на \n; если это не так, то это не так. Таким образом, вы можете цитировать вызовы fgets до тех пор, пока в конце не будет символ EOL, а затем в зависимости от того, что ваша программа делает с входом, вы можете решить, следует ли перераспределять или обрабатывать входные данные понемногу.

Смежные вопросы