j'ai besoin de faire une copie d'une chaîne de caractère, puis de la remplacer par des "*" pour masquer les caractère en question
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//demande d'allocation de mémoire
int i = 0 ;
char motSecret[] = "MARRON";
char mot = malloc(strlen(motSecret)+2 * sizeof(char));
strcpy(mot, motSecret);
//char mot[] = "MARRON";
for ( i = 0 ; i < strlen(motSecret) ; i++)
{
mot[i] = "*";
}
printf("le mot %s ", mot);
return 0;
}
ce code ne fonctionne pas. j'obtien le journal d'erreur suivant :
||=== Build: Debug in test3 (compiler: GNU GCC Compiler) ===|
C:\Users\admin\prog\c\projets\test3\main.c||In function 'main':|
C:\Users\admin\prog\c\projets\test3\main.c|10|warning: initialization makes integer from pointer without a cast [-Wint-conversion]|
C:\Users\admin\prog\c\projets\test3\main.c|11|warning: passing argument 1 of 'strcpy' makes pointer from integer without a cast [-Wint-conversion]|
C:\Program Files (x86)\CodeBlocks\MinGW\include\string.h|45|note: expected 'char *' but argument is of type 'char'|
C:\Users\admin\prog\c\projets\test3\main.c|15|error: subscripted value is neither array nor pointer nor vector|
C:\Users\admin\prog\c\projets\test3\main.c|19|warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat=]|
||=== Build failed: 1 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
si je commente les lignes 10 et 11, et dé commente la ligne 12, mon problème disparaît.
pourquoi la copie de ma chaîne ne veut pas fonctionner de la même manière qu'une chaîne créé simplement?
une autre tout petit problème, ma ligne 15 ne remplace pas les caractère par des * mais par des $, je comprend pas bien pourquoi mais c'est pas très grave
Edit: petit précision : j'ai ajouté 2 à sizeof(char) afin d'être sûr que la chaîne a serai assez longue... Sachant qu'un char fait 1octet et que le strlen(motSecret) devrais je pense avoir compté le \0 de fin de chaîne
Ligne 10, mot est déclaré comme pointeur sur char, il est initialisé avec l'adresse d'un bloc mémoire de la taille de 6 caractères (char).
Ligne 11, strcpy ne demande pas un char mais deux pointeurs sur char, les paramètres sont donc correctes.
Il y a un tout de même un petit problème, c'est que le tableau motsecret à une taille de 7 char et tu le copie dans un tableau de 6 char. (il ne faut pas oublier que les chaîne de caractères se terminent par le caractère '\0'.
C'est pour ça qu'on dit que le nom d'un tableau se dégrade (decays) en adresse (de son premier élément) lors d'une évaluation. Mais sizeof () est un opérateur du langage, qui n'évalue pas son argument.
- Edité par michelbillaud 18 septembre 2019 à 12:09:10
motSecret c'est lui le tableau : il contient les caractères 'M', 'A', 'R', 'R', 'O', 'N' et '\0'. Mais toute utilisation le verra comme un pointeur sur le premier des caractères donc pointe sur le caractère 'M'. motSecret[0] contient le caractère 'M'. &motSecret est l'adresse d'un tableau, c'est donc l'adresse de 'M' 'A' 'R' 'R' 'O' 'N' '\0'. &motSecret[0] est l'adresse du caractère 'M'.
Donc les valeurs motSecret et &motSecret et &motSecret[0] sont bien égales (mais elles n'ont pas le même type la première et la dernières sont des char*, la seconde est un char (*)[7].)
mot contient une adresse mémoire : oui. Mais pour le moment cette adresse est totalement aléatoire (pointe donc n'importe où). *mot contient UN UNIQUE caractère celui qui est désigné par le pointeur mot. A ne surtout pas utiliser tant que mot n'a pas été initialisé correctement.
Bon. Merci bien à tous, ça me paraît clair là façon dont vous me l'expliquez, je m'y perdai à l'utilisation. On verra à l'avenir je vais faire mes tests sa m'aidera a comprendre et à retenir, merci bien
Normal d'avoir du mal à comprendre : l'idée - lors de la conception de C - était tordue : au départ, un simple pointeur sur une zone contenant les éléments (héritage de B, je crois). Puis une constante représentant l'adresse de cette zone.
je ne suis malheureusement pas assez à l'aise avec l'anglais pour tout comprendre. mais je vois en tout cas que cette histoire ne date pas d'hier mais là sont les racines, et elles restent apparemment fortement encré dans le langage, mais t’inquiète, je vais tout comprendre et m'y faire
ce que je trouve tout de même compliqué, moi qui vien de la programmation web (principalement PHP, autodidacte mais ya déja quelques année) c'est que cette fois, c'est pas très facile de demander a php de quel type est tel variable, que contient-t-elle ? une lettre ou une chaîne? de type nombre ou bien une chaîne de caractère? bon, ya aussi la notion que tout est nombre... avec ASCII, je sais, mais voilà
bref, c'est très différent, néanmoins je retrouve pas mal de choses et c'est enrichissant plus bas niveau donc on comprend des concept informatique, notamment cette table ASCII que je ne connaissais pas du coté programmation. et puis ces histoire d'adresse mémoire.. j'imagine qu'il y en aura peut être d'autres
ton lien je le garde de coté et me penche dessus quand même à essayer de comprendre, sa me semble très intéressant des accident de syntaxe qui ont aboutie a des complexifications du langage j'ai vu par exemple... LOL
Personnellement je trouve que, surtout si on n'est pas super à l'aise avec les pointeurs, mieux vaut définir des chaînes de caractères de longueur fixe (*). Il y a plein de situation où les chaînes de caractères ont naturellement une longueur maximale. Pour le jeu du pendu, par exemple, on peut se limiter à 26 caractères (taille 27 avec le zéro terminal) puisque le mot le plus long, « intergouvernementalisation », en fait 26. Si c'est pour mémoriser des noms de joueurs dont on affichera le score, il suffit de spécifier une taille limite (tout le monde fait ça, non ?).
-----
(*) Je parle de la définition, pas de la déclaration d'un paramètre de fonction.
Pour le jeu du pendu, par exemple, on peut se limiter à 26 caractères (taille 27 avec le zéro terminal) puisque le mot le plus long, « intergouvernementalisation », en fait 26.
_____
C'est sans compter le chlorure d’aminométhylpyrimidinylhydroxyéthylméthythiazolium (49 lettres).
mon objectif personnellement, c'est quand même de comprendre les pointeur ce serai dommage de coder en C et de chercher a contourner une fonctionnalité du langage, et je pense avoir plutôt bien compris on verra si j'ai d'autres souci comme celui ci je reviendrai d'abord lire l'aide que j'ai eu ici, je pense pouvoir résoudre mes souci de pointeur seul à présent
C'est pour ça qu'on dit que le nom d'un tableau se dégrade (decays) en adresse (de son premier élément) lors d'une évaluation. Mais sizeof () est un opérateur du langage, qui n'évalue pas son argument.
L'opérateur sizeof n'évalue pas son opérande, sauf exception bien sûr. ;-) C11 6.5.3.4§1 The sizeof operator yields the size (in bytes) of its operand [...] The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant. C11 6.7.6.2§5 : Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.
A part ça, il existe un cas simple où l'identificateur d'un tableau ne se comporte pas du tout comme celui d'un pointeur.
char t[6] = "hello";
char *p;
char q[6];
p = t; // OK
q = t: // pas OK
C'est le and is not an lvalue de la règle complète de la norme qui fait ici la différence: C11 6.3.2.1§3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
- Edité par Marc Mongenet 18 septembre 2019 à 23:53:41
Pour le second point, c'est pour le cas sizeof (t[ f(i) ] ) ?
EDIT:
Dans le draft C18, https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf
<< 6.5.3.4. note 2
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant
>>
Je suppose que "évaluer un VLA", dans le sens du standard, se limite à regarder son type et sa taille, qui est dynamique ?
- Pour l'utilisation des pointeurs : on n'en est plus à l'époque où on écrivait du code C de telle ou telle façon en sachant ce que le compilateur en ferait. On peut manipuler un tableau avec des indices, et si on regarde le code généré, constater qu'il a transformé ça en manipulation de registres travaillant sur des adresses. Et que ça donne exactement le même code avec des pointeurs Donc privilégier la simplicité d'écriture. Si on veut se la péter optimisation, commencer par compiler avec les bonnes options :-)
- Edité par michelbillaud 19 septembre 2019 à 9:31:58
l'éventuelle évalutation de x++ n'est pas spécifiée (cela dit, gcc et clang n'évaluent pas).
En outre, ça me semble contradictoire avec C11 6.5.3.4§1/C18 6.5.3.4§2 qui ne laisse pas de place à un comportement non spécifié.
copie de chaine de carractere avec strcpy()
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.