Voici mon problème : Je récupère des informations d'un fichier texte grâce à une recherche de chaine de caractères. Le problème est que si la chaine existe plusieurs fois, ça va me l'afficher plusieurs fois aussi... Comment faire pour ne l'afficher qu'une seule fois ?
Voici mon code :
/*
VERSION 3 : - SELECTION DES INFORMATIONS UTILES (FAILING PROGRAM)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TAILLE_MAX 136
char * binstr(char * bin, int lngmax, const char * str){
int lngstr = strlen(str);
char * ret = NULL;
for(int i=0; i<lngmax-lngstr; i++){
if(memcmp(bin+i,str,lngstr)==0){
ret=bin+i;
break;
}
}
return ret;
}
int main(int argc, char *argv[])
{
char * search[10]; //chaine à rechercher
search[0] = "FAILING PROGRAM ";
search[1] = "DATE - ";
search[2] = "TIME - ";
search[3] = "START OF POST PROCESSING RUN FOR DUMP ";
char * chemin = "./Dumps/dumpJSAD.txt"; //chemin
FILE* entree = fopen(chemin, "rb"); //Lecture en binaire
FILE* sortie = fopen("sortie.txt", "wb"); //Ecriture en binaire
char chaine[TAILLE_MAX] = "";
char res[100], i=0, j=0;
if (argc != 1) { //Si problème de paramètres
printf("usage: %s fichier\n", argv[0]);
return EXIT_FAILURE;
}
if(entree != NULL){ //Lecure ligne par ligne
for(int ligne = 1; ; ligne ++){
char * resultat = fgets(chaine, TAILLE_MAX, entree);
if(resultat == NULL) break;
char * d = binstr(resultat, TAILLE_MAX ,search[3]) ;
if(d != NULL){
fprintf(sortie, "Numéro de dump : %.4s\r\n", d+strlen(search[3]));
}
char * a = binstr(resultat, TAILLE_MAX ,search[0]) ; //Recherche de la chaine demandée
if(a != NULL){
fprintf(sortie, "Programme : %.4s\r\n", a+strlen(search[0])); //affiche les 4 caractères du FAILING PROGRAM
}
char * b = binstr(resultat, TAILLE_MAX ,search[1]) ;
if(b != NULL){
fprintf(sortie, "Date : %.5s\r\n", b+strlen(search[1])); //affiche 2fois DATE/HEURE car 2lecture dans le programme
}
char * c = binstr(resultat, TAILLE_MAX ,search[2]) ;
if(c != NULL){
fprintf(sortie, "Heure : %.8s\r\n", c+strlen(search[2]));
}
}
}
fclose(entree);
fclose(sortie);
}
Et autre chose, mon tableau avec les informations à rechercher est MOCHE !!! Mais j'ai essayer de faire ça plus proprement avec une boucle for mais PAS MOYEN !!! HELP !!!
Fichier de sortie :
Numéro de dump : 3589
Numéro de dump : 3589
Date : 19MAY
Heure : 16.36.03
Programme : JSAD
Date : 19MAY
Heure : 16.36.03
Dans un fonction cad ? Dans une fonction main ou dans une fonction "search" par exemple ?
Merci pour le lien vers le cours "structures", très facile enfaite !
Merci
EDIT :
Merci pour ta précieuse aide !
Ca marche.
Par contre il y a un soucis sur une petite chose : parce exemple le nom du programme est JSAD et la version est 0G. Dans le dump c'est écrit sur la même ligne (JSAD0G).
Comment récupérer les deux informations séparées ?
Et quand j'affiche mes infos, je dois afficher seulement 4 caractères pour le nom du prog ("JSAD") et ensuite 8 caractères pour l'heure ("16.36.03"). Avant je faisais ça dans le fprintf avec "%.4s" pour 4 caractères ect ...
Comment faire maintenant qu'il est dans la boucle ?
Edit: de même que je changerais found (je sais, c'est moi qui ai écrit ça au départ) en already_displayed.
Edit encore: je viens de relire ton programme. Tu as apparemment compris les structures, alors pourquoi ne pas y avoir ajouté la variable id ? De plus, que crois-tu que donne sizeof(search) ?
struct s_search {
char *searched_value;
char *id;
bool found;
int size;
};
struct s_search search[]={
{"FAILING PROGRAM ","Prgm : ",false,4},
{"DATE - ","Date : ",false,5},
{"TIME - ","Heure : ",false,8},
{"START OF POST PROCESSING RUN FOR DUMP ","Ref : ",false,4},
{"SYSTEM ERROR NUMBER ","Ctrl : ",false,11},
};
// Et l'affichage qui va avec
fprintf(outfile,"%d-%s%.*s\r\n",numline,search[i].id,search[i].size,rc+strlen(search[i].searched_value));
Edit encore encore: et je changerais id en title_to_display
- Edité par edgarjacobs 19 juin 2020 à 16:07:36
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Quand tu dis que le décalage est toujours le même, tu veux dire que la chaîne à récupérer (la version) est située toujours au même endroit (mêmes positions) dans la ligne ? Genre c'est toujours 2 caractères en position 46 et 47 ? Si oui :
Je vois bien une solution qui permet un traitement particulier tout en restant dans un programme "générique": ajouter dans la structure un pointeur sur fonction, qui permet alors un traitement spécifique par entrée trouvée.
J'ai repris ton dernier code (en insérant id dans la structure), je l'ai modifié et testé avec le fichier que tu avais fourni dans ce post. Je te laisse l'analyser.
Évidemment, à toi de modifier displayProgramVersion() pour faire ce que tu veux. Et, bien sur, il est possible de passer d'autres paramètres à la fonction, à condtion de modifier sa déclaration ligne 24
- Edité par edgarjacobs 22 juin 2020 à 17:28:38
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Quand tu dis que le décalage est toujours le même, tu veux dire que la chaîne à récupérer (la version) est située toujours au même endroit (mêmes positions) dans la ligne ? Genre c'est toujours 2 caractères en position 46 et 47 ? Si oui :
J'ai essayer ce que tu as donner mais comme je l'imaginais, ça ne marche pas. read_line ne contient pas des caractères mais des lignes. Donc read_line[46] contient la ligne 46.
edgarjacobs,
Je n'est pas très bien compris la déclaration ligne 24.
Ce que ton code fait c'est d'afficher la ligne FAILING PROGRAM dans le terminal pour le moment et je dois donc modifier displayProgramVersion pour qu'il n'affiche que la version ?
J'ai essayer ce que tu as donner mais comme je l'imaginais, ça ne marche pas. read_line ne contient pas des caractères mais des lignes. Donc read_line[46] contient la ligne 46.
read_line est déclaré ligne 44 comme un tableau de caractères. C'est un tableau qui sert de tampon pour une ligne. Et qui devrait s'appeler line_read (ligne lue), ou line, ou buffer, et pas read_line (lire ligne) qui est une description d'action.
Quand tu dis que tu as essayé, fais-vois le code. On ne sait pas ce que tu as pu faire à partir des indications qui été suggérées.
quand tu dis que ça ne marche pas, donne une description précise.
J'ai essayer ce que tu as donner mais comme je l'imaginais, ça ne marche pas. read_line ne contient pas des caractères mais des lignes. Donc read_line[46] contient la ligne 46.
read_line est déclaré ligne 44 comme un tableau de caractères.
Quand tu dis que tu as essayé, fais-vois le code. On ne sait pas ce que tu as pu faire à partir des indications qui été suggérées.
quand tu dis que ça ne marche pas, donne un description précise.
TOSYSTEM ERROR NUMBER OPR-I000004 VIRTUAL STORAGE ERROR DATE - 19MAY TIME - 16.36.03
TOSYSTEM ERROR NUMBER OPR-I000004 VIRTUAL STORAGE ERROR DATE - 19MAY TIME - 16.36.03
TOSYSTEM ERROR NUMBER OPR-I000004 VIRTUAL STORAGE ERROR DATE - 19MAY TIME - 16.36.03
D0*FAILING PROGRAM JSAD0G OBJ-JSAD0G +00000464 TRC-JSAD LOADSET-BASE
D0*FAILING PROGRAM JSAD0G OBJ-JSAD0G +00000464 TRC-JSAD LOADSET-BASE
Argh, j'ai oublié le coup du caractère nul ! (Le pire, c'est que je m'en suis immédiatement rendu compte en me relisant...)
Quand je disais « Genre c'est toujours 2 caractères en position 46 et 47 » c'était un exemple, je ne connais pas les positions précises ! (Comme quoi il n'y a pas que moi qui suis distrait )
En fait, j'ai l'impression que le contenu des lignes s'affiche à des positions précises. Je reprends ton extrait :
Ça commence par un caractère spécial, puis l'intitulé de l'erreur entre les positions 1 et 29, puis un mot-clé entre 30 et 35, etc. Si c'est le cas pour toutes les lignes, tu dois exploiter cette organisation.
("0G" est situé aux positions 46 et 47, ça alors ! J'avais pourtant pris ces nombres au hasard... Cela dit tu as obtenu "D0", donc il y a un décalage d'un cran peut-être dû au premier caractère spécial. Du coup ce serait plutôt :
et c'est peut-être le "0G" en position 35-36 qui t'intéresse, non ? Mais ça, c'est à toi de le déterminer.)
Si tu as plusieurs mots-clés à récupérer (et si c'est bien cette organisation), ça pourrait être une bonne idée de créer une fonction qui retourne (sous forme de paramètre passé par adresse) la sous-chaîne qui commence en position p et de longueur l.
Pour l'instant, ça affiche les caractères 47-48 de toutes les lignes. Si tu veux le faire pour certaines lignes seulement, il faut un critère permettant de reconnaître le type de ligne. Est-ce que tu veux cet affichage que pour les lignes qui commencent par "FAILING PROGRAM" ? Ou que pour une ligne précise et pas les autres ?
Pour l'instant, ça affiche les caractères 47-48 de toutes les lignes. Si tu veux le faire pour certaines lignes seulement, il faut un critère permettant de reconnaître le type de ligne. Est-ce que tu veux cet affichage que pour les lignes qui commencent par "FAILING PROGRAM" ? Ou que pour une ligne précise et pas les autres ?
Ah ok.
Il me faut seulement une ligne précise : ici la ligne 38
Comment ça la ligne 38 ? Tu veux dire que chaque fois que tu utiliseras ce programme pour afficher des infos d'un fichier dump, ce sera la ligne 38 qui contiendra la version ?
Et qu'est-ce que tu appelles la ligne 38 ? La 38è ligne du fichier d'entrée ? Ou la 38è ligne qui s'affiche ? (38 en comptant à partir de 0, ou à partir de 1 ?)
Du coup tu pourrais faire quelque comme ça (juste après l'affichage de la ligne complète) :
char mot_cle[20] ; // 20 ou autre chose...
char version[3] ;
extraire(read_line, mot_cle, 2, 15) ; // 15 = longueur de "FAILING PROGRAM", 2 = sa position (à corriger)
if (strcmp(mot_cle, "FAILING PROGRAM") == 0)
{ // On est sur une ligne commençant par "FAILING PROGRAME"
extraire(ligne, version, 47, 2) ;
/* afficher 'version' */
}
où la fonction 'extraire' serait une fonction ayant ce prototype :
void extraire(char ligne[], char mot[], int position, int longueur) ;
Elle extrait de la ligne un mot qui commence à la position indiquée et a la longueur indiquée, en n'oubliant pas de terminer ce mot par le caractère nul. Elle sert ici pour extraire le peut-être mot-clé (mot de longueur 15 et de position 2, ou peut-être 3, à vérifier) puis pour extraire la version.
(Ne recopie surtout pas ça tel quel : je n'ai pas essyayé, les nombres sont à vérifier/corriger, et j'ai utilisé un nom de fonction en français par habitude, contrairement à toi. C'est juste pour donner une idée.)
À vrai dire je ne me souviens plus ce qu'affiche cette ligne (ce n'est pas mon programme...) Ce n'était pas la ligne complète ? Pas grave. Je voulais dire : là où tu veux afficher une info de plus (la version).
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent