Language C, "connot convert int to cons char& [Résolu/Fermé]

Signaler
-
 jean -
Bonjour,

je débute en langage C et je voudrais faire une fonction me permettant de copier une chaine de caractères afin de pouvoir ensuite travailler dessus.

#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int recuperation();
int copy();


int main(int argc, char *argv[])
{
recuperation();

system("PAUSE");
return EXIT_SUCCESS;
}

int recuperation()
{
printf ("Entre votre chaine : ");
char phrase[10];
gets(phrase);
printf ("la chaine entree est : %s \n", phrase);


}

int copy (int *phrase,int *phrase_copy)
{
int tmp;
int i;
int n = strlen(phrase);


for ( i=0; i<n; i++)
{
tmp=*phrase;
*phrase=phrase_copy;
}
phrase++;
printf ("la chaine copiee est : %s \n", phrase_copy);
}


Voila donc je commence par rentrer la chaine ce qui fonctionne bien et c'est dans la seconde partie où il y a un problème probablement dans les arguments. J'ai trouvé quelques problèmes ressemblant sur le net mais je n'ai pas réussi à fait le rapprochemnt bien que ce soir certainement une erreure bête dans les paramètres ou declarations. J'ai donc tenté de changer ceux-ci sans resultats.

In function 'int copy(int*, int*)
cannot convert 'int*' to const char* for argument '1' to 'size_t strlen(const char*)
invalid conversion from 'int*' to 'int'

Merci pour le temps que vous m'accorderez!

2 réponses

Messages postés
29703
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
8 avril 2021
7 066
1) Si tu es en C (et non en C++) il faut utiliser le headers <stdlib.h> et non <cstdlib> (qui wrappe le header C pour le C++). Dans ton cas vu que tu n'utilises ni std::cout, std::cerr, std::cin (et leurs opérateurs << et >>) tu n'as aucune raison d'inclure <iostream> (qui est le header C++ de ces trois flux). En l'occurrence tu utilises printf (qui lui est dans <stdio.h>).

2) Pour la même raison, tu peux virer le using namespace std; qui est spécifique au C++ et qui permet de sous-entendre les std:: (par exemple tu peux écrire cout au lieu de std::cout). Personnellement je déconseille l'utilisation des "using" même si ça entraîne parfois quelques lourdeurs d'écriture.

3) Ensuite il faut éviter l'instruction system qui est une très mauvaise habitude. De plus l'instruction pause n'a de sens que sous windows. En l'occurrence il vaut mieux remplacer system("pause") par :
getchar();

(ce qui fait exactement la même chose)

4) Apparemment la fonction copy sert à dupliquer une chaîne. Il faut bien voir que cette fonction existe déjà dans la lib C (stcpy) : http://www.manpagez.com/missing.php
Maintenant si c'est un exercice on peut effectivement s'entraîner à coder son propre strcpy.
- Pour commencer quand un entier est positif, on utilise plutôt un unsigned int (ou unsigned en abrégé) car si on se trompe (comparaison entre entier signés et non signés, le compilateur nous préviendra).
- Les fonctions recuperation et copy ne retournent rien donc leur type de retour est void.
- La fonction recuperation ne permet pas de récupérer la chaîne lue !!!
- De plus comme on est en C et pas en C++ les variables doivent être déclarées en début de scope (pour faire simple en début de fonction).
- Ensuite dans copy, une chaîne est un tableau de char donc de type char *.
- Ta fonction copy réécrit la chaîne de départ dans un noueau tableau mais celui-ci n'a pas été alloué. Comme cet espace n'a pas été reservé, le programme plantera et déclenchera une segmentation fault. Il faut donc l'allouer au préalable ou faire un malloc. En terme de design de programme, l'allocation mémoire doit être fait par la fonction qui appelle ta fonction copy. C'est donc ce qu'on va faire.
- La boucle for ne permet pas d'avancer dans la chaîne de départ, tu recopieras donc tout le temps le premier caractère.

Voici le programme corrigé :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void recuperation(char *phrase){
    printf("Entrez votre chaine : ");
    gets(phrase);
    printf("la chaine entree est : %s \n", phrase);
}

void copy (char *phrase,char *copie){
    unsigned i;
    unsigned n = strlen(phrase);
    for (i=0; i<=n; i++){ // on s'arrete à i==n pour récupérer le '\0' qui termine la chaine
        copie[i] = phrase[i];
    }
}

int main(){
    char phrase[10]; // si la chaîne est de longueur >10, le programme plante
    char copie[10];
    recuperation(phrase);
    copy(phrase,copie);
    printf ("la chaine copiee est : %s\n",copie);
//  system("PAUSE");
    getchar();
    return EXIT_SUCCESS;
}

Après on peut aller plus loin car ce programme s'écrit beaucoup plus facilement en C++ :
#include <iostream>
#include <string>
#include <cstdio> // getchar()

int main(){
    std::string phrase;
    std::cout << "Entrez votre phrase : ";
    std::cin >> phrase;
    std::cout << "La phrase entrée est : " << phrase << std::endl;
    std::string copie = phrase;
    std::cout << "La phrase copie est : " << copie << std::endl;
    getchar();
    return 0;
}

L'avantage c'est que la le programme marche même pour une chaîne de taille supérieure à 10, on n'a pas à se préoccuper des '\0' etc...

Bonne chance
J'ai effectivement fait un projet C++ car les projets C sur mon dev-c++ ont quelques soucis mais je ne connais pas encore le C++. On m'a alors dit que je pouvais procéder ainsi.

Ma fonction recuperation ne permet pas de récupérer la chaine c'est parce que je dois créer le tableau dans le main? Tu dis que c'est une question de design de l'allouer à l'endroit où on appelle la fonction, est normal que si on l'alloue dans copy ça mette une erreur?

Dans la fonction copy je pensais avoir fait un pointeur me permettant d'avancer dans les caractère après chaque boucle je suppose que je n'ai pas réalisé ce que je pensais avoir fait?

Sinon j'aurais eu une question sur, tu écris les fonctions avant le main, c'est préférable ou on peut les écrire après et les déclarer avant comme j'avais fait ou ça ne se fait pas?

Je sais je suis un peu curieux mais après tout il faut l'être pour progresser.

Sinon je vois effectivement mes erreurs et ce qui faut faire pour y remédier, je vais pouvoir avancer dans l'exercice.

Merci encore pour ton aide et ces conseils! ;-)
Messages postés
29703
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
8 avril 2021
7 066
J'ai effectivement fait un projet C++ car les projets C sur mon dev-c++ ont quelques soucis mais je ne connais pas encore le C++. On m'a alors dit que je pouvais procéder ainsi.

Le truc c'est que pour le moment, tu ne tires pas parti des avantages du C++ (cf 2e version que je te propose, beaucoup plus simple) et ton programme ne peut compiler en C. Les indications que je t'ai donné servent simplement à soit tirer pleinement parti des fonctionnalités du C++, soit faire un programme en C pur.

Ma fonction recuperation ne permet pas de récupérer la chaine c'est parce que je dois créer le tableau dans le main? Tu dis que c'est une question de design de l'allouer à l'endroit où on appelle la fonction, est normal que si on l'alloue dans copy ça mette une erreur?

La variable doit effectivement être soit passée en paramètre de la fonction (et crée au niveau du main) soit retournée par la fonction, sans quoi la variable reste locale à la fonction. En terme de design il faut au préalable appréhender la notion de scope (horizon en français) qui est simplement une paire d'accolade (de fonction ou de boucle). En général ce qui est alloué en début de scope doit être désalloué à la fin de ce scope afin de n'oublier personne. Quand tu auras vu les malloc tu verras qu'il faut faire un free, c'est à ca que je fais allusion.
{ // debut scope
   declaration variable + allocation
   instructions
   liberer variables allouées
} // fin de scope

Dans ton cas le scope en question c'est la fonction main, et les instructions sont les appels à tes deux fonctions. Je vais laisser ce point en suspens, on y reviendra ultérieurement si ça t'intéresse. Dis-toi juste pour le moment que tes variables locales sont implicitement désallouées en fin de scope, seuls les pointeurs ont besoin d'être désalloués. Tu verras aussi que cette règle de design ne peut pas toujours être suivie en pratique et c'est pourquoi on a recours à des fonctions "constructeur" (allocation) et "destructeur" (désallocation).

Dans la fonction copy je pensais avoir fait un pointeur me permettant d'avancer dans les caractère après chaque boucle je suppose que je n'ai pas réalisé ce que je pensais avoir fait?


Non ton pointeur n'avance pas dans ce que tu as écrit, seul i était incrémenté dans la boucle for.

Sinon j'aurais eu une question sur, tu écris les fonctions avant le main, c'est préférable ou on peut les écrire après et les déclarer avant comme j'avais fait ou ça ne se fait pas?

Personnellement je mets toujours le main à la fin, ça m'évite de déclarer des prototypes comme tu as fait. Après c'est vraiment comme tu préfères il n'y a pas vraiment de règle.

Je sais je suis un peu curieux mais après tout il faut l'être pour progresser.

C'est plutôt une qualité je trouve

Sinon je vois effectivement mes erreurs et ce qui faut faire pour y remédier, je vais pouvoir avancer dans l'exercice.
Merci encore pour ton aide et ces conseils! ;-)

Pas de soucis, bonne continuation
Bonsoir,

En vacances depuis ce midi j'ai pu recoder quelques lignes et j'ai encore un léger problème, décidément il est difficile de débuter en C.. ^^

Dans les lignes codées je n'ai pas de soucis à la compilation mais il n'effectue pas ce que je souhaite.

void supprime_espace(char *copie, char *ssespace)
{
unsigned i=0;
unsigned n = strlen(copie);
while (i <= n)
{
if ( !isspace(*copie) )
{
ssespace[i] = copie[i];
i++;
}

else
{
i++;
}
}
}

La nouvelle chaine ssespace qui devrait être la même que la précédente en ayant comme son nom l'indique supprimer les espaces ne le fait pas. j'ai ensuite essayer de passer avec un pointeur voir si ça allait pas mieux fonctionner mais je me suis casser les dents étant donné qu'après m'afficher le même résultat que précédemment le programme plante. Je me demande donc si le problème ne vient pas de la fonction if en fait plutôt mais bon je me suis demander pas mal de choses sans pour autant trouver le résultat escompté.

void supprime_espace(char *copie, char *ssespace)
{
unsigned i=0;
unsigned n = strlen(copie);
char *pcopie = 0;
while (i <= n)
{
if ( !isspace(*pcopie) )
{
ssespace[i] = *pcopie;
pcopie++;
i++;
}

else
{
pcopie++;
i++;
}
}
}