Partie gauche de strchr

a marqué ce sujet comme résolu.

Bonjour, je voudrais récuperer ce qu’il y’a vant strchr :

1
2
3
char string[] = "hello this is a sentence";
char *token;
token = strchr(string, ' ');

ce code me retourne this is a sentence

moi je voudrais récupérer : hello

sur google quand je tape strchr reverse, je trouve la fonction strrchr mais elle ne fait pas ce que je voudrais qu’elle fasse, elle retourne la dernnier occurence

moi je voudrais récupérer la partie gauche de strchr, y’a t’il une solution ?

+0 -0

Une chaîne de caractères en mémoire, c’est une suite de caractères qui se termine par un \0. token est un pointeur vers là où se trouve le premier espace. Une idée serait donc de passer de cette représentation :

1
'h','e','l','l','o',' ','t','h',...

à

1
'h','e','l','l','o','\0','t','h',...

Est-ce que tu vois comment on pourrait faire ?

Oui effectivement, mais mais si tu as un pointeur (disons p) qui pointe sur la première case de :

1
'h','e','l','l','o','\0','t','h',...

alors printf("%s", p) affichera hello. Et de même pour toutes les fonctions qui travaillent sur une chaîne, comme strcmp, strchr, etc. : les caractères qui suivent ne seront pas pris en compte, en quelque sorte (même s’ils existent toujours en mémoire). Tu peux tester, par exemple :

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <string.h>

int main(void) {
    const char t[] = {'h','e','l','l','o','\0','t','h','\0'};
    puts(t); // hello
    printf("%d\n", strcmp(t, "hello")); // 0
    return 0;
}

On est dans une partie assez spécifique au C : "récupérer la partie gauche", c’est équivalent à trouver un pointeur sur une zone mémoire qui contient les caractères 'h','e','l','l','o','\0', et ce peu importe ce qu’il y a après. Par contre, tu peux toujours te ramener à quelque chose de plus classique en te plaçant à un autre endroit de la mémoire :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
#include <string.h>

int main(void) {
    const char t[] = {'h','e','l','l','o','\0','t','h','\0'};
    char dst[32];
    strcpy(dst, t);
    puts(dst);
    return 0;
}

Est-ce que c’est plus clair ?

Ta variable token représente ton premier espace. Tout ce qui t’intéresse se trouve donc entre les deux adresses mémoires situées respectivement àstring (le début de ta chaine) et à token (fin de la chaine qui t’intéresse).

Lucas-84 > C’est quoi ton délire ?

+0 -2

Lucas-84 > C’est quoi ton délire ?

Davidbrcz

Étonnamment, tu me donnes moyennement l’envie de te répondre gentiment. Et je vois pas ce qui te choque dans mes messages.

Lucas-84

Bah tu ponds deux réponses (dont 1 pavé) assez incompréhensibles qui tournent vaguement autour du pot et qui AMA ne vont pas aider le PO (qui a tout l’air d’un débutant).

Sans vouloir donner la réponse clé en main (ce que je comprends), y’a moyen de le diriger vers strtok ou sscanf de manière plus explicite.

+0 -0

Bah tu ponds deux réponses (dont 1 pavé) assez incompréhensibles qui tournent vaguement autour du pot et qui AMA ne vont pas aider le PO (qui a tout l’air d’un débutant).

Sans vouloir donner la réponse clé en main (ce que je comprends), y’a moyen de le diriger vers strtok ou sscanf de manière plus explicite.

Davidbrcz

Ah mais moi ma solution initiale c’était juste *token = 0. ^^ Alors avant que tu râles, je précise : avec tous les désavantages associés, à savoir qu’on modifie la chaîne de départ (même si le code de l’OP part déjà de ce principe…), que ça ne marche pas avec les chaînes littérales, etc.

Quant à ma tentative d’explication incompréhensible, elle est quand même censée couvrir des choses qui sont à mon avis des pré-requis à d’autres solutions avec des fonctions de bibliothèque (p.ex. faire un peu d’arithmétique des pointeurs et strncpy). En général j’aime bien broder autour de la question ; si jamais l’OP veut juste ses deux lignes de code et repartir sans avoir rien appris, libre à lui. C’est juste que c’est ma pas ma philosophie.

Bon et si t’as des remarques un peu plus précises que « c’est quoi ton délire lol » sur comment rendre mes messages compréhensibles, je suis à l’écoute. ;)

ce que je voudrais faire c’est séparer ma phrase a chaque virgule puis prendre le premier élement

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void change(char **a);

int main() {
    char sourceHold[]="toto arg1 arg2 arg3,tutu arg1 arg2,titi";
    char *tok = strtok(sourceHold, ",");
    while(tok != NULL) {
        printf("element complet %s\n",tok);

        char* dest;
        strcpy(dest, tok);
        char *tok2 = strtok(dest, " ");
        while(tok2 != NULL) {
            printf("element sans arguments %s\n",tok2);
            tok2 = strtok(NULL, " ");
        }

        tok = strtok(NULL, ",");
    }
}

je bloque avec le 2ieme strtok (ma variable tok2), je sais pas pourquoi j’ai une seg fault

+0 -0

Parce que la fonction strtok est à effets de bord : elle utilise une variable statique pour stocker le tampon, ce qui la rend non-réentrante.

Mais en parcourant le manuel de strtok, tu devrais trouver strtok_r, son équivalent réentrant.


Edit : Bon, j’ai été un peu trop vite. Avant d’arriver sur ce problème de réentrance, tu es bloqué par le segfault que provoque strcpy. Tu copies en effet une chaîne de caractères vers une zone mémoire non allouée (dest est un pointeur non initialisé), donc ça plante en toute logique.

merci je connaissais pas cette fonction la solution :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void change(char **a);

int main() {
    char sourceHold[]="toto arg1 arg2 arg3,tutu arg1 arg2,titi";

    char *token;
    char *rest = sourceHold;

    while((token = strtok_r(rest, ",", &rest)))
    {
        printf("token:%s\n", token);
        char *token2;
        char *rest2 = token; 
        token2 = strtok_r(rest2, " ", &rest2);
        printf("token2:%s\n", token2);

    }
}
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte