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 :

Les pointeurs en C!


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Les pointeurs en C!
    Bonjour tout le monde,

    Je débute en C et après avoir tester de nombreux langages de programmation pour traiter des gros fichiers on m'a dit que le langage C était le mieux et le plus rapide.
    Mon problème est que je dois transposer une fichier de 818155 lignes et 71 colonnes en un fichier de 71 lignes et 818155 colonnes.
    Je suis parvenue a faire le script en C et il marche pour de petits fichiers mais pour mon fichier de 818155 lignes il plante et je pense que c'est une question de mémoire.
    On m'a dit d'utiliser des pointeurs pour surmonter ce problèmes mais je n'y arrive pas et je ne comprend pas.
    Est-ce que quelqu'un peut m'aider a utiliser les pointeurs dans mon script?

    Voila mon script qui transpose mon fichier: ll est mon nombre total de ligne et nb_var mon nombre total de colonnes; entree est mon fichier d'entree et sortie est mon fichier en sortie

    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
    30
    31
     char tab[ll][nb_var][50];
     int ligne = 0;
     int colonne = 0;
     int caractere = 0;
     int lin = 0;
     int col = 0;
     int car = 0;
     char carac;
     
     while ((carac=fgetc(entree)) != EOF)
     {
      if (carac == '\n') { tab[ligne][colonne][caractere] = '\0'; ligne = ligne + 1; colonne = 0; caractere = 0; }
      else if (carac == '\t') { tab[ligne][colonne][caractere] = '\0'; colonne = colonne + 1; caractere = 0; }
      else { tab[ligne][colonne][caractere] = carac; caractere = caractere + 1; }
     }
     
     for(col=0; col < nb_var; col++)
     {
      for(lin=0; lin < ll; lin++)
      {
       while (tab[lin][col][car] != '\0')
       {
        fprintf(sortie,"%c",tab[lin][col][car]);
        car = car + 1;
       }
       fprintf(sortie,"\t");
       car = 0;
      }
      fprintf(sortie,"\n");
      car = 0;
     }
    Je stocke mon fichier dans un tableau a 3 dimensions puis je lis se tableau à l'envers pour transposer dans mon fichier de sortie.
    Il faudrait que j'utilise un pointeur de tableau (je crois) mais je ne sait pas comment faire.

    Est-ce que quelqu'un peut m'aider?

    Merci par avance.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    71 lignes * 818,155 colonnes * 50 caractères ASCII étendu, ça donne 2,904,450,250 octets, soit plus de 2GO (2,147,483,648). Sur un Windows, cela ne tiendrait pas dans la mémoire "utilisateur" à laquelle un processus 32 bits non-étendu a droit.

    Par contre, un processus 64 bits (ou un processus 32 bits étendu sur une plate-forme 64 bits) pourrait travailler sur une telle quantité en mémoire.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  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 691
    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 691
    Points : 30 988
    Points
    30 988
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par July09 Voir le message
    On m'a dit d'utiliser des pointeurs pour surmonter ce problèmes mais je n'y arrive pas et je ne comprend pas.
    ...Il faudrait que j'utilise un pointeur de tableau (je crois) mais je ne sait pas comment faire.
    Bonjour

    Je pense que tu n'as pas bien compris pourquoi on t'a parlé de pointeur...

    En fait, tu as défini ton tableau dans la pile (la zone mémoire destinée aux variables "usuelles"). C'est le cas de toutes les variables qu'on définit dans un bloc (les accolades) ou les paramètres de fonction. Or la pile est limitée.
    En revanche, si tu utilises un pointeur qui récupère une zone mémoire allouée par malloc(), alors cette zone mémoire sera allouée dans un autre endroit: le "tas". Et le tas est bien plus gros. je viens de tester, un malloc de 71 * 818,155 caractères fonctionne (alors qu'un tableau de 71 * 818,155 caractères me met un segfault).

    Mais bien entendu, avant de courir il faut savoir marcher. Et donc apprendre au minimum
    • ce qu'est un pointeur
    • sa relation avec les tableaux
    • l'allocation mémoire


    PS: ou alors tu définis ton tableau en "global" (en dehors de tout bloc) et dans ce cas ça ira aussi. Si c'est vraiment pour un besoin ponctuel ça fonctionnera mais si tu prends l'habitude d'user de cette solution de facilité, tu t'en mordras les doigts un jour où l'autre (et plus ce sera tard plus la morsure sera douloureuse)...
    PS2: au fait, pourquoi est-ce que tu définis un tableau de 71 * 818,155 * 50 caractères ? Est-ce que tu veux stocker 50 fichiers en même temps ???
    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
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    PS2: au fait, pourquoi est-ce que tu définis un tableau de 71 * 818,155 * 50 caractères ? Est-ce que tu veux stocker 50 fichiers en même temps ???
    Je pense que dans sa définition, chaque "case" est un buffer de 50 caractères.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Nouveau Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je pense que dans sa définition, chaque "case" est un buffer de 50 caractères.

    Oui c'est ça en fait chaque caractère est stocké dans une case et mes variables (colonnes) vont de 2 à 50 caractères.

  6. #6
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour
    En plus de ce qui a été dit, peux-tu nous dire concrètement ce que ton fichier contient ?
    Et d'après ce que moi j'ai compris, tu comptes traite l'intégralité du fichier à travers les pointeurs donc, traiter tous les informations en mémoire afin de les transposer par la suite.
    Au lieu de se pencher sur comment traiter l'ensemble du fichier en mémoire pourquoi ne pas tout simplement se pencher sur l'accès au fichier lui-même en utilisant un type d'accès indexé qui est particulièrement adapté pour le traitement de ce genre de fichier en clair, une combinaison d'accès rapide notamment direct au fichier lui-même et un accès séquentiel.
    Au final, ce type d'accès va nous permettre de traiter le fichier avec une certaine souplesse car ce choix ne pas dépend du fichier lui-même mais plutôt de la façon dont on t'il doit être traité par l'ordinateur.
    (Exemple en pourrait lire un fichier en mode binaire et ainsi donc lire les octets de son choix ou tout le fichier.)
    quand pensez-vous ?
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  7. #7
    Nouveau Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Je pense que tu n'as pas bien compris pourquoi on t'a parlé de pointeur...

    En fait, tu as défini ton tableau dans la pile (la zone mémoire destinée aux variables "usuelles"). C'est le cas de toutes les variables qu'on définit dans un bloc (les accolades) ou les paramètres de fonction. Or la pile est limitée.
    En revanche, si tu utilises un pointeur qui récupère une zone mémoire allouée par malloc(), alors cette zone mémoire sera allouée dans un autre endroit: le "tas". Et le tas est bien plus gros. je viens de tester, un malloc de 71 * 818,155 caractères fonctionne (alors qu'un tableau de 71 * 818,155 caractères me met un segfault).

    Mais bien entendu, avant de courir il faut savoir marcher. Et donc apprendre au minimum
    • ce qu'est un pointeur
    • sa relation avec les tableaux
    • l'allocation mémoire


    PS: ou alors tu définis ton tableau en "global" (en dehors de tout bloc) et dans ce cas ça ira aussi. Si c'est vraiment pour un besoin ponctuel ça fonctionnera mais si tu prends l'habitude d'user de cette solution de facilité, tu t'en mordras les doigts un jour où l'autre (et plus ce sera tard plus la morsure sera douloureuse)...
    PS2: au fait, pourquoi est-ce que tu définis un tableau de 71 * 818,155 * 50 caractères ? Est-ce que tu veux stocker 50 fichiers en même temps ???
    Merci pour ta réponse.
    J'ai pas mal cherché d'explication sur les pointeurs avce de beaux schémas et je comprend le sens mais c'est vrai que j'ai du mal a voir le lien avec les tableaux et je ne sais pas les utiliser car je me perds entre les * et &. J'ai lu que le nom d'un tableau par définition est un pointeur. Mais j'ai du mal avec les tableaux à faire la différence entre adresse des blocs de mon tableau et valeurs réelles !

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par July09 Voir le message
    J'ai lu que le nom d'un tableau par définition est un pointeur.
    C'est hélas faux. Le nom d'un tableau reste une variable de type tableau, mais peut être convertie en un pointeur vers son premier élément.
    Ainsi, si j'écris int tab[10];, je peux initialiser un pointeur avec int* ptr = tab;, qui correspond à int* ptr = &tab[0];.


    On voit les limites du raisonnement "tableau==pointeur" dès qu'on utilise des tableaux à plusieurs dimensions. En effet, si l'on initialise un pointeur avec le nom d'un tableau 2D, le pointeur obtenu n'est pas vraiment un pointeur d'éléments, mais un pointeur de tableau 1D.

    Et les tableaux à longueur variable apportés par le standard C99 causent encore plus de confusion de ce côté-là.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 377
    Points : 23 663
    Points
    23 663
    Par défaut
    Citation Envoyé par July09 Voir le message
    J'ai pas mal cherché d'explication sur les pointeurs avce de beaux schémas et je comprend le sens mais c'est vrai que j'ai du mal a voir le lien avec les tableaux et je ne sais pas les utiliser car je me perds entre les * et &. J'ai lu que le nom d'un tableau par définition est un pointeur. Mais j'ai du mal avec les tableaux à faire la différence entre adresse des blocs de mon tableau et valeurs réelles !
    J'ai eu à traiter exactement le même problème que toi il y a quelques années, dans un centre de recherche en génétique. On y était habitué à traiter des très larges quantités de données mais on y voyait aussi des ex-étudiants en bioinfo chez qui la biologie moléculaire était la discipline principale et l'informatique « une couche de plus », en Perl ou en Python, pour traiter leurs fichiers de chiffres. À l'époque, j'avais mis en ligne (sur des serveurs Unix centralisés) un programme « transpose » qui servait à ça et qui faisait usage de mmap64() quand c'était possible.

    En réalité, ce n'est pas très difficile : un pointeur est une valeur qui correspond à une adresse en mémoire, telle que manipulée par le micro-processeur (en principe). Et par extension, c'est aussi le nom que l'on donne à la variable qui la transporte puisque c'est à partir de cette variable que l'on va indexer ce qu'elle pointe, mais cela est vrai avec tous les types : quand on écrit « int x », par exemple, on dit que « x est un entier » parce que la valeur qu'elle transporte est un entier.

    C'est une réalité depuis que l'on a inventé les micro-processeurs, et bien avant qu'on les formalise officiellement. Du coup, c'est une très bonne chose de voir comment le C formalise ses types de données et de se conformer à ces définitions si l'on veut faire du code professionnel, mais c'est tout sauf intuitif. Ceux qui ont fait de l'assembleur, voire même du Basic (avec Peek et Poke) savent de quoi je parle : comme bien souvent en sciences et techniques, c'est clair à partir du moment où on sait déjà de quoi on parle.

    Par contre, en ce qui concerne ton cas particulier : un fichier de plus de 2 Go, c'est énorme ! Il faut donc concevoir un programme qui tienne compte des aspects logistiques, et pas de considérer qu'une matrice de 800.000 lignes est le même objet mathématique qu'un matrice 3×3, que tout se passe au point de vue algorithmique, que le compilateur va finalement tout optimiser pour nous et qu'au final, si ça ne marche pas, c'est que la machine n'est pas assez puissante. Il faut revenir un peu aux traitements asynchrones.

    Si ce genre de transposition est ponctuelle dans ton activité, et que tu as 800.000 lignes de 71 colonnes, alors je ferais 71 passes sur le même fichier en lisant à chaque fois la ligne en cours, en extrayant de celle-ci la colonne qui m'intéresse et en allant concaténer sa valeur à la suite du fichier de sortie. Dès que j'arrive à la fin, j'ajoute un retour à la ligne au fichier de sortie et je recommence. En t'y prenant de cette façon, tu pourrais écrire directement ton programme en ShellScript si tu le souhaitais, et ton programme (en C ou n'importe quel langage) n'aurait besoin que de 64 ko de mémoire pour être efficace.

  10. #10
    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
    J'ai lu que le nom d'un tableau par définition est un pointeur.
    Il faut être plus précis pour comprendre : la question est "qu'est-ce que représente l'identificateur associé à un tableau ?"
    Cela dépend du contexte :

    - Si cet identificateur est opérande de l'opérateur unaire & (adresse de) ou sizeof alors il représente le tableau.

    - Sinon, il représente l'adresse du premier élément du tableau. Même dans ce cas ce n'est pas un objet pointeur mais une valeur d'adresse (comme exemple de valeur d'adresse on a NULL) autrement dit quelque chose qu'on peut stocker dans un (objet) pointeur

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char tab [10];      // un tableau
    int i;              // un entier
    char * p;           // un objet pointeur de type "adresse d'un char"
    char (*pt)[10] ;    // un objet pointeur de type "adresse d'un tableau de 10 char"
     
    pt= &tab;            // ici tab représente le tableau (d'où le type correspondant de pt)
    i= sizeof tab        // ici aussi et sizeof tab vaut 10
    p= tab;              // ici tab représente l'adresse du premier élément du tableau
    i = tab[0];          // ici aussi
    fonc(tab);           // ici aussi
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 691
    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 691
    Points : 30 988
    Points
    30 988
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par July09 Voir le message
    Oui c'est ça en fait chaque caractère est stocké dans une case et mes variables (colonnes) vont de 2 à 50 caractères.
    Ok, je vois donc ça comme une espèce de table comme ceci...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a1	a2	a3
    b1	b2	b3
    c1	c2	c3
    d1	d2	d3
    e1	e2	e3
    où chaque colonne est séparée de la suivante par une tabulation.

    Quoi qu'il arrive, tu ne peux pas te mettre dans la tête de stocker tout ton fichier en mémoire. Comme le dit Obsidian, on ne peut pas considérer un 800000x70x50 de la même façon qu'un 2x3x5. Un ordinateur a lui-aussi ses limites.

    Ceci dit, ce n'est pas très compliqué de faire sans. Si par exemple je lis chaque ligne et que j'extraits puis écris la première colonne, puis que je reviens au début pour lire chaque ligne en extrayant maintenant la seconde colonne, puis etc etc, tu peux alors écrire un second fichier qui sera la rotation du premier.

    J'ai rapidement écrit ce code

    Code c : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define NCOL		(3)
    #define NCAR		(50)
     
    void write_col(FILE *f1, FILE *f2, unsigned short col, char *delim)
    {
    	char ligne[NCOL * NCAR + 1];	// Ncol de Ncar + 1 pour le '\0'
    	char *work;
    	char *extract;
    	unsigned short i;
     
    	// Rembobinage initial
    	rewind(f1);
     
    	// Lecture de chaque ligne
    	while (fgets(ligne, NCOL * NCAR + 1, f1) != NULL)
    	{
    		// Suppression du '\n'
    		if ((extract=strchr(ligne, '\n')) != NULL)
    			*extract='\0';
     
    		// Extraction de la colonne demandée sur le délimiteur demandé
    		for (i=0; i < col; i++)
    			extract=strtok_r(i != 0 ?NULL :ligne, delim, &work);
     
    		// Ecriture de la colonne extraite
    		fprintf(f2, "%s%s", extract, delim);
    	}
     
    	// La fin de la ligne
    	fputc('\n', f2);
    }
     
    int main()
    {
    	FILE *f1;
    	FILE *f2;
    	unsigned short i;
     
    	f1=fopen("fic1", "r");
    	f2=fopen("fic2", "w");
    	for (i=1; i <= NCOL; i++)
    		write_col(f1, f2, i, "\t");
    	fclose(f1);
    	fclose(f2);
    }

    Et voici ce que ça donne sur l'exemple montré plus haut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a1	b1	c1	d1	e1	
    a2	b2	c2	d2	e2	
    a3	b3	c3	d3	e3
    Comme tu peux le voir, je ne demande à ce code que la capacité de mémoriser une seule ligne donc pas besoin de grosse quantité de mémoire (pour toi ça fera 71x50+1 soit 3551 caractères ce qui est largement dans ses capacités). Une petite difficulté pour le comprendre quand j'utilise strtok_r(). Cette fonction a pour but de découper une chaine sur un délimiteur. A son premier appel (donc quand "i" vaut 0) il faut lui passer la chaine à découper et aux appels suivants il faut lui passer NULL d'où le i != 0 ?NULL :ligne. Et il faut aussi lui passer l'adresse d'un pointeur qu'elle utilisera pour stocker le travail en cours (pour pouvoir repartir du même point aux appels suivants) d'où le &work, work étant alors un pointeur sur un caractère.

    Et je n'ai utilisé les pointeurs que quand je ne pouvais pas faire autrement. Son seul seul défaut c'est qu'il écrit le délimiteur (ici une tabulation) de façon systématique donc y compris à la fin de chaque ligne. Je pourrais l'éviter mais ça l'alourdirait de façon trop complexe (faudrait lire un caractère en plus pour voir si on a atteint la fin du fichier puis revenir en arrière, bref...).

    Je viens de l'utiliser sur un fichier de 255000 lignes et il a tout digéré sans soucis (j'ai mis plus de temps à afficher le fichier final que ce que mon code a mis pour le créer). Tu peux essayer de t'en inspirer pour ton problème...

    [edit]Bah non, en fait régler le soucis du délimiteur placé de façon systématique n'est finalement pas si complexe que ça. Suffit de terminer la fonction ainsi
    Code c : 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
    		// Extraction de la colonne demandée
    		for (i=0; i < col; i++)
    			extract=strtok_r(i ?NULL :ligne, delim, &work);
     
    		// Ecriture de la colonne extraite
    		fputs(extract, f2);
     
    		// Lecture en plus pour détecter EOF
    		if (fgetc(f1) != EOF)
    		{
    			// Ecriture du délimiteur
    			fputs(delim, f2);
     
    			// On n'a pas atteint EOF, on revient en arrière
    			fseek(f1, -1, SEEK_CUR);
    		}
    		else
    		{
    			// Ecriture de la fin de ligne
    			fputc('\n', f2);
    		}
    	}
    }
    Et si ça se trouve, ça doit même accélérer la fonction (fprintf étant super lent, dans cette version je l'ai éliminé).

    Donc une règle c'est que la mémoire coûte cher (et même avec un pointeur alloué ça peut ne pas suffire) et si t'as déjà les informations stockées quelque part (un fichier), il te faut alors trouver un moyen pour utiliser cette source et découper ton travail en tâches successives afin de ne mémoriser que le minimum nécessaire à la tâche en cours. Ceci dit, ici c'était facile. Il y a beaucoup de lignes certes mais comme je n'en mémorise qu'une seule et qu'elle est petite... Si maintenant il fallait transformer un fichier de 3 lignes de 800000 colonnes, là ce serait alors une autre façon de découper le travail...
    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]

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 691
    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 691
    Points : 30 988
    Points
    30 988
    Billets dans le blog
    1
    Par défaut
    Dommage, ce topic semble abandonné par son auteur alors que moi il m'intéressait.

    Je me suis amusé à étudier le problème d'un point de vue absolu: un fichier dont on ne connait pas à l'avance le nombre de lignes, ni le nombre de colonnes, ni la taille d'une colonne. La seule chose qu'on ait c'est son séparateur (un csv quoi). Et donc écrire le code qui transforme un tel fichier de x lignes, y colonnes en y lignes, x colonnes.

    A ce niveau là, on ne peut pas compter sur la mémorisation d'une ligne, ni même d'une colonne. La seule chose qu'on ait, c'est la lecture du fichier caractère par caractère. J'ai aussi enlevé ce fgetc+fseek pour détecter la fin (trop long) et l'ait remplacé par une mémorisation initiale de la taille du fichier.
    Voilà ce que ça donne

    Code c : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #include <stdio.h>
     
    // Taille fichier
    unsigned long size_fic(FILE *f)
    {
    	unsigned long size;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=ftell(f);
     
    	// Positionnement fin fichier et récupération taille
    	fseek(f, 0, SEEK_END);
    	size=ftell(f);
     
    	// Repositionnement position initiale
    	fseek(f, pos, SEEK_SET);
     
    	// Renvoi taille trouvée
    	return size;
    }
     
    // Compteur de colonnes
    unsigned long cpt_col(FILE *f, char delim)
    {
    	int c;
    	unsigned long col;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=ftell(f);
     
    	// Rembobinage initial
    	rewind(f);
     
    	// Lecture du fichier
    	col=0;
    	while ((c=fgetc(f)) != EOF)
    	{
    		// Si on atteint un délimiteur de colonne ou une fin de ligne
    		if (c == delim || c == '\n')
    		{
    			// Une colonne de plus
    			col++;
     
    			// Si on atteint la fin de ligne
    			if (c == '\n')
    				// On a fini de compter
    				break;
    		}
    	}
     
    	// Repositionnement position initiale
    	fseek(f, pos, SEEK_SET);
     
    	// Renvoi nb colonnes trouvées
    	return col;
    }
     
    // Extraction et écriture d'une colonne X
    void write_col(
    	FILE *f1,
    	FILE *f2,
    	unsigned long col,
    	char delim,
    	unsigned long size)
    {
    	int c;
    	unsigned long nzone;
    	unsigned long pos;
     
    	// Rembobinage initial
    	rewind(f1);
     
    	// Itération sur le nb de caractères du fichier
    	nzone=1;
    	for (pos=1; pos <= size; pos++)
    	{
    		// Lecture caractère
    		c=fgetc(f1);
     
    		// Si on a atteint un délimiteur de zone
    		if (c == delim || c == '\n')
    		{
    			// Le n° de zone augmente
    			nzone++;
     
    			// Si on atteint la fin de la ligne
    			if (c == '\n')
    			{
    				// Si on n'est pas à la fin du fichier
    				if (pos != size)
    				{
    					// Ecriture délimiteur
    					fputc(delim, f2);
     
    					// Réinitialisation zone pour ligne suivante
    					nzone=1;
    				}
    				else
    					// Ecriture fin de ligne
    					fputc('\n', f2);
    			}
     
    			// Il ne faut pas stocker le délimiteur
    			continue;
    		}
     
    		// Si le n° de zone correspond à la colonne demandée
    		if (nzone == col)
    			// On écrit le caractère dans le fichier
    			fputc(c, f2);
    	}
    }
     
    int main(int argc, char *argv[])
    {
    	FILE *f1;
    	FILE *f2;
    	unsigned long i;
    	unsigned long ncol;
    	unsigned long sz_fic;
     
    	f1=fopen(argv[1], "r");
    	f2=fopen(argv[2], "w");
    	sz_fic=size_fic(f1);
    	ncol=cpt_col(f1, '\t');
    	for (i=1; i <= ncol; i++)
    		write_col(f1, f2, i, '\t', sz_fic);
    	fclose(f1);
    	fclose(f2);
    }

    J'ai testé sur un fichier de 1000000 de lignes de 3 colonnes. En quelques secondes j'ai eu un second fichier de 3 lignes à 1000000 de colonnes. Toutefois il lui a fallu près de 16h pour traiter ce second fichier et en construire un 3° (identique au premier). Et j'ai pas trop d'idée pour accélérer ce traitement. En effet, quand la colonne X de la ligne n a été écrite, lui lui faut parcourir les 999999 autres pour arriver à la colonne X de la ligne n+1 et ça, ça se fait caractère par caractère. Peut-être remplacer fopen()+fgetc() par open()+read() et traiter le tampon lu mais j'en doute, la lecture fgetc() se faisant elle-aussi au travers d'un tampon interne...
    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]

  13. #13
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    @Sve@r: En effet, sujet intéressant donc je me permets d'y apporter ma contribution ! Donc je pense que le mieux dans ce genre de cas, c'est de mapper le fichier en mémoire. Cependant, si ce n'est pas possible, il faut limiter au maximum les fonctions de lecture/écriture ! Donc fgetc me semble vraiment pas être une solution viable pour ça... Le mieux serait de créer un énorme buffer et de réécrire par dessus (pas de le réallouer donc) pour pouvoir faire les "opérations" dessus.

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 691
    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 691
    Points : 30 988
    Points
    30 988
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par imperio Voir le message
    Donc fgetc me semble vraiment pas être une solution viable pour ça... Le mieux serait de créer un énorme buffer et de réécrire par dessus (pas de le réallouer donc) pour pouvoir faire les "opérations" dessus.
    Tout d'abord, voici les temps de traitement de ma solution à base de fgetc() sur un fichier de 10000 lignes (3 colonnes de 2 caractères par ligne)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ~/tmp$ time ./rotate1 fic0 fic11
     
    real	0m0.077s
    user	0m0.004s
    sys	0m0.008s
    ~/tmp$ time ./rotate1 fic11 fic12
     
    real	0m6.444s
    user	0m6.220s
    sys	0m0.128s
    ~/tmp$ cmp fic12 fic0
    ~/tmp$
    Ensuite j'ai effectivement pensé à un tampon de lecture, la lecture se faisant à base de open/read comme j'en avais parlé
    Code c : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    #include <stdio.h>
    #include <fcntl.h>
     
    #define SZ_TAMPON		(32000)
     
    // Taille fichier
    unsigned long size_fic(int f)
    {
    	unsigned long size;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=lseek(f, 0, SEEK_CUR);
     
    	// Positionnement fin fichier et récupération taille
    	size=lseek(f, 0, SEEK_END);
     
    	// Repositionnement position initiale
    	lseek(f, pos, SEEK_SET);
     
    	// Renvoi taille trouvée
    	return size;
    }
     
    // Compteur de colonnes
    unsigned long cpt_col(int f, char delim)
    {
    	char c;
    	unsigned long col;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=lseek(f, 0, SEEK_CUR);
     
    	// Rembobinage initial
    	lseek(f, 0, SEEK_SET);
     
    	// Lecture du fichier
    	col=0;
    	while (read(f, &c, 1) > 0)
    	{
    		// Si on atteint un délimiteur de colonne ou une fin de ligne
    		if (c == delim || c == '\n')
    		{
    			// Une colonne de plus
    			col++;
     
    			// Si on atteint la fin de ligne
    			if (c == '\n')
    				// On a fini de compter
    				break;
    		}
    	}
     
    	// Repositionnement position initiale
    	lseek(f, pos, SEEK_SET);
     
    	// Renvoi nb colonnes trouvées
    	return col;
    }
     
    // Extraction et écriture d'une colonne X
    void write_col(
    	int f1,
    	int f2,
    	unsigned long col,
    	char delim,
    	unsigned long size)
    {
    	typedef struct {
    		char zone[SZ_TAMPON];
    		char *pt;
    		int nb;
    		int i;
    	} t_buf;
    	t_buf lire;
    	t_buf ecrire;
    	unsigned long nzone;
    	unsigned long pos;
     
    	// Rembobinage initial
    	lseek(f1, 0, SEEK_SET);
     
    	// Itération sur le nb de caractères du fichier
    	nzone=1;
    	pos=0;
    	while (pos < size)
    	{
    		// Lecture zone
    		lire.nb=read(f1, lire.zone, SZ_TAMPON);
     
    		// Initialisation zone à écrire
    		ecrire.pt=ecrire.zone;
    		ecrire.nb=0;
     
    		// Traitement de la zone lue
    		for (lire.pt=lire.zone, lire.i=0; lire.i < lire.nb; lire.i++, lire.pt++)
    		{
    			// La position s'incrémente
    			pos++;
     
    			// Si on a atteint un délimiteur de zone
    			if (*lire.pt == delim || *lire.pt == '\n')
    			{
    				// Le n° de zone augmente
    				nzone++;
     
    				// Si on atteint la fin de la ligne
    				if (*lire.pt == '\n')
    				{
    					// Si on n'est pas à la fin du fichier
    					if (pos != size)
    					{
    						// Stockage délimiteur
    						*ecrire.pt++=delim;
     
    						// Réinitialisation zone pour ligne suivante
    						nzone=1;
    					}
    					else
    						// Stockage fin de ligne
    						*ecrire.pt++='\n';
     
    					// On a un caractère de plus
    					ecrire.nb++;
    				}
     
    				// Il ne faut pas stocker le délimiteur
    				continue;
    			}
     
    			// Si le n° de zone correspond à la colonne demandée
    			if (nzone == col)
    			{
    				// On stocke le caractère
    				*ecrire.pt++=*lire.pt;
    				ecrire.nb++;
    			}
    		}
     
    		// On écrit la zone à écrire
    		write(f2, ecrire.zone, ecrire.nb);
    	}
    }
     
    int main(int argc, char *argv[])
    {
    	int f1;
    	int f2;
    	unsigned long i;
    	unsigned long ncol;
    	unsigned long sz_fic;
     
    	f1=open(argv[1], O_RDONLY);
    	f2=open(argv[2], O_WRONLY|O_TRUNC|O_CREAT, 0644);
    	sz_fic=size_fic(f1);
    	ncol=cpt_col(f1, '\t');
    	for (i=1; i <= ncol; i++)
    		write_col(f1, f2, i, '\t', sz_fic);
    	close(f1);
    	close(f2);
    }

    Voici les temps de traitement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ~/tmp$ time ./rotate2 fic0 fic21
     
    real	0m0.041s
    user	0m0.000s
    sys	0m0.000s
    ~/tmp$ time ./rotate2 fic21 fic22
     
    real	0m37.610s
    user	0m0.140s
    sys	0m4.964s
    ~/tmp$ cmp fic22 fic0
    ~/tmp$
    37 secondes au lieu de 6, c'est clairement à abandonner.
    Ensuite j'ai remplacé dans ce code open+read par fopen+fread
    Code c : 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    #include <stdio.h>
     
    #define SZ_TAMPON		(32000)
     
    // Taille fichier
    unsigned long size_fic(FILE *f)
    {
    	unsigned long size;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=fseek(f, 0, SEEK_CUR);
     
    	// Positionnement fin fichier et récupération taille
    	fseek(f, 0, SEEK_END);
    	size=ftell(f);
     
    	// Repositionnement position initiale
    	fseek(f, pos, SEEK_SET);
     
    	// Renvoi taille trouvée
    	return size;
    }
     
    // Compteur de colonnes
    unsigned long cpt_col(FILE *f, char delim)
    {
    	char c;
    	unsigned long col;
    	unsigned long pos;
     
    	// Mémorisation position courante
    	pos=ftell(f);
     
    	// Rembobinage initial
    	rewind(f);
     
    	// Lecture du fichier
    	col=0;
    	while ((c=fgetc(f)) != EOF)
    	{
    		// Si on atteint un délimiteur de colonne ou une fin de ligne
    		if (c == delim || c == '\n')
    		{
    			// Une colonne de plus
    			col++;
     
    			// Si on atteint la fin de ligne
    			if (c == '\n')
    				// On a fini de compter
    				break;
    		}
    	}
     
    	// Repositionnement position initiale
    	fseek(f, pos, SEEK_SET);
     
    	// Renvoi nb colonnes trouvées
    	return col;
    }
     
    // Extraction et écriture d'une colonne X
    void write_col(
    	FILE *f1,
    	FILE *f2,
    	unsigned long col,
    	char delim,
    	unsigned long size)
    {
    	typedef struct {
    		char zone[SZ_TAMPON];
    		char *pt;
    		int nb;
    		int i;
    	} t_buf;
    	t_buf lire;
    	t_buf ecrire;
    	unsigned long nzone;
    	unsigned long pos;
     
    	// Rembobinage initial
    	rewind(f1);
     
    	// Itération sur le nb de caractères du fichier
    	nzone=1;
    	pos=0;
    	while (pos < size)
    	{
    		// Lecture zone
    		lire.nb=fread(lire.zone, sizeof(char), SZ_TAMPON, f1);
     
    		// Initialisation zone à écrire
    		ecrire.pt=ecrire.zone;
    		ecrire.nb=0;
     
    		// Traitement de la zone lue
    		for (lire.pt=lire.zone, lire.i=0; lire.i < lire.nb; lire.i++, lire.pt++)
    		{
    			// La position s'incrémente
    			pos++;
     
    			// Si on a atteint un délimiteur de zone
    			if (*lire.pt == delim || *lire.pt == '\n')
    			{
    				// Le n° de zone augmente
    				nzone++;
     
    				// Si on atteint la fin de la ligne
    				if (*lire.pt == '\n')
    				{
    					// Si on n'est pas à la fin du fichier
    					if (pos != size)
    					{
    						// Stockage délimiteur
    						*ecrire.pt++=delim;
     
    						// Réinitialisation zone pour ligne suivante
    						nzone=1;
    					}
    					else
    						// Stockage fin de ligne
    						*ecrire.pt++='\n';
     
    					// On a un caractère de plus
    					ecrire.nb++;
    				}
     
    				// Il ne faut pas stocker le délimiteur
    				continue;
    			}
     
    			// Si le n° de zone correspond à la colonne demandée
    			if (nzone == col)
    			{
    				// On stocke le caractère
    				*ecrire.pt++=*lire.pt;
    				ecrire.nb++;
    			}
    		}
     
    		// On écrit la zone à écrire
    		fwrite(ecrire.zone, sizeof(char), ecrire.nb, f2);
    	}
    }
     
    int main(int argc, char *argv[])
    {
    	FILE *f1;
    	FILE *f2;
    	unsigned long i;
    	unsigned long ncol;
    	unsigned long sz_fic;
     
    	f1=fopen(argv[1], "r");
    	f2=fopen(argv[2], "w");
    	sz_fic=size_fic(f1);
    	ncol=cpt_col(f1, '\t');
    	for (i=1; i <= ncol; i++)
    		write_col(f1, f2, i, '\t', sz_fic);
    	fclose(f1);
    	fclose(f2);
    }

    Et voici les temps de traitement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    moi@virtualux:~/tmp$ time ./rotate3 fic0 fic31
     
    real	0m0.074s
    user	0m0.004s
    sys	0m0.000s
    ~/tmp$ time ./rotate3 fic31 fic32
     
    real	0m2.228s
    user	0m2.076s
    sys	0m0.084s
    ~/tmp$ cmp fic32 fic0
    ~/tmp$
    Cette fois on a 2 secondes au lieu de 6. Cette 3° solution semble donc très prometteuse. Je vais la lancer sur mon fichier de 1000000 de lignes voir le temps que ça prendra. Déjà voici le temps que ça a mis pour générer le fichier intermédiaire (3 lignes de 1000000 de colonnes)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ~/tmp$ wc -l fic0
    1000000 fic0
    ~/tmp$ time ./rotate1 fic0 fic11
     
    real	0m3.135s
    user	0m0.012s
    sys	0m0.480s
    ~/tmp$ time ./rotate3 fic0 fic31
     
    real	0m2.246s
    user	0m0.000s
    sys	0m0.248s
    ~/tmp$ cmp fic11 fic31
    ~/tmp$
    Si vraiment le temps de traitement est divisé par 3 ça devrait mettre un peu moins de 5h. Je reviendrai peut-être donner le résultat ce soir (sinon ce sera demain).

    [edit ... (demain)...] ok, voici les résultats
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ~/tmp$ time ./rotate3 fic31 fic32
     
    real	373m14.669s
    user	348m56.284s
    sys	23m22.312s
    ~/tmp$ cmp fic32 fic0
    ~/tmp$
    Un peu plus de 6h au lieu de 16 avec le fgetc() !!!
    Comme quoi, quand on prends les outils appropriés et qu'on jongle avec la mémoire dispo associée au reste...
    PS1: Je pourrais modifier le SZ_TAMPON (je viens de le passer à 512000) mais les écarts sur le fichier de 10000 lignes ne me semblent pas très significatif...
    PS2: le soucis principal étant la lecture, je ne suis pas certain que bufferiser l'écriture soit super utile mais bon, ça ne coûte (presque) rien
    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]

  15. #15
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Wo ! Je n'aurais jamais pensé que fopen et fread seraient plus rapides open et read. Je me demande d'où vient une différence aussi grosse...

    Sinon j'ai eu une autre idée : tu sépares ton fichier en plusieurs petits et pendant que tu traites un fichier, t'en mappes un autre en mémoire (threading). Ça peut peut-être donner un gain de temps intéressant. Je pense que ce qui doit prendre le plus de temps est la lecture donc si on mappe en mémoire pendant qu'on traite un autre fichier, ça permettrait de ronger pas mal de temps là-dessus ! Qu'en penses-tu ? Je veux bien les résultats si t'essaie !

    PS: pour les fichiers temporaires, je viens de penser la fonction tmpfile. Ça pourrait être intéressant à essayer aussi.

Discussions similaires

  1. [LG]Les pointeurs: Forme en "Anneaux"
    Par k o D dans le forum Langage
    Réponses: 4
    Dernier message: 20/10/2004, 07h29
  2. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  3. [TTreeView] Problème avec les pointeurs d'objet
    Par BlackWood dans le forum Composants VCL
    Réponses: 2
    Dernier message: 02/07/2004, 14h31
  4. pointeurs, toujours les pointeurs :/
    Par giviz dans le forum C
    Réponses: 16
    Dernier message: 08/10/2003, 15h02
  5. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50

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