2017-05-01 7 views
0

Je voudrais savoir s'il est possible d'allouer dynamiquement de la mémoire quand/avant d'utiliser un scanf. Cela signifierait qu'il n'est pas nécessaire de donner une taille de char * lors de l'initialisation. Au lieu de cela, la quantité de mémoire nécessaire serait allouée en fonction de la taille de la chaîne d'entrée (ce qui signifie: après avoir entré l'entrée).C: allocation dynamique lors d'un scanf

Actuellement je ne trouve pas d'autre solution que d'allouer une quantité de mémoire spécifique avant d'avoir l'entrée, donc avant de connaître la taille de l'entrée:

char str[10]; 
scanf("%s", str); 

Et je sais que ce n'est pas sûr: si l'entrée est plus long que 10 caractères, le programme écrira sur la mémoire non allouée, ce qui peut causer des erreurs de segmentation ou des choses comme ça.

+1

Qu'est-ce qui vous empêche d'écrire une fonction qui fait exactement ce que vous voulez? (De plus, votre déclaration pour 'str' crée un tableau de dix pointeurs, ce qui n'est probablement pas ce que vous vouliez. –

+1

Ne pas utiliser 'scanf' pour la saisie de l'utilisateur en premier lieu. – melpomene

+0

@DavidSchwartz Mes compétences ne sont pas assez élevées pour cela. J'ai essayé de lire les bibliothèques mais j'ai compris à peu près rien de ce qui y était écrit (sauf les commentaires :)) – nounoursnoir

Répondre

0

Utilisez la fonction getline,

ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

ExempleTry Online

int main(void) 
{ 
    char * line; 
    size_t size; 

    if(getline(&line, &size, stdin) != (-1)) 
    { 
     printf("You entered: %s",line); 
    } 

    return 0; 
} 
+0

Votre 'readLineString' est dangereux et utilise un tampon statique de longueur 512. Ce n'est pas dynamique en aucune façon. (Il fait ensuite une version manuelle de 'strdup' mais à quoi cela sert-il?) – melpomene

+0

@melpomene Je suis d'accord, comment liriez-vous les entrées avec une longueur dynamique? –

+1

['getline'] (http://man7.org/linux/man-pages/man3/getdelim.3.html) si je me sens paresseux et qu'il ne doit pas être portable. – melpomene

1

Comme il est indiqué dans les commentaires,% m Je crois permet de résoudre votre requête

Une autre approche sera de limiter l'entrée à l'octet numéro que vous connaissez w Vous avez alloué à votre variable avec par exemple% 10s n'indiquera que 10 caractères Ensuite, en réaffectant votre variable d'entrée pour faire de la place pour plus de caractères à entrer dans le prochain appel à scanf, vous devez passer str & str [10] dans next appel afin qu'il ne remplace pas l'entrée précédente

1

L'entrée utilisateur de stdin est difficile.


de

OP « si l'entrée est plus de 10 caractères, le programme écrire sur la mémoire non alloué » est un problème hors de 1. Si l'entrée est plus longue que , le programme écrira dans la mémoire non allouée.

char str[10]; 
scanf("%s", str); 

getline();, comme le suggère cette good answer est la solution typique.

Je rejette l'idée de "allocation dynamique pendant un scanf" comme un bon objectif de conception. Un programme qui permet une saisie sans fin est sujette à l'abus. Cela permet à l'utilisateur de surcharger les ressources du système. Un bon code valide l'entrée en premier. Plus besoin de Heartbleed.

Je recommande Au lieu que l'entrée stdin est évaluée pour une longueur raisonnable d'entrée, que ce soit 10, 1000, ou un million et un tampon de 2x ou plus est fourni.

#define MAX_EXPECTED_SIZE 100 
char buf[MAX_EXPECTED_SIZE * 2]; 
if (fgets(buf, sizeof buf, stdin)) { 
    size_t len = strlen(buf); 
    if (len + 1 == sizeof buf && buf[len] != '\n') { 
    // Assume hostile input and act accordingly. Possibly exiting with message. 
    // or consume rest of line 
    int ch; 
    while ((ch = getchar()) != '\n' && ch != EOF); 

    return ERROR_LONG_LINE 
    } 

    // Use buf[] 
} 

code peut affecter la mémoire de la bonne taille est ensuite une copie de buf doit être maintenue.