¿Cómo asignar dinámicamente espacio de memoria para una cadena y obtener esa cadena del usuario?


Quiero leer la entrada del usuario usando el programa C. No quiero usar array como,

char names[50];

Porque si el usuario da cadena de longitud 10, entonces los espacios restantes se desperdician.

Si utilizo puntero de carácter como,

char *names;

Entonces necesito asignar memoria para eso de tal manera de,

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

En este caso también, hay una posibilidad de desperdicio de memoria.

Por lo tanto, lo que necesito es asignar dinámicamente la memoria para una cadena que es exactamente igual que el longitud de la cuerda.

Supongamos,

Si la entrada del usuario es "stackoverflow", entonces la memoria asignada debe ser de 14 (es decir, Longitud de la cadena = 13 y 1 espacio adicional para '\0').

¿Cómo podría lograr esto?

Author: chqrlie, 2011-11-17

9 answers

Lea un carácter a la vez (usando getc(stdin)) y haga crecer la cadena (realloc) a medida que avanza.

Aquí hay una función que escribí hace algún tiempo. Tenga en cuenta que está destinado solo para la entrada de texto.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 08:20:55

Usted podría tener una matriz que comienza con 10 elementos. Leer entrada carácter por carácter. Si se pasa, reasignar otros 5 más. No es el mejor, pero luego puedes liberar el otro espacio más tarde.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 08:21:03

Si usted debe ahorrar memoria, lea char por char y realloc cada vez. El rendimiento morirá, pero ahorrarás 10 bytes.

Otra buena compensación es leer en una función (usando una variable local) y luego copiar. Así que el búfer grande será función de ámbito.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 08:24:13

También puede usar una expresión regular, por ejemplo, el siguiente fragmento de código:

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

Obtendrá toda la línea de stdin, asignando dinámicamente la cantidad de espacio que toma. Después de eso, por supuesto, tienes que liberar 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-31 11:06:01

A continuación se muestra el código para crear una cadena dinámica:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-04 18:09:53

Este es un enfoque más simple

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-17 08:57:32

Aquí hay un fragmento que escribí que realiza la misma funcionalidad.

Este código es similar al escrito por 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-31 11:31:53

Primero, defina una nueva función para leer la entrada (de acuerdo con la estructura de su entrada) y almacene la cadena, lo que significa la memoria en la pila utilizada. Establezca la longitud de la cadena para que sea suficiente para su entrada.

En segundo lugar, use strlen para medir la longitud exacta utilizada de la cadena almacenada antes, y malloc para asignar memoria en montón, cuya longitud está definida por strlen. El código se muestra a continuación.

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;

Finalmente, copie el valor de strInStack a strInHeap usando strcpy, y devuelva el puntero a strInHeap. El strInStack se liberará automáticamente porque solo sale en esta sub-función.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-05 13:35:23