alf a écrit 255 commentaires

  • [^] # Re: base de la programmation

    Posté par  . En réponse au message Question pour C gourou !. Évalué à 2.

    #include <stdio.h>
    
    struct enreg { /* ... */ };
    
    void fct(struct enreg *s) {
    char chaine[256], date[20], heure[20];
    int v;
    float a,b,c,d;
    int i=0;
    
    FILE *fp = fopen("1.txt", "r");
    N'oublie pas de vérifier si fopen a bien pu ouvrir le fichier (if (fp == NULL) { /* erreur */ }).
    while(fgets(chaine, sizeof(chaine), fp)) {
    Faire un while sur fgets est mieux que sur feof, mais ce n'est pas encore ça. Si une ligne du fichier fait plus de 254 caractères, tu auras des surprises... (voir http://linuxfr.org/comments/784745,1.html où j'en ai déjà parlé)
    sscanf(chaine, "%s %s %d %f %f", date, heure, &v, &a, &b );
    Il faut toujours tester les valeurs de retour des fonctions *scanf. Elles retournent le nombre de conversions effectuées avec succès. dans ton cas, si elle renvoie un nombre différent de 5, alors il y a une erreur. Par ailleurs, si une des deux premières chaînes fait plus de 19 caractères, tu obtiens un débordement de tampon, et donc un comportement indéfini. Vérifie dans la doc, mais il me semble que le bon format est %[20]s.
    (s+i)->v = v;
    C'est correct mais, pour des raisons de lisibilité, je préfère la notation s[i].v.
    main() {
    Non. int main(void). gcc autorise un type absent pour la fonction main, car il se base sur le C90, mais il faut préciser le type en mode C99.
    struct enreg x[1000000]; // cree la structure x
    Ouch. 1000000 de fois environ 50 octets (en suposant une implémentation classique), ça fait 50 Mo sur la pile. Un peu gros. Ca compilera très probablement (peut-être avec un warning si le compilo n'est pas trop mauvais), mais ce n'est pas garanti que ça marche à l'exécution. Utilise plutôt une allocation dynamique avec malloc.
    fct(&x[1000000]);
    Comme déjà dit, fct(x);.
  • [^] # Re: Le libraire qui me fait rêver...

    Posté par  . En réponse au journal Un auteur contre Amazon. Évalué à 3.

    Je comprends la réaction de George Walter, mais je me demande tout de même s’il n’exagère pas un peu. Je suis le premier à défendre les libraires indépendants, mais cependant, il ne faut pas surestimer les problèmes des libraires indépendants. Attention, cela ne veut pas dire que je nie les difficultés qu’ils peuvent rencontrer comme la concurrence de très grandes structures de vente.

    Oui et non. En France, on a la loi Lang sur le prix unique des livres, qui n'autorise les vendeurs qu'à faire des réductions d'au plus 5% sur le prix indiqué (par l'éditeur ou l'importateur), mais d'autres pays n'ont pas de loi similaire, et là la concurrence peut faire beaucoup plus mal. http://www.culture.gouv.fr/culture/dll/prix-livre/prix-1.htm donne, en plus d'explications sur la loi Lang, la situation dans d'autres pays. On note qu'au Royaume-Uni, un accord entre professionnels (?) plus ou moins équivalente, et datant de 1900 à été supprimée en 1995...

    Mais je suis d'accord sur le fait que, tant qu'il y aura des gens qui aiment les livres, les petites librairies indépendantes auront leur mot à dire.

    J’ai trouvé par hasard mon libraire idéal : c’est le genre d’endroit qu’on pense seulement voir dans les films. Au comptoir, il y a un vieux monsieur avec une petite barbe blanche et des lunettes. Dans le magasin, il n’y que des vieux livres qui sont empilés dans le désordre. Il y a plein de poussière et lorsqu’on rentre, on renifle l’odeur des vieux livres.

    C'est quoi l'adresse ? ;)
  • [^] # Re: Commentaires

    Posté par  . En réponse au message rattacher sur init. Évalué à 3.

    Maintenant, avoir un process qui dépende de 1 (PPID == 1), dépend plutot de comment tu le lances. En l'occurence, lance le avec un & à la fin et celui ci se "détachera" de ton shell et prendra comme PPID celui d'init.

    Le & fait dépendre le process d'init ? J'ai un doute, là... Il ne le lance pas plutôt dans un sous-shell, pour en garder le contrôle ? (je n'ai pas de shell sous la main pour faire le test)
  • [^] # Re: Commentaires

    Posté par  . En réponse au message rattacher sur init. Évalué à 3.

    Bon choix pour le K&R ;) Je suppose que c'est la 2è édition ? N'oublie pas http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html pour les errata.
    Ceci étant, je ne parviens toujours pas à lancer executable avec un PID égal à 1.
    Un PPID égal à 1, tu veux dire ?
    D'ailleurs en passant, si vous avez des sites ou ouvrages à me recommander n'hésitez pas :)
    J'ai déjà donné la FAQ de c.l.c. Il y a aussi :
    • celle de fr.comp.lang.c ;
    • celle de developpez.com ;
    • http://clc-wiki.net/ qui est un site assez récent (donc encore peu rempli), développé par des gens de comp.lang.c (donc bien) (mais j'ai souvent des problèmes pour m'y connecter). Il pointe lui-même sur des ressources intéressantes ;
    • et le site officiel du groupe au sein de l'ISO qui édite la norme C http://www.open-std.org/JTC1/SC22/WG14/ , sur lequel tu peux trouver principalement des versions de travail (drafts) de la norme (en suivant le lien "standards", le n1124 étant la dernière version C99 + correctifs) et le "Rationale" qui est un commentaire de la norme faite par le groupe de travail lui-même, et qui donne des explications détaillées sur le pourquoi du comment.
    • pour faire du POSIX, la norme elle-même est payante, mais la Single Unix Specification, qui englobe POSIX plus d'autres choses, est elle gratuite et dispo sur http://www.unix.org/single_unix_specification/ .
    • je suggèrerai aussi la doc de ton compilo, les man...
  • # Commentaires

    Posté par  . En réponse au message rattacher sur init. Évalué à 10.

    je commence à étudier le C
    Bon courage :)
    Et voici que je bute sur un problème qui est peut-être lié aux avancés de gcc.
    Ou peut-être à ton code ? Avant de jeter la pierre à tes outils (ok, tu as mis "peut-être"), il est parfois préférable d'y regarder à deux fois.
    mon soucis ici, c'est que executable reprend le pid du lanceur...
    J'ai du mal à comprendre ta phrase. Ici, le "lanceur", c'est le processus qui reçoit le 0 par le fork, ou le processus qui a lancé le programme (i.e. le shell, par exemple) ?
    #include sys/types.h
    #include unistd.h
    Je suppose que les < et > sont partis durant le copié-collé... (en passant, ce n'est pas du C "pur", mais l'extension au langage C fournie par la norme POSIX. Je précise juste pour qu'il n'y ait pas de confusion, vu que tu commences à étudier le C)
    main() {
    Non. main renvoie une valeur de type int. gcc accepte que main ne renvoie rien, mais c'est une extension non portable, à éviter. Par ailleurs, si tu n'utilises pas de paramètres, il est conseillé de mettre un void explicite comme liste de paramètres (le void n'est pas nécessaire pour main, mais permet d'être plus clair). D'où :
    int main(void)
    La suite :
            pid_t pid;
            pid = fork();
    
            if (!pid) {
    Pour des valeurs entières, je préfère le test plus explicite :
            if (pid == 0) {
    On remarque que tu n'as prévu que 2 cas dans ton code, alors qu'il y en a normalement 3 : l'erreur (-1), le succès et le processus fils qui continue (0) et le succès et le processus père qui continue (fork renvoie alors le PID du fils). Pour savoir ce qui se passe précisément, distinguer les 3 cas serait souhaitable. Si le forka échoué, le programme quitte sans appeler executable. S'il a réussi, le processus père quitte, et c'est seulement le processus fils qui remplacera sa propre image par celle de executable. Donc le processus exécutant executable aura le PID du fils, et non celui du père. Par contre, son PPID sera celui de son père. Et quand le père se termine, le PPID du fils est changé pour être celui d'un processus défini par l'implémentation (dixit SUSv3), usuellement init si je me souviens bien (ou le grand-père ?).
                    execl("./executable", NULL, NULL);
    Il serait bon de vérifier si l'appel fonctionne (-1 en cas d'erreur). Pour l'instant, ça a l'air de marcher, mais quand tu voudras changer le nom du programme appelé, ou que tu te placeras dans un autre dossier pour le lancer, ou... alors tu seras content d'avoir un message d'erreur explicite ;)
            } else {
    
                    return;
    
            }
    Comme tu n'as pas donné de type de retour à main il est cohérent de ne pas retourner de valeur, mais comme main doit renvoyer une valeur entière, il vaut mieux renvoyer 0 (ou EXIT_SUCCESS).
  • [^] # Re: Pseudo-aléa et initialisation

    Posté par  . En réponse au message Question sur les fonctions RAND et SRAND. Évalué à 5.

    J'oubliais : http://c-faq.com/lib/index.html , question 13.16 pour une meilleure méthode d'extraction d'une valeur pseudo-aléatoire à partir du résultat de rand que "rand() % m + b", puis questions 13.15 à 13.20 pour plus d'informations.
  • # Pseudo-aléa et initialisation

    Posté par  . En réponse au message Question sur les fonctions RAND et SRAND. Évalué à 5.

    Comme tu l'as toi-même précisé, rand renvoie une valeur pseudo-aléatoire. srand initialise la graine de génération du pseudo-aléa retourné par rand. La norme C spécifie que, dans une implémentation donnée, pour une valeur de la graine, la suite de valeurs retournée par des appels successifs à rand doit être la même (mais cette suite peut être différente entre différentes implémentations, heureusement d'ailleurs).

    De plus, l'appel à rand sans avoir appelé srand revient à renvoyer le même pseudo-aléa qu'avec la graine 1. Il est donc normal que, sans srand, ton programme se comporte toujours de la même manière à chaque fois que tu l'appelles.

    Dixit le n1124 :

    7.20.2 Pseudo-random sequence generation functions
    7.20.2.1 The rand function
    Synopsis

    #include <stdlib.h>
    int rand(void);

    Description

    The rand function computes a sequence of pseudo-random integers in the range 0 to RAND_MAX.
    The implementation shall behave as if no library function calls the rand function.

    Returns

    The rand function returns a pseudo-random integer.

    Environmental limits

    The value of the RAND_MAX macro shall be at least 32767.

    7.20.2.2 The srand function

    Synopsis

    #include <stdlib.h>

    void srand(unsigned int seed);

    Description

    The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

    The implementation shall behave as if no library function calls the srand function.

    Returns

    The srand function returns no value.

    EXAMPLE The following functions define a portable implementation of rand and srand.
    static unsigned long int next = 1;
    int rand(void) // RAND_MAX assumed to be 32767
    {
        next = next * 1103515245 + 12345;
        return (unsigned int)(next/65536) % 32768;
    }

    void srand(unsigned int seed)
    {
        next = seed;
    }


    Une manière classique de choisir une graine pour srand, que tu as reprise dans ton code, est de récupérer la date courante par un appel time(NULL) (*). Ainsi, la graine sera différente à chaque exécution de ton programme (pourvu que ton programme ne soit pas lié à une libc "customisée" ;-) ), et donc la suite de pseudo-aléa sera différente.

    En passant, ces fonctions font partie de la bibliothèque C standard, donc dans ton contexte très probablement de la glibc, pas de gcc (qui n'inclut pas de bibliothèque C).

    (*) time renvoie une valeur de type time_t, alors que srand attend un unsigned int. Ce n'est pas grave, la conversion implicite se fera si besoin. Les considérations sur la qualité de la graine qui en découlent sont un peu trop complexes... (de toute façon, si on vient à se poser cette question, il est probable qu'on cherchera à utiliser un autre générateur de pseudo-aléa que celui fourni par défaut)
  • # Malloc

    Posté par  . En réponse au message creation d'une matrice de sous mot. Évalué à 2.

    1)
    int* pos=(int*)malloc(sizeof(int)); /*allouer la memoire pour le tableau position */
    Matrice* M=AllouerMatrice(strlen(mot)+1,1); / *allouer la memoire pour la matrice */

    Caster la valeur de retour de *alloc est inutile en C (bien qu'obligatoire en C++, mais c'est un autre langage). Le cast peut même cacher une erreur : en l'absence d'inclusion de l'en-tête stdlib.h, le prototype de malloc n'est pas "connu" au moment où tu appelles cette fonction. En mode C90, le compilateur supposera alors qu'elle renvoie le type int. Sur certaines archi, les conséquences sont nulles, mais il existe des achi sur lesquelles le code se comportera de manière erratique. Si, par exemple, des registres différents sont utilisés pour les entiers et les pointeurs, alors malloc renverra sa valeur de retour dans un registre "pointeur", et le code appelant ira chercher la valeur dans un registre "entier". D'où incohérence, et comportement indéfini garanti.

    Si tu affectais le retour de malloc dans une variable de type pointeur sur quelque chose, alors le compilateur devrait te renvoyer une erreur (*). Si tu castes la valeur avant l'affectation, comme tu le fais, alors le compilateur ne dit plus rien, car il suppose que tu sais ce que tu fais.

    Note qu'en mode C99, la règle du int implicite quand une fonction sans prototype visible est appelée n'existe plus, c'est directement une erreur (comportement indéfini, je crois, mais bref), et donc la question ne se pose plus.

    2)
    Si malloc n'arrive pas à allouer de la mémoire, elle renvoie un pointeur nul. Il faut donc faire un test :

    if (pos == NULL)
    {
        /* En cas d'erreur */
    }
    else
    {
        /* Le comportement "normal" */
    }

    .

    (*) En passant, le message d'erreur de gcc dans cette situation est très peu explicite pour celui qui ne connaît pas les détails du C...
  • [^] # Re: .

    Posté par  . En réponse au message Pointeurs et structures. Évalué à 2.

    Question de style, mais je n'aime pas caster dans le membre gauche d'une affectation. Il y a toujours le risque d'abuser de la notation, et le compilateur ne dit jamais rien sur un cast erroné. Ici, c'est ok, mais qui sait ce qui peut se passer dans d'autres programmes, si on caste un peu trop...
  • [^] # Re: .

    Posté par  . En réponse au message Pointeurs et structures. Évalué à 2.

    Je suis d'accord avec tout ton post (et spécialement le PS... y a-t-il un tracker ouvert pour ça ? Je le plussoierais sans vergogne ;)... Enfin, sauf le fait que sizeof S vaut nécessairement 4 sur une architecture 32 bits. Ca peut être 2, 1, 4... suivant l'humeur du compilo (mais, certes, 4 est une valeur très probable en environnement Unixoïde 32 bits).
  • [^] # Re: *

    Posté par  . En réponse au message Pointeurs et structures. Évalué à 2.

    Problème de précédence : (*alloc).addStart.
  • [^] # Re: scanf ?

    Posté par  . En réponse au message Probleme d'ecriture dans un STRUCT de int .. Évalué à 2.

    Dans un programme de test, c'est vrai ; mais autant prendre de bonnes habitudes ;)
  • [^] # Re: Bizarre

    Posté par  . En réponse au message Probleme d'ecriture dans un STRUCT de int .. Évalué à 3.

    Avec un peu de chance, si ton short fait bien 2 octets et ton int 4 (ce qui n'est pas obligatoire), il a écrit l'octet de poids faible au bon endroit (donc tu retrouves la bonne valeur), et les 3 autres dans un "ailleurs" qui n'est pas trop sensible pour ne pas planter le programme.
    Si ton int fait vraiment 4 octets, je soupçonne très fortement que, en raison de l'alignement mémoire de la structure, un des trois octets nuls est tombé sur l'octet de poids fort du short et les deux autres octets sont tombés dans la zone de bourrage.

    Quoi qu'il en soit, il s'agit très sûrement d'un comportement indéfini (je n'ai pas vérifié la norme) qui tombe en marche par miracle de l'alignement et de l'endianness.

    Il est aussi possible que sizeof(short) == sizeof(int) et alors on ne se pose même plus de question...
  • [^] # Re: Bizarre

    Posté par  . En réponse au message Probleme d'ecriture dans un STRUCT de int .. Évalué à 2.

    Bizarre... j'ai pensé à un problème de format %d avec des short... mais en ayant copié ton code + de quoi le compiler... ça passe chez moi... (pourtant ça devrais pas, le short est sur deux octets et le int sur quatre).

    Ce n'est pas parce que ton programe est tombé en marche qu'il est correct ;)
  • # scanf ?

    Posté par  . En réponse au message Probleme d'ecriture dans un STRUCT de int .. Évalué à 3.

    Bizarre, personne n'a relevé...

    L'utilisation "propre" de scanf est très difficile, car les traitements d'erreur ne sont pas simples. Si une entrée ne respecte pas le bon format, alors scanf s'arrête sans "consommer" l'entrée standard. Si tu boucles sans vérifier le bon fonctionnement de scanf, et sans "consomer" toi-même l'entrée standard quand il y a une erreur, tu causes une boucle infinie de ton programme.

    La meilleure solution est de lire une ligne complète à la fois, puis de la traiter en mémoire. Pour celà, le mieux est d'utiliser une fonction qui encapsule fgets, comme ggets ( http://cbfalconer.home.att.net/download/index.htm ), et de traiter la chaîne de caractères résultante avec sscanf (ou strto*).

    Mais que tu utilises scanf ou sscanf (ou strto*), il est nécessaire de tester le bon fonctionnement de ces fonctions. Les *scanf renvoient le nombre de conversions effectuées avec succès (et strto* possède un argument spécifique). Tu dois donc effectuer le test :

        if (scanf(" %d %d %d", &liste[i].x, &liste[i].y, &liste[i].z) == 3)
        {
            /* traitement normal */
        }
        else
        {
            /* erreur ! */
        }


    Pour plus de détails, se référer à la FAQ de comp.lang.c, question 12.20 : http://c-faq.com/stdio/scanfprobs.html .

    De plus :
    printf("\n %d %d %d", liste[i].x, liste[i].y, liste[i].z);

    La sortie standard peut être bufferisée, donc place un "\n" en fin de la chaîne de format de printf, ou appelle fflush(stdout) pour vider l'éventuel tampon.

    PS: pendant que j'y suis, gcc -Wall -Wextra -std=<ton choix> -pedantic est ton ami (remplacer -Wextra par -W pour les versions inférieures à 4, je crois).
  • [^] # Re: .

    Posté par  . En réponse au message On on pouvais m'expliquer cela, ça serait vraiment sympa .... :). Évalué à 3.

    C'aurait été sympa de préciser dès le début que la fonction en question faisait partie d'une classe "date", tu ne crois pas ? Et le "oui effectivement", ça me fait presque croire que tu savais déjà à quoi servait cette fonction...

    Je noterais juste en passant que ta classe (ou en tout cas par le bout de code que tu nous montres) ne gère pas les fuseaux horaires, les leap second, l'heure d'été, le 29 février, tout ça... Si tu n'en as pas besoin, tant mieux, sinon, fais attention...
  • # JSR 202 ?

    Posté par  . En réponse à la dépêche Java Standard Edition 6 est sorti. Évalué à 5.

    Une petite question sur le JSR 202, qui est inclus dans Java 6. D'après la page de description de ce JSR :
    Some applications that automatically generate JavaTM source code (such as JSP compilers) have reported encountering problems due to implicit size limits in the current class file format. This JSR will increase relevant limits where needed.

    Je suis déjà tombé sur cette limite, en faisant des paquets d'include statiques à partir d'une JSP : la compilation de la JSP complète échouait parce qu'une limite du format des fichiers .class était dépassée (je ne sais plus si c'est la limite de taille du bytecode d'une méthode, ou de toute la classe, mais il me semble que c'était plutôt le premier cas).

    J'avais compris (après maintes recherches infructueuses) que le JSR 202 était sensé repousser la limite en question, et donc j'attendais de savoir quand il serait implémenté. Pourtant, en lisant le PDF qui compare la spécification avant et après le JSR ( http://jcp.org/aboutJava/communityprocess/final/jsr202/index(...) ), je ne vois pas trop ce qui fait que la limitation de taille a été enlevée, ou au moins que la limite a été repoussée... Il faut dire que je ne suis pas non plus au courant de la machinerie interne des JVM au point de comprendre la spec du format des fichiers .class.

    Comme je n'ai pas trouvé d'infos ailleurs, j'en profite pour poser la question ici : est-ce que des gens plus au fait peuvent préciser l'état de la chose ?

    PS : oui, je sais, faire des include statiques dans des JSP au point de faire péter le compilateur, il y a un problème de conception à la base, et c'est le code des JSP qu'il faut corriger plutôt que le compilateur. Mais c'était juste pour savoir si la situation avait changé...
  • # Collations

    Posté par  . En réponse au message SELECT et caractères accentués dans SQLite. Évalué à 4.

    Pour comparer des textes en SQL en prenant en compte les accents, les collations sont (en général) la solution. Pour SQLLite, je viens de trouver http://www.sqlite.org/datatype3.html , paragraphe "User-defined Collation Sequences", qui me semble indiqué pour toi (je n'ai jamais utilisé SQL Lite, j'ai juste fait un google rapide...).

    SQLPro a fait un papier dessus, pour SQL Server : http://sqlpro.developpez.com/cours/sqlserver/collations/ .
  • [^] # Re: ta solution ?

    Posté par  . En réponse au message programme c qui émule la commande cat (solution trouvée hipipip houraaaaaaaaaaaa). Évalué à 2.

    Je n'y avais pas fait attention avant, mais read renvoie -1 dans certains cas d'erreur (SUSv3 précise plusieurs cas). Dans ce cas, la valeur -1 est affectée à byte_lu (qui est signé donc il n'y a pas de problème) puis, -1 étant non nul, la condittion de ton while est vraie. Le write est donc exécuté.

    Sauf que write attend un troisième argument de type size_t, et que tu lui donnes la valeur-1. size_t étant non signé, la conversion se fait modulo la valeur maximale représentable par ce type +1, soit SIZE_MAX + 1. write reçoit donc la valeur SIZE_MAX (i.e. SIZEMAX + 1 - 1). write va donc essayer de lire autant d'octets dans ton tableau pour les écrire... D'où un comportement indéfini par :
    - lecture de données non initialisées si c'est le tout premier appel à read qui plante ;
    - et débordement de tableau dans le cas quasi-certain où SIZE_MAX est supérieur à 1024.

    A part ça, question de style, je place toujours les accolades autour des blocs if, else, while... Surtout, quand le bloc d'un if est entre accolades, je mets les accolades aussi autour du bloc else (et réciproquement), même si un des blocs ne fait qu'une ligne. Je dis ça surtout par rapport à ton :
        if (fd == -1)
            perror("open: ");
        else
        {
            /* ... */
        }
  • [^] # Re: ta solution ?

    Posté par  . En réponse au message programme c qui émule la commande cat (solution trouvée hipipip houraaaaaaaaaaaa). Évalué à 4.

    While et Return n'existent pas en C (ni en POSIX), donc ton code tel que posté ne compile pas. Je suppose qu'il y a eu une erreur de copié-collé et qu'un éditeur de texte malappris aura ajouté de lui-même les majuscules.
    while ((byte_lu = read(d, tampon, 1024)) > 0)
    {
        fd = write(STDOUT_FILENO, tampon, byte_lu);
        close(d);
    } 
    Le close se trouvant dans la boucle, tu n'afficheras au plus que 1024 octets de chaque fichier. Le close devrait se trouver en-dehors de la boucle while. Sinon, ton programme fait bien ce qu'il faut (en passant, ça ne sert à rien de récupérer la valeur de retour de write si tu ne l'utilises pas).
  • [^] # Recursive make considered harmful

    Posté par  . En réponse au message makefile pour code divisé en modules. Évalué à 3.

    Le bon sens nous pousse à utiliser un Makefile par répertoire, sauf cas particuliers où il n'y a rien à compiler ou à traiter d'une manière générale dans ces dépôts.

    Ensuite, on compile en général toutes les sources et ressources d'un même module en un seul *.o local, puis le Makefile du premier niveau les assemble tous avec le main pour former l'exécutable final.

    Sauf quand les dépendances sont plus complexes que ça...
    http://www.canb.auug.org.au/~millerp/rmch/recu-make-cons-har(...) explique (en anglais) pourquoi les "make" récursifs posent problème, et y propose une solution non-récursive simple à mettre en oeuvre.
  • [^] # Re: Accolades...

    Posté par  . En réponse au message programme c qui émule la commande cat (amélioration). Évalué à 2.

    Je répond ici c'que c'est bien indenté :)
    Merci ;)

    En indentant, je voulais juste montrer des choses que d'autres ont fait remarquer, mais qui n'était pas évidentes sur un code "plat". En particulier:
    - le close() est perdu tout seul en-dehors de la boucle principale... On ne fermera donc qu'un fichier au plus ! Le close devrait être en fin du else, dans la boucle.
    - le else ne contient qu'une seule instruction ! Soit il manque les accolades autour de tout le bloc qui suit, soit on se repose sur le fait qu'il y ait un exit dans le if pour ne pas faire de else (les deux styles existent, chacun fait son choix). Mais je penche pour un oubli des accolades (ça arrive à tout le monde).
    - la boucle d'écriture while (byte_lu > 0) ne contient pas le read. Donc, comme dit par ailleurs, boucle infinie.

    Plus que l'utilisation des fonctions read et write, le fait d'avoir mal placé le close par rapport à la boucle sur les paramètres, ou le read par rapport à la boucle de lecture/écriture, montre qu'il y a qu'il faut surtout travailler sur l'algorithmique et la manière de traduire un algorithme en "pseudo-langage" (ou tout formalisme que tu as pu apprendre dans tes cours) vers un programme C.

    Ce ne sont pas des erreurs graves, loin de là ; ce genre d'exercices est justement fait pour les corriger. Mon conseil d'utiliser un éditeur qui fait de l'indentation automatique (ou un outil comme indent) est lié au fait qu'une bonne indentation (et une coloration syntaxique) du code permet de mieux voir les blocs de code, et de repérer les erreurs de ce genre.
  • [^] # Re: social ?

    Posté par  . En réponse à la dépêche L'ordinateur à 100$ devient réalité. Évalué à 10.

    Leur besoin est immense

    Là je ne suis pas convaincu. L'OLPC est un ordinateur à l'interface extrêmement simplifiée, destiné aux enfants - et probablement impropre à un usage "adulte" non trivial. Mais qui a décidé que les enfants des pays pauvres avaient besoin d'ordinateurs portables ?

    C'est presque la question que je me pose depuis la première fois que j'ai entendu parler de ce projet... Plus précisément, ce n'est pas le "qui a décidé" qui m'intéresse tant, mais: "est-ce que les enfants des pays pauvres ont tant besoin d'ordinateurs portables ?"

    Je suppose (j'espère) que le but n'est pas de distribuer des ordinateurs portables comme ça, mais de faire un suivi avec les enseignants, les familles. Bref, j'espère qu'il y a un vrai projet pédagogique derrière, destiné à s'inclure dans le mode de vie et de pensée des pays en question (i.e. qui n'impose pas ses vues en termes de contenu éducatif sur ces personnes), et dans lequel l'ordinateur portable n'est qu'un maillon d'une chaîne bien plus grande, un objet qui ne soit pas présenté aux enfants à qui on le propose/donne comme la solution à tous leurs maux, mais comme un outil qui leur permettra, avec l'aide des éducateurs, de faire des découvertes qu'ils n'auraient pas pu faire autrement (ou alors beaucoup plus diffcilement).

    A lire les pages de leur wiki http://wiki.laptop.org/go/Learning_Vision et http://wiki.laptop.org/go/Our_mission où ils expliquent un peu plus le pourquoi de leur chose, je reste un peu sceptique. Je ne doute pas de leur bonne volonté, ni de leur idéalisme que je voudrais partager. Je suis d'accord sur le fait qu'un ordinateur portable à 100 euros avec une connection internet donnant accès aux projets Gutemberg, Wikipedia et autres bibliothèques en ligne est un grand avantage, à bien moindre coût que la construction d'une bibliothèque classique (si tant est que les ressources sur internet dans la langue du pays en question sont suffisamment nombreuses). Mais l'informatique n'est qu'un outil, avec ses risques et mauvais usages, et je n'ai pas trouvé sur leur site de mention de ces risques, et de la manière dont leur projet compte les contrer (je n'ai pas le temps de rentrer dans les détails, mais http://natureinstitute.org/txt/st/details/fdnc.htm , chapitres 12 à 14, les décrit bien le genre de "risques" auquel je fais allusion. J'admets que le contexte est différent...). Peut-être n'ai-je pas assez cherché.

    Dans un tout autre contexte (et cette remarque n'a pas grand chose à voir avec ce qui précède), en France, quand on prête des ordinateurs portables à des collégiens ( http://www.altivis.fr/ORDI-35-un-ordinateur-portable.html par exemple), les profs comme les parents ne sont pas suivis, du coup les élèves (qui savent déjà pour la plupart comment utiliser ces ordinateurs) s'en servent pour jouer ou regarder des films pas de leur âge, et surtout pas à bosser, et quand le *prêt* est fini en fin d'année, on se rend compte qu'il manque des ordinateurs... La cata, quoi. Heureusement, OLPC m'a l'air beaucoup mieux organisé. Il faudrait qu'ils viennent faire un tour en France, une fois qu'ils auront fini avec le tiers-monde ;)
  • # Des précisions ?

    Posté par  . En réponse au message Pourquoi ne pas inventer un language agréable ET compilé ?. Évalué à 2.

    Pourquoi personne n'a encore inventé un nouveau langage facile à programmer contrairement au C++ (on me dira, C++ c'est facile quand même) et agréable à programmer, plus intuitif etc... Un language qui se compile en binaire et est donc rapide à l'exécution.

    Presque n'importe que langage peut être implémenté suivant les deux concepts compilé et interprété, même si chacun est plus ou moins pensé pour être implémenté d'une façon ou d'une autre (voire d'une troisième comme le Java qui peut être compilé en bytecode qui est ensuite interprété).

    Si tu pouvais préciser ce que tu entends par "langage facile à programmer (...) et agréable à programmer, plus intuitif ", ça permettrait de te mettre sur des pistes. Il y a tout plein de langages de programmations procéduraux, objets, fonctionnels, un peu des trois, un peu d'autres choses, qui utilisent plus ou moins de concepts, avec des syntaxes plus ou moins lourdes... Le choix est vaste...
  • [^] # Re: alors

    Posté par  . En réponse au message programme c qui émule la commande cat (amélioration). Évalué à 3.

    printf("%s",tampon[i]);
    Ca sert à quoi à part afficher n'importe quoi à l'ecran et eventuellement planter ?
    Bon, pour le plantage, je crois que ça mérite un peu plus d'explications (autant je préfère ne pas donner de solutions toutes faites la plupart du temps, autant certains points diffciles méritent d'être expliqués)...
    read() lit au plus N octets (*) et les place dans le tampon qu'on lui donne en paramètre. Au contraire des fonctions de la bibiothèque standard dédiées au traitement de chaînes de caractères, read() NE met PAS de caractère '\0' pour terminer la chaîne (c'est une lecture binaire). Au contraire, printf() attend une chaîne de caractères au sens C, i.e. terminée par '\0'. D'où un gros souci potentiel...

    Dans ton cas, la chaîne de format "%s" spécifie qu'on affiche le contenu de tampon[i] (supposé de type char *) sur la sortie standard, jusqu'à soit le premier caractère d'espacement, soit la fin de la chaîne. Donc :
    - si tampon[i] contient une espace, alors printf s'arrète là ;
    - sinon elle continue jusqu'à la fin de tampon[i], et essaye d'aller plus loin. Elle déborde donc le tampon et, au sens de la norme C, cause un comportement indéfini de ton programme.

    En pratique, ce comportement indéfini se traduira très probablement soit par l'affichage de données supplémentaires (qui traînent sur la pile), soit par une erreur de segmentation, soit le premier cas suivi du second.

    (*) Sans aller regarder la doc de plus près, je suppose que c'est le read de POSIX. Dans ce cas on a de plus CHAR_BIT == 8, et on peut donc traduire joyeusement "byte" par "octet" sans se soucier d'architectures ésotériques comme certains mainframes ou DSP.