IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

remplacement caractère dans chaine


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2009
    Messages : 46
    Points : 48
    Points
    48
    Par défaut remplacement caractère dans chaine
    Bonjour,
    après quelques années d'égarement en Python, je cherche à parfaire mon C.
    Pour cela, je fais des exercices sur rosalind.info (site d'entrainement à la bio-info), et je bloque à l'exo 2 sans comprendre mon erreur ...
    L'objectif est simple: écrire un programme (j'ai choisi en C) qui lit une séquence d'ADN (ATGTGACG) et la transcrit en ARN (AUGUGACG).

    Pour cela, j'ai écrit un bout de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(int argc, char *argv[]){
    	FILE *infile = NULL;
    	char chaine;
     
    	infile = fopen(argv[1], "r");
    	if(infile != NULL){
    		do{
    			chaine = fgetc(infile);
    			if(chaine=="T"){
    				printf("U");
    				}else{
    				printf("%s", chaine);
    				}
    			}while(chaine != EOF);
    	}else exit(EXIT_FAILURE);
    	return(0);
    }
    Le compile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    gcc p2.c -o p2
    p2.c: In function ‘main’:
    p2.c:12:13: warning: comparison between pointer and integer [enabled by default]
        if(chaine=="T"){
                 ^
    p2.c:15:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int[-Wformat=]
         printf("%s", chaine);
         ^
    Et en le lançant j'ai ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     ./p2 test.txt 
    Erreur de segmentation (core dumped)
    .

    (test.txt = GATGGAACTTGACTACGTAAATT)

    Je ne comprends vraiment pas où j'ai faux.

    Bises et bonnes fêtes!
    M.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il y a confusion entre caractère et chaine de caractères.
    Un caractère est un objet de type char
    Un littéral caractère se note entre guillemet simple : 'A' , '0' '\n' ... C'est un int (enC) dont la valeur dépend du codage utilisé des caractères (fréquemment ASCII)

    Une chaine de caractère est simplement un tableau de caractères (de char) contenant quelque part un '\0' qui marque la terminaison de la chaine.
    Un littéral chaine de caractères se note entre guillemet double : "ABCDE" ... Cette chaine, donnée en exemple, utilise 6 char (il y a le zéro terminal à ne pas oublier).

    Dans ton code, chaine est déclaré char et ne peut stocker qu'une chaine vide (il n'y a de place que pour le zéro terminal). Il faut la déclarer comme un tableau (suffisamment grand) de char.

    On peut comparer deux char avec l'opérateur == , après tout ce sont des entiers.
    On ne peut pas comparer deux chaines avec cet opérateur. Il faut utiliser des fonctions de la bibliothèque standard (prototypes dans <string.h>) pour le faire. Ici strcmp() fera l'affaire. On ne peut pas non plus copier une chaine dans une autre par l'opérateur d'assignation =, mais on doit utiliser une fonction standard comme strcpy() .
    En fait, aucun opérateur appliqué à une chaine ne s'applique à son contenu.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Ce qu'il faut bien que tu comprennes, c'est que (contrairement à Python où une chaine est déjà un objet), une chaine de caractères n'existe pas en C. Il n'est pas assez haut niveau pour pouvoir manipuler ce genre d'entité.

    En C, on utilise pour pouvoir manipuler des chaines des tableaux de caractères. Donc quand tu écris char toto[]="Hello" ça va alors stocker le caractère 'H' dans l'élément [0] du tableau "toto", le caractère 'e' dans son élément [1] et etc.

    Et toi, à partir de là, tu ne peux que traiter ces éléments un par un. Si par exemple tu veux savoir si le tableau "toto" contient la chaine "salut" tu devras alors regarder si toto[0] vaut 's', si toto[1] vaut 'a' et etc. En Python, les crochets pour accéder à l'élément [x] d'une chaine sont une souplesse d'écriture offerte en plus des autres, en C c'est la seule possible.

    Fort heureusement ces algos ont déjà été écrits et te sont accessible via les fonctions de traitement des chaines. T'as par exemple strcmp() à laquelle on passe deux chaines et qui se charge de traiter chacun de ses caractères pour te répondre au final si elles sont égales ou si l'une et plus petite que l'autre.

    Autre soucis: l'écriture if (toto == "salut") est autorisée mais cette instruction ne comparera que les adresses qui contiennent les chaines (adresses forcément différentes puisque la variable "toto" n'est pas à la même adresse que la chaine statique "salut") et non les contenus des chaines. Et il en ira de même chaque fois que tu essaieras de manipuler une chaine directement au lieu de manipuler ses éléments.

    Donc quand tu écris "T" (avec des guillemets doubles) le compilo croit que tu veux parler du tableau {'T', '\0'} et forcément il ne pige plus rien puisque dans ton esprit (tel que je vois ton code) tu essaies de comparer le caractère lu avec le caractère 'T' (avec des guillemets simples).

    T'aurais mieux fait d'en rester à Python (j'ai fait du C pendant 15 ans, ben quand je suis passé à Python ça a été le jour qui succède à la nuit )

    PS: essaie de bien nommer les actions. Ton titre dit "remplacement dans chaine" ce qui signifie que tu effectues un changement dans la chaine d'origine. Alors que ton code montre que tu effectues un affichage spécifique selon la valeur de certains caractères de la chaine qui elle, reste inchangée. Ce n'est pas tout à fait un "remplacement" ça...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre régulier
    Homme Profil pro
    Responsable ingénierie des logiciels - Recherche alternance
    Inscrit en
    Novembre 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable ingénierie des logiciels - Recherche alternance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 68
    Points : 92
    Points
    92
    Par défaut
    En utilisant strcmp et strcpy comme disais diogene :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(int argc, char *argv[]){
    	char *chaine = NULL;
    	int nbc; // contiendra le nombres de caractere du char
     
            strcpy( chaine, argv[1]); // on copie la chaine rentrée en paramètre dans "chaine"
            nbc = strlen(chaine); // on inscrit le nombre de caractere de chaine dans nbc
     
            for(int i=0; i<nbc; i++)
            {
                   if(chaine[i] == 'T')
                   {
                           printf("U");
                   }
                   else
                   {
                          printf("%s", chaine[i]);
                   }
            }
     
    return 0;
    Bon je n'est pas testé le code mais il y a de forte chances que ça marche ...
    Je sais pas si ça ne le fait qu'à moi mais le "tab" dans le textarea servant à la rédaction de la réponse ne marche plus pour m'a part ... Quelque peu gênant pour l'encapsulation.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Ojiuiookojbezib Voir le message
    En utilisant strcmp et strcpy comme disais diogene :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    #include <stdlib.h>
    #include <stdio.h>
     
    int main(int argc, char *argv[]){
    	char *chaine = NULL;
    	int nbc; // contiendra le nombres de caractere du char
     
            strcpy( chaine, argv[1]); // on copie la chaine rentrée en paramètre dans "chaine"
            // Et pourquoi donc ??? Ca fait trop mal au luc de travailler à partir de argv[1] ???
            // Au fait, t'es sûr que ton pointeur pointera vers une zone mémoire adéquate pour stocker tous les caratères de argv[1]
     
            nbc = strlen(chaine); // on inscrit le nombre de caractere de chaine dans nbc
            // Pas vraiment utile ici - Au lieu de boucler jusqu'à nbc on bouclera jusqu'à chaine[i] = '\0'...
     
            for(int i=0; i<nbc; i++)
            {
                   if(chaine[i] == 'T')
                   {
                           printf("U");  // Utiliser un marteau pour ouvrir une noisette, oui si on veut mais si on utilise les outils adaptés ça optimise le code... fputc('U', stdout)
                   }
                   else
                   {
                          printf("%s", chaine[i]); // %s ? T'es sûr ???
                   }
            }
     
    return 0;
    Bon je n'ai pas testé le code mais il y a de forte chances que ça marche ...
    Je ne pense pas (surtout quand tu remplis un pointeur sans lui avoir alloué de mémoire pour stocker ce qu'il a à stocker). Mis à part ça il y a quand-même beaucoup de malfaçons (voir mes commentaires dans ton code)...

    Citation Envoyé par Ojiuiookojbezib Voir le message
    Je sais pas si ça ne le fait qu'à moi mais le "tab" dans le textarea servant à la rédaction de la réponse ne marche plus pour m'a part ... Quelque peu gênant pour l'encapsulation.
    Moi ça n'a jamais marché. Soit je tape mes codes en mettant des espaces, soit je le tape sous gvim puis je le copie/colle...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre régulier
    Homme Profil pro
    Responsable ingénierie des logiciels - Recherche alternance
    Inscrit en
    Novembre 2013
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable ingénierie des logiciels - Recherche alternance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 68
    Points : 92
    Points
    92
    Par défaut
    Mince oui en effet
    Précipitation précipitation ...

Discussions similaires

  1. Remplacer caractère dans chaine de caractères via lexique
    Par nico2rib dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 13/07/2012, 15h01
  2. Remplacer caractère dans une chaine de caractères
    Par Baffien dans le forum SAS Base
    Réponses: 3
    Dernier message: 21/10/2009, 18h59
  3. Remplacement caractère dans une macro variable
    Par Atojul dans le forum Macro
    Réponses: 2
    Dernier message: 22/04/2008, 09h43
  4. Requête pour remplacer caractères dans une table
    Par elliott1961 dans le forum Installation
    Réponses: 5
    Dernier message: 16/01/2006, 01h47
  5. [String] Remplacement caractères dans une chaîne
    Par Crazyblinkgirl dans le forum Langage
    Réponses: 4
    Dernier message: 19/07/2004, 11h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo