Jak dynamicznie przydzielać miejsce w pamięci dla Ciągu i uzyskać ten ciąg od użytkownika?

Chcę odczytać dane wejściowe od użytkownika używającego programu C. Nie chcę używać tablicy typu,

char names[50];

Ponieważ jeśli użytkownik poda łańcuch o długości 10, to Pozostałe spacje zostaną zmarnowane.

Jeśli użyję wskaźnika znakowego,

char *names;

Następnie muszę przeznaczyć na to pamięć w taki sposób,

names = (char *)malloc(20 * sizeof(char));

Również w tym przypadku istnieje możliwość utraty pamięci.

Więc potrzebuję dynamicznie przydzielać pamięć Dla ciągu znaków, który jest dokładnie taki sam jak długość sznurka.

Załóżmy,

Jeśli dane wejściowe użytkownika to "stackoverflow", to przydzielona pamięć powinna być 14 (tzn. Długość łańcucha = 13 i 1 dodatkowa spacja dla '\0').

Jak mógłbym to osiągnąć?

Author: chqrlie, 2011-11-17

9 answers

Czytaj po jednym znaku na raz (używając getc(stdin)) i rozwijaj ciąg znaków (realloc) w miarę upływu czasu.

Oto funkcja, którą napisałem jakiś czas temu. Uwaga jest przeznaczony tylko do wprowadzania tekstu.

char *getln()
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
            ch = 0;

        /* Check if we need to expand. */
        if (size <= index) {
            size += CHUNK;
            tmp = realloc(line, size);
            if (!tmp) {
                free(line);
                line = NULL;
                break;
            }
            line = tmp;
        }

        /* Actually store the thing. */
        line[index++] = ch;
    }

    return line;
}
 39
Author: cnicutar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 08:20:55

Możesz mieć tablicę, która zaczyna się od 10 elementów. Odczyt wejściowy znak po znaku. Jeśli to się skończy, przydziel kolejne 5. Nie najlepsze, ale potem możesz zwolnić inne miejsce później.

 6
Author: tekknolagi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 08:21:03

Jeśli chcesz oszczędzić pamięć, przeczytaj znak po znaku i realloc za każdym razem. Wydajność umrze, ale oszczędzicie to 10 bajtów.

Innym dobrym rozwiązaniem jest odczyt w funkcji (używając zmiennej lokalnej), a następnie kopiowanie. Więc duży bufor będzie miał zasięg funkcji.

 5
Author: BigMike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 08:24:13

Możesz również użyć wyrażenia regularnego, na przykład następującego fragmentu kodu:

char *names
scanf("%m[^\n]", &names)

Pobierze całą linię ze standardowego wejścia, przydzielając dynamicznie ilość zajmowanego miejsca. Po tym, oczywiście, musisz uwolnić names.

 5
Author: Jytug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-31 11:06:01

Poniżej znajduje się kod do tworzenia dynamicznego ciągu znaków:

void main()
{
  char *str, c;
  int i = 0, j = 1;

  str = (char*)malloc(sizeof(char));

  printf("Enter String : ");

  while (c != '\n') {
    // read the input from keyboard standard input
    c = getc(stdin);

    // re-allocate (resize) memory for character read to be stored
    str = (char*)realloc(str, j * sizeof(char));

    // store read character by making pointer point to c
    str[i] = c;

    i++;
    j++;
  }

  str[i] = '\0'; // at the end append null character to mark end of string

  printf("\nThe entered string is : %s", str);

  free(str); // important step the pointer declared must be made free
}
 1
Author: Kunal Wadhwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-05 12:20:04
char* load_string()
 {

char* string = (char*) malloc(sizeof(char));
*string = '\0';

int key;
int sizer = 2;

char sup[2] = {'\0'};

while( (key = getc(stdin)) != '\n')
{
    string = realloc(string,sizer * sizeof(char));
    sup[0] = (char) key;
    strcat(string,sup);
    sizer++

}
return string;

}

int main()
  {
char* str;
str = load_string();

return 0;
  }
 1
Author: Shihan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 18:09:53

Jest to bardziej proste podejście

char *in_str;
in_str=(char *)malloc(512000 * sizeof(char));
enter code herescanf("\n%[^\n]",in_str);
 0
Author: Kiran JD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-17 08:57:32

Oto fragment, który napisałem, który wykonuje tę samą funkcjonalność.

Ten kod jest podobny do tego napisanego przez Kunal Wadhwa .

char *dynamicCharString()
{
char *str, c;
int i;
str = (char*)malloc(1*sizeof(char));

while(c = getc(stdin),c!='\n')
{
    str[i] = c;
    i++;
    realloc(str,i*sizeof(char));
}
str[i] = '\0';
return str;
}
 0
Author: user8311083,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-31 11:31:53

Najpierw zdefiniuj nową funkcję do odczytu danych wejściowych (zgodnie ze strukturą danych wejściowych) i zapisz łańcuch znaków, co oznacza pamięć w stosie. Ustaw długość łańcucha, aby wystarczyła do wprowadzenia.

Po drugie, użyj strlen, aby zmierzyć dokładną długość łańcucha przechowywanego wcześniej i malloc, aby przydzielić pamięć w stercie, której długość jest określona przez strlen. Kod jest pokazany poniżej.

int strLength = strlen(strInStack);
if (strLength == 0) {
    printf("\"strInStack\" is empty.\n");
}
else {
    char *strInHeap = (char *)malloc((strLength+1) * sizeof(char));
    strcpy(strInHeap, strInStack);
}
return strInHeap;

Na koniec skopiuj wartość strInStack do strInHeap używając strcpy i zwróć wskaźnik do strInHeap. strInStack zostanie zwolnione automatycznie, ponieważ kończy się tylko w tej podfunkcji.

 0
Author: Edward Xu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-05 13:35:23