Je suis assez compétent dans quelques langues de script, mais je me forgie enfin à apprendre cru C. Je joue juste avec des trucs de base (I / O en ce moment). Comment allouer la mémoire de la mémoire de tas puis-je enregistrer une chaîne dans la mémoire allouée, puis la cracher de côté? C'est ce que j'ai en ce moment, comment puis-je le faire fonctionner correctement?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *toParseStr = (char*)malloc(10);
scanf("Enter a string",&toParseStr);
printf("%s",toParseStr);
return 0;
}
5 Réponses :
Vous n'avez pas besoin d'un Appelez également et code> avant toparsestr code> dans scanf code> car il s'agit déjà d'un pointeur p>
gratuit (toparsestr) code> après p>
Selon le système de BBALL, il peut être nécessaire de mettre un "\ n" dans ce printf pour des choses à apparaître correctement. De plus, 10 caractères sont une chaîne vraiment courte.
Bien que vrai, ce n'est pas vraiment la source d'un problème (le & code> est inutile mais inoffensif dans ce cas).
@Jerry, il est inoffensif car le spécificateur de format ne spécifie pas des arguments, mais une fois qu'il l'a correctement réparé, il faut avoir un% comme dans votre réponse, il va causer un segfault
@Michael: Oui, mais il ne pointe qu'un problème relativement mineur où il y a beaucoup d'autres qui sont beaucoup plus graves. En particulier, changer ce point particulier (tout en laissant le reste du code inchangé) ne fournira aucune amélioration (visible) de son comportement.
Vous devez donner modifier: dans ce cas, scanf code> un format de conversion afin qu'il sait que vous souhaitez lire une chaîne - à l'heure actuelle, vous venez d'afficher les ordures qui se trouvaient dans la mémoire que vous avez allouée. Plutôt que d'essayer de décrire tous les problèmes, voici quelques codes qui devraient au moins être proches de travailler: gratuit code> 't faire toute différence réelle, mais comme d'autres l'ont souligné, il est em> une bonne habitude de cultiver néanmoins. p> p>
Contrairement à la conviction de certaines personnes, rinçage stdout code> est pas i> nécessaire pour que l'invite apparaisse avant que l'entrée soit lue, à moins que la mise en œuvre ne soit bien et véritablement cassée. Pour ceux qui s'en soucient vraiment, voir § 7.19.3. stdout code> ne peut être complètement tamponné que si elle peut être déterminée pas i> pour faire référence à un périphérique interactif.
vous vous trompez. stdout code> peut toujours être tamponné de ligne B> ce qui signifie que rien ne s'affiche jusqu'à ce qu'une nouvelle ligne soit imprimée. POSIX recommande que les implémentations affleurant stdout code> et d'autres flux tamponnés de la ligne de ce type à la lecture, mais c'est une performance significative à numériser la liste des fichiers ouverts pour les flux tamponnés de ligne (en particulier avec des filets et des filets) et une implémentation Peut choisir de ne pas le faire pour de très bonnes raisons. Pour autant que je sache, l'ISO C rend peu / aucune exigence sur la sémantique tampon. Donc, vous Devriez B> Flush!
int main(int argc, char *argv[])
{
char *toParseStr;
const int n = 10;
printf("Garbage: %p\n",toParseStr);
AllocateString(&toParseStr,n);
printf("Address of the first element of a contiguous array of %d bytes: %p\n",n,toParseStr);
printf("Enter string here: ");
scanf("%s",toParseStr);
printf("%s\n",toParseStr);
free(toParseStr);
return 0;
}
+1 pour libérer même dans un petit programme. Me rappelle que "petites gouttes font un océan". ;-)
Vous devez appeler fflush (stdout); code> entre imprimer l'invite et appeler scanf code>. La plupart des implémentations feront cela pour que vous puissiez être poli, mais cela n'est pas mandaté.
Premièrement, les erreurs qui gardaient votre programme de travail: J'ai également supprimé la distribution inutile de votre appel à Une amélioration nécessaire que votre programme a encore besoin d'utiliser scanf (3) code> prend une chaîne de format, comme printf (3) code>, pas une chaîne à Imprimer pour l'utilisateur. Deuxièmement, vous passez l'adresse du pointeur toparsestr code>, plutôt que le pointeur toparsestr code>. Malloc ( 3) code>. P> scanf (3) code> 'S A code> option pour allouer la mémoire pour Vous - de sorte que certains Joker mettent dix caractères dans votre chaîne ne commencent pas à piétiner la mémoire non liée. (Oui, C laissera quelqu'un qui écrase presque tout l'espace d'adressage avec ce programme, comme écrit. Frame de sécurité géante. :) p> #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *toParseStr = malloc(10);
printf("Enter a short string: ");
scanf("%s",toParseStr);
printf("%s\n",toParseStr);
return 0;
}
scanf code> n'a pas d'option code> code>. Ceci est une extension GNU qui n'est pas seulement non standard mais conflits b> avec ISO C (% A code> est l'un des spécificateurs de lire un numéro de point flottant!). Il devrait être évité absolument.
Merci; Je n'étais pas au courant de cette vulgarisation avec Iso C.
Utilisation de L'exemple classique est que j'entre la chaîne "Cette chaîne est de la manière de plus de 10 caractères" dans votre programme, le chaos s'ensuivra, les chats et les chiens vont commencer à dormir ensemble et une singularité nue peut Bien apparaître et consommez la Terre (la plupart des gens n'adaptent que «comportement indéfini», mais je pense que ma description est meilleure). p> Je décourage activement l'utilisation de fonctions qui ne peuvent pas fournir une protection. Je vous exhorterais (surtout comme un nouveau venu à c) d'utiliser Une fois que vous avez une ligne, vous pouvez ensuite appeler J'utiliserais: P> scanf () code> (ou FSCANF () code> sur les données que vous ne contrôlez pas) avec un spécificateur "% s" standard est un moyen quasi certain d'obtenir vous-même dans des ennuis avec des débordements de tampon. fgets () code> pour lire votre entrée puisque vous pouvez contrôler beaucoup plus facilement les débordements de mémoire tampon et il est plus adapté à une entrée de ligne simple que scanf () code>. p> sscanf () code> sur le contenu de votre coeur qui, au fait, vous. N'ayez pas besoin de faire dans ce cas particulier puisque vous obtenez seulement une chaîne brute de toute façon. P> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSZ 10
int main(int argc, char *argv[]) {
char *toParseStr = malloc(BUFFSZ+2);
if (toParseStr == NULL) {
printf ("Could not allocate memory!\n");
return 1;
}
printf ("Enter a string: ");
if (fgets (toParseStr, BUFFSZ+2, stdin) == NULL) {
printf ("\nGot end of file!\n");
return 1;
}
printf("Your string was: %s",toParseStr);
if (toParseStr[strlen (toParseStr) - 1] != '\n') {
printf ("\nIn addition, your string was too long!\n");
}
free (toParseStr);
return 0;
}
+1, bien que j'ajouterais que lorsque fgets code> a des avantages, scanf code> et fscanf code> do i> disposent de empêcher également les débordements de la mémoire tampon.
C'est un bon point, @jerry, bien que j'ai rarement vu que les gens utilisent le spécificateur de largeur avec "% s" :-) puisque la majeure partie de mon code d'E / S console a tendance à avoir une entrée basée sur la ligne,% s est inappropriée pour obtenir l'espace blanc. Cependant, comme votre réponse est réellement juste dans ce cas, +1 pour vous.
Une autre possibilité intéressante est scanf ("% 9 [^ \ n]", votre_string); code> - Entrée de chaîne orientée ligne de scanf code>, pour tout ce qui vaut.
@Jerry Coffin: scanf code> et FSCANF code> est généralement difficile à utiliser pour d'autres raisons. OMI c'est mieux pour quiconque n'est pas un expert C pour les éviter complètement. Quoi qu'il en soit, +1 pour être la seule réponse qui met en garde sur le débordement potentiel de la mémoire tampon.
@Jerry: +1 pour le Nice % [ code> suggestion. Donc, peu de gens savent qu'il existe. Il est en fait utile pour la mise en œuvre d'une version entièrement portable de GNU getline code> / getdelim code> sur la nature ISO C. et si vous utilisez % n code> après cela, vous Peut même obtenir le nombre d'octets de lecture, au cas où la lecture des données contient des octets nuls incorporés.
Vous n'avez pas besoin de lancer le type de retour de
MALLOC (3) code> dans ISO C avec code> inclus. Il convient de souligner que vous devriez probablement utiliser la pile ici.