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?
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;
}
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.
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
.
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.
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
}
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;
}
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.
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;
}
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.
C'est une approche plus simple
char *in_str;
in_str=(char *)malloc(512000 * sizeof(char));
scanf("\n%[^\n]",in_str);