web-dev-qa-db-fra.com

Comment allouer dynamiquement de l'espace mémoire pour une chaîne et obtenir cette chaîne de l'utilisateur?

Je veux lire les entrées de l'utilisateur en utilisant le programme C. Je ne veux pas utiliser un tableau comme,

char names[50];

parce que si l'utilisateur donne une chaîne de longueur 10, les espaces restants sont perdus.

Si j'utilise un pointeur de caractère comme,

char *names;

alors j'ai besoin d'allouer de la mémoire pour cela de telle manière,

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

Dans ce cas également, il existe une possibilité de perte de mémoire.

Donc, ce dont j'ai besoin, c'est d'allouer dynamiquement de la mémoire pour une chaîne qui est exactement identique à la longueur de la chaîne.

Assumons,

Si la saisie de l'utilisateur est "stackoverflow", la mémoire allouée doit être de 14 (c'est-à-dire longueur de la chaîne = 13 et 1 espace supplémentaire pour '\ 0').

Comment pourrais-je y parvenir?

41
Dinesh

Lisez un caractère à la fois (en utilisant getc(stdin)) et développez la chaîne (realloc) au fur et à mesure.

Voici une fonction que j'ai écrite il y a quelque temps. Notez qu'il est uniquement destiné à la saisie de texte.

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;
}
40
cnicutar

Vous pourriez avoir un tableau qui commence avec 10 éléments. Lire caractère par caractère. Si tout se passe bien, en réaffecter 5 autres. Pas le meilleur, mais alors vous pouvez libérer l'autre espace plus tard.

6
tekknolagi

Vous pouvez également utiliser une expression régulière, par exemple le code suivant:

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

obtiendra toute la ligne de stdin, en allouant dynamiquement la quantité d’espace nécessaire. Après cela, bien sûr, vous devez libérer names.

5
Jytug

Si vous devez économiser de la mémoire, lisez char par char et realloc à chaque fois. Les performances vont mourir, mais vous épargnerez ces 10 octets. 

Un autre bon compromis est de lire une fonction (en utilisant une variable locale) puis de la copier. Donc, le gros tampon sera fonction étendue.

5
BigMike

Voici le code pour créer une chaîne dynamique: 

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
Kunal Wadhwa
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
Shihan

C’est un extrait de fonction que j’ai écrit pour analyser l’entrée utilisateur pour rechercher une chaîne, puis la stocker dans un tableau de la même taille que l’entrée utilisateur. Notez que j initialise j à la valeur 2 pour pouvoir stocker le caractère '\ 0'.

char* dynamicstring() {
    char *str = NULL;
    int i = 0, j = 2, c;
    str = (char*)malloc(sizeof(char));
    //error checking
    if (str == NULL) {
        printf("Error allocating memory\n");
        exit(EXIT_FAILURE);
    }

    while((c = getc(stdin)) && c != '\n')
    {
        str[i] = c;
        str = realloc(str,j*sizeof(char));
        //error checking
        if (str == NULL) {
            printf("Error allocating memory\n");
            free(str);
            exit(EXIT_FAILURE);
        }

        i++;
        j++;
    }
    str[i] = '\0';
    return str;
}

Dans main (), vous pouvez déclarer une autre variable char * pour stocker la valeur de retour de dynamicstring (), puis libérer cette variable char * lorsque vous avez terminé de l'utiliser.

0
André Fael

Voici un extrait que j'ai écrit qui exécute la même fonctionnalité.

Ce code est similaire à celui écrit par 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
user8311083

Tout d’abord, définissez une nouvelle fonction pour lire l’entrée (en fonction de la structure de votre entrée) et stockez la chaîne, c’est-à-dire la mémoire utilisée dans la pile. Définissez une longueur de chaîne suffisante pour votre entrée. 

Deuxièmement, utilisez strlen pour mesurer la longueur exacte utilisée de la chaîne stockée auparavant et malloc pour allouer de la mémoire dans le segment de mémoire, dont la longueur est définie par strlen. Le code est indiqué ci-dessous.

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;

Enfin, copiez la valeur de strInStack dans strInHeap à l'aide de strcpy et renvoyez le pointeur à strInHeap. La strInStack sera automatiquement libérée car elle n'existe que dans cette sous-fonction.

0
Edward Xu

C'est une approche plus simple

char *in_str;
in_str=(char *)malloc(512000 * sizeof(char));
scanf("\n%[^\n]",in_str);
0
Kiran JD