6
votes

Char * p, et scanf

J'ai essayé de rechercher une raison pour laquelle le code suivant échoue et que je ne pouvais en trouver un. Alors s'il vous plaît, excusez mon ignorance et laissez-moi savoir ce qui se passe ici. XXX

Aussi loin que j'ai compris, j'ai créé un pointeur P à une zone contiguë dans la mémoire de la taille 29 + 1 ( pour le \ 0). Pourquoi ne puis-je pas utiliser Scanf pour changer le contenu de cela?

P.s s'il vous plaît corrigez-moi si j'ai dit quelque chose de mal à propos de Char *.


0 commentaires

4 Réponses :


-2
votes

scanf () analyse des données saisies dans STDIN (normalement, le clavier). Je pense que vous voulez sscanf () .

Cependant, le but de scanf () est de faire partie d'une chaîne avec des séquences d'échappement prédéfinies, que votre chaîne de test n'a pas. Donc cela en fait un peu pas clairement ce que vous essayez de faire.

Notez que sscanf () prend un argument supplémentaire en tant que premier argument, qui spécifie la chaîne étant analysée.


2 commentaires

Je pense que la question est de savoir pourquoi Scanf ne fonctionne pas. Réponse de Muggen explique que


Je vois plusieurs choses mal au code de l'OP, il est donc un peu difficile de savoir exactement ce qu'il essayait d'accomplir.



6
votes

p points à un littéral constant, qui peut en fait résider dans une zone de mémoire en lecture seule (en fonction de la mise en œuvre). En tout état de cause, essayant d'écraser c'est comportement indéfini . C'est à dire. Cela pourrait ne rien end, ni un accident immédiat, ou une corruption de mémoire cachée qui provoque des problèmes mystérieux plus tard. ne fais jamais cela .


6 commentaires

@Peter, je n'ai pas non plus de bownvoit mais ne voyez pas une raison sur laquelle -1 donc i +1


Je viens de supprimer mon vote en direct. J'ai vu une autre explication plus tôt. Je suppose que vous avez édité cela.


Notez que modifier la déclaration à Char P [] = "Bonjour, cela ne va pas fonctionner"; fait créer un tampon modifiable que l'OP peut utiliser.


@Muggen, très gentil de votre part :-) Maintenant que le bowvote est supprimé, n'hésitez pas à supprimer votre uvot de compensation, car votre réponse est bien meilleure (elle mérite le haut de la page +1 de moi)


@ user210504, oui je modifie ma réponse pour l'améliorer. Je crois que je n'ai pas changé le sens de celui-ci, mais s'il vous plaît vérifier l'historique de modification et laissez-moi savoir si j'ai écrit quelque chose d'incorrect dans une version antérieure précédente. @John, merci. Il est toujours bon de polir mes compétences de rouille C :-)


@Peter, je quitterai le +1 pour mentionner que le comportement des littéraux de chaîne est défini la mise en œuvre.



14
votes
char * p = malloc(sizeof(char) * 128);
scanf("%126s",s);

14 commentaires

Si c'est le cas, alors comment puis-je lire une chaîne avec une longueur inconnue?


@Adel, fait une petite modification, look la dernière ligne


C'est bien, merci! Mais que faire si je ne peux pas prédire la longueur de la chaîne à numériser?


@Adel, vous ne pouvez pas lire une ligne avec une longueur inconnue, mais vous pouvez utiliser un très gros tampon (par exemple, un tampon [1024] ) mais assurez-vous toujours que vous ne débordez pas ce gros tampon


@Muggen: vient de vérifier quelque chose maintenant char * p = "hi"; Ensuite, j'ai écrit p = "lol" et le code a fonctionné simplement bien, comment a-t-il édité la chaîne si elle était réadonnée? Merci


@Adel, la chaîne n'est pas en lecture seule. Juste parce que cela ne plante pas, cela ne signifie pas que c'est vrai. C'est ce que comportement non défini signifie. Tout peut arriver :)


Pour ajouter, déclarer un pointeur non-const char * p = "abc"; à un littéral à chaîne est une mauvaise pratique. Lorsque vous utilisez des littéraux à chaîne immuable, déclarez-les comme const char * . Ensuite, le compilateur vous informera, si vous passez accidentellement ce pointeur à une fonction qui s'attend à un argument de pointeur non constitutionnel. Recherche de "Const Ciditness" à lire sur le concept et pourquoi il est important.


@Muggen: Oh bien! Merci !! Cela me fait me demander cependant, si char * p donne à l'UB chaque fois que nous essayons de jouer avec cela, pourquoi l'utiliserions-nous jamais?


@Adel, char * p ne donne pas ub. C'est un pointeur, qui pointe vers un emplacement que nous pouvons utiliser pour écrire. Si nous utilisons cet emplacement de mauvaise manière, il est ub.


@Adel, en faisant p = "lol" Vous n'avez pas modifié le littéral de chaîne pointé par p . Vous avez changé le pointeur p pour pointer vers une autre chaîne littéral.


@Mizo, qui ferait que quelqu'un se demande si dans de tels cas, il devrait utiliser const char * const p = "ceci est une chaîne"; : p


@Andel, également si vous vouliez modifier ce que p vous devez utiliser strcpy () qui peut encore provoquer ub si vous dépassez les limites autorisées . Et en supposant que p est un pointeur valide à utiliser.


@Muggen, en effet, s'ils souhaitent interdire les modifications à la valeur de l'adresse du pointeur. Ce n'est pas obligatoire, mais comme ayant une branche Char * MODIFIANT à un littéral à chaîne est un non-non dans mon livre.


est 'scanf ("% 126s", s)' non? en fait 'char p [max_size]; Fgets (p, max_size, stdin) 'est un meilleur choix.



0
votes

Il se bloque car la mémoire n'a pas été allouée pour p. Allouer la mémoire pour P et cela devrait être correct. Ce que vous avez est une zone de mémoire constante pointant par p. Lorsque vous essayez d'écrire quelque chose dans ce segment de données, l'environnement d'exécution augmentera un piège qui conduira à un accident.

J'espère que cela répond à votre question


0 commentaires