Page 1 sur 1

[langage c] question (en cours)

Publié : mer. 13 avr. 2016, 18:47
par AchilleFraisse
Bonjour,
On peut poser des questions sur un programme écrit en C sur ce forum ?

Re: [langage c] question (en cours)

Publié : mer. 13 avr. 2016, 20:12
par FoolEcho
Tu peux toujours... après, ce n'est pas la vocation de ce forum, forcément.

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 04:35
par ed0c
Moi je dis qu'il ne peut pas

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 09:52
par AchilleFraisse
J'ai un programme qui se connecte via la protocole imap sur mon serveur mail.
J'ai une boucle infini (Tant que l'utilisateur ne veut pas quitter en tapant LOGOUT), qui permet d'envoyer des requêtes au serveur mail puis de recevoir les réponses :

Code : Tout sélectionner

/* On boucle tant que l'utilisateur ne veut pas quitter */
while((strstr(msg, "LOGOUT\r\n")) == NULL)
    {
        char *data = ""; /* Chaine contenant la réponses du serveur */

        i++;
        /* Saisie de l'utilisateur */
        printf("\n> ");
        input(tmp, 1024); /* Voire la fonction input comme la fonction scanf, mais en plus évolué */

        sprintf(msg, "%d %s\r\n", i, tmp); /* On construit le message à envoyer au serveur mail */

        /* Envoie de la saisie au serveur */
        if(send(sock, msg, strlen(msg), 0) < 0)
        {
            perror("send()");
            exit(errno);
        }

        /* Récupération des données */
        do {
            /* On recoit les données par bloc de 1024 octets */
            if((n = recv(sock, buffer, sizeof buffer, 0)) < 0)
            {
                perror("recv()");reqûete
                exit(errno);
            }

            /* On termine la chaine de caractère par le '\0' de fin de chaine */
            if(n < 1024)
                buffer[n] = '\0';

            /* VERSION 1 : COMMENTER CETTE LIGNE */
            data = add(data, buffer); /* Reconstruction de la chaine */

            /* On ferme le serveur à la demande de l'utilisateur */
            if((strstr(msg, "LOGOUT\r\n")) != NULL)
            {
                printf("Serveur fermé !\n\n");
                break;
            }
            /* VERSION 1 : DECOMMENTER CES DEUX LIGNES */
            //else
            //   printf("%s", buffer);

        } while(strstr(buffer, "completed.\r\n") == NULL);

	/* VERSION 1 : COMMENTER CETTE LIGNE */
        printf("%s", data);
        
        free(data);
    }
Et voici la fonction add :

Code : Tout sélectionner

char *add(char *ch1, char *ch2)
{
    char *data = "";
    int i, j, n = strlen(ch1), m = strlen(ch2);

    data = (char*) malloc(n * sizeof(char) + m * sizeof(char));
    //strcat(data, ch1);
    //strcat(data, ch2);

    for(i = 0 ; i < n ; i++)
        data[i] = ch1[i];

    for(j = i ; j < m+n ; j++)  
        data[j] = ch2[j-i];

    return data; 
}
Les données sont reçu du serveur par bloc de 1024 octets. Ma variable data a donc une taille de 1025 pour accueil le '\0' de fin de chaine.

Lors de la première requête effectué sur le serveur, tout ce passe bien (je reçois bien les données).
Lors de la deuxième requête, je reçois que la moitié des données, et il y a des caractères qui se sont transformé en caractère bizarre. Pourtant les deux requêtes sont identiques.

Je ne vois pas pourquoi ? Voyez vous une erreur dans mon code ?

NB : Je tient à signaler que si je ne regroupe pas toutes les données reçu dans la variable data avant de les afficher, mais que je les affiche par bloc de 1024 octets (décommenter les deux lignes avec le else, et commenter la ligne du printf("%s", data) et data = add() ), tout marche très bien.
Mais ce que je veux c'est toutes mes données d'une requête dans une seule variable.

J'espère avoir été clair.

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 10:15
par oktoberfest
J'imagine que buffer est déclaré comme ça :

Code : Tout sélectionner

char buffer[1024];
Premier souci : si tu reçois précisément 1024 caractères, tu n'auras pas de '\0' de fin de chaîne à la fin de buffer. Donc ta fonction add ne va pas trop bien marcher.

Ensuite tu as des fuites mémoire, quand tu fais :

Code : Tout sélectionner

data = add(data, buffer)
data pointe sur une zone mémoire. A la sortie de la fonction add, data pointe sur une autre zone mémoire (celle allouée dans add). Mais l'ancienne zone mémoire n'est pas libérée.

PS : Je ne me souvenais plus que le C pouvait être aussi bas niveau et moche à lire :)

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 10:23
par benjarobin
Ta fonction add ne réserve pas via le malloc le \0 de fin.
Sinon pourquoi ne pas utiliser strcpy et strcat ? Voir encore plus simple de remplacer toute cette fonction (ok c'est un peu moins rapide mais vraiment tu n'est pas à quelques us prêt) par

Code : Tout sélectionner

asprintf(&data, "%s%s", ch1, ch2)

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 10:29
par AchilleFraisse
oktoberfest a écrit :J'imagine que buffer est déclaré comme ça :

Code : Tout sélectionner

char buffer[1024];
Premier souci : si tu reçois précisément 1024 caractères, tu n'auras pas de '\0' de fin de chaîne à la fin de buffer. Donc ta fonction add ne va pas trop bien marcher.
Non, justement buffer est déclaré comme ceci :

Code : Tout sélectionner

char buffer[1025];
benjarobin a écrit :Ta fonction add ne réserve pas via le malloc le \0 de fin.
Sinon pourquoi ne pas utiliser strcpy et strcat ? Voir encore plus simple de remplacer toute cette fonction (ok c'est un peu moins rapide mais vraiment tu n'est pas à quelques us prêt) par

Code : Tout sélectionner

asprintf(&data, "%s%s", ch1, ch2)
Je ne connaissais pas asprintf() . Mais lorsque je marque :

Code : Tout sélectionner

asprintf(&data, "%s%s", data, buffer)
il me dit implicit declaration of function asprintf.

Deplus, si je garde mon code précédent et que j’enlève tout simplement free(data), ca marche.

Re: [langage c] question (en cours)

Publié : jeu. 14 avr. 2016, 18:48
par aminnairi
Salut,
AchilleFraisse a écrit : il me dit implicit declaration of function asprintf.

Code : Tout sélectionner

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
[...]
asprintf(3) - Linux man page

*flies away*

Re: [langage c] question (en cours)

Publié : mar. 26 avr. 2016, 10:22
par AchilleFraisse
Il me renvoie encore le même warning

Re: [langage c] question (en cours)

Publié : mar. 26 avr. 2016, 10:45
par benjarobin
Pourtant ceci compile (et fonctionne) sans warning

Code : Tout sélectionner

#define _GNU_SOURCE 1
#include <stdio.h>

int main(void)
{
    char *data = NULL;
    const char *ch1 = "hello";
    const char *ch2 = " world";

    asprintf(&data, "%s%s", ch1, ch2);
    puts(data);
    return 0;
}
Compilé avec

Code : Tout sélectionner

gcc -std=c99 -O2 -Wall -Wextra t.c -o t

Re: [langage c] question (en cours)

Publié : mar. 26 avr. 2016, 17:28
par aminnairi
Je confirme, même sans spécifier la version. Donnes-nous la commande que tu utilise pour compiler.