2015-10-19 1 views
0

Je dois trouver dans un fichier texte la ligne spécifique qui commence par un mot-clé et ensuite je dois analyser cette ligne pour extraire des informations. Je vais le clarifier par un exemple:Trouver une ligne dans un fichier et extraire des informations

processor  : 0 
vendor_id  : GenuineIntel 
cpu family  : 6 
model   : 5 
model name  : Pentium II (Deschutes) 
stepping  : 2 
cpu MHz   : 400.913520 
cache size  : 512 KB 
fdiv_bug  : no 
hlt_bug   : no 

c'est le fichier texte (/ proc/cpuinfo de Linux). Je dois écrire une fonction qui analyse le fichier jusqu'à ce qu'il trouve "nom du modèle:" et il doit ensuite stocker dans un tableau Array l'information "Pentium II (Deschutes)". C'est ce que je codé jusqu'à présent:

int get_cpu(char* info) 
{ 
    FILE *fp; 
    char buffer[1024]; 
    size_t bytes_read; 
    char *match; 

    /* Read the entire contents of /proc/cpuinfo into the buffer. */ 
    fp = fopen("/proc/cpuinfo", "r"); 

    bytes_read = fread(buffer, 1, sizeof (buffer), fp); 

    fclose (fp); 

    /* Bail if read failed or if buffer isn't big enough. */ 
    if (bytes_read == 0 || bytes_read == sizeof (buffer)) 
     return 0; 

    /* NUL-terminate the text. */ 
    buffer[bytes_read] == '\0'; 

    /* Locate the line that starts with "model name". */ 
    match = strstr(buffer, "model name"); 

    if (match == NULL) 
     return 0; 

    /* copy the line */ 
    strcpy(info, match); 
} 

il est dit que le tampon est toujours pas assez grand ......

+4

"il est dit que le tampon n'est toujours pas assez grand". C'est parce que ce n'est pas assez grand. Exécutez simplement 'cat/proc/cpuinfo> output' manuellement et regardez la taille du fichier' output'. Que trouvez-vous? – kaylum

+0

sur mon système c'est un très gros document ... Je devrais écrire un programme qui pourrait fonctionner sur tous les systèmes Linux – rugrag

+0

@kaylum * utilisation inutile de cat * détecté \ * scnr \ * (encore +1) [explication: un simple 'cp' ferait si vous voulez examiner avec' ls' - il vaut mieux juste utiliser 'wc -c'] –

Répondre

1

va bien au-delà du simple fait que /proc/cpuinfo est généralement supérieure à 1024 octets :

> wc -c </proc/cpuinfo 
3756 

et comme, bien sûr, votre tampon est trop petit pour lire le fichier entier à la fois ...

Qu'est-ce que vous essayez ici est de traiter un fichier texte et la façon naturelle de le faire serait ligne par ligne.

Essayez quelque chose comme

(modifier: remplacer enfin le tout avec le code testé ... il est pas si facile d'obtenir strtok() droit ... hehe)

#include <stdio.h> 
#include <string.h> 

int main(void) 
{ 
    char buf[1024]; 
    char *val = 0; 
    FILE *fp = fopen("/proc/cpuinfo", "r"); 
    if (!fp) 
    { 
     perror("opening `/proc/cpuinfo'"); 
     return 1; 
    } 

    while (fgets(buf, 1024, fp))  /* reads one line */ 
    { 
     char *key = strtok(buf, " "); /* gets first word separated by space */ 
     if (!strcmp(key, "model")) 
     { 
      key = strtok(0, " \t");  /* gets second word, separated by 
             * space or tab */ 
      if (!strcmp(key, "name")) 
      { 
       strtok(0, " \t");   /* read over the colon */ 
       val = strtok(0, "\r\n"); /* read until end of line */ 
       break; 
      } 
     } 
    } 

    fclose(fp); 

    if (val) 
    { 
     puts(val); 
    } 
    else 
    { 
     fputs("CPU model not found.\n", stderr); 
    } 
    return 0; 
} 
utilisation

:

> gcc -std=c89 -Wall -Wextra -pedantic -o cpumodel cpumodel.c 
> ./cpumodel 
AMD A6-3670 APU with Radeon(tm) HD Graphics 
+0

J'ai utilisé le test implicite d'un pointeur' NULL' comme '0' comme vous le faites, et le explicit utiliser dans 'strtok()' aussi, jusqu'à ce que je rencontre des articles tels que cette réponse SO. http://stackoverflow.com/questions/9894013/is-null-always-zero-in-c –

+0

@WeatherVane 'NULL' n'a pas besoin d'être' 0' (comme dans tous les bits zéro), mais '0' dans un contexte de pointeur signifie le pointeur 'NULL', quelle que soit sa représentation, et un pointeur' NULL' évalue toujours faux dans un contexte booléen ... donc le chemin "traditionnel" est sûr. –

+0

@WeatherVane Cela étant dit, je préfère simplement la version "laconique" ici. C'est une question de style et «NULL» a bien sûr l'avantage d'être plus expressif. –

0

Veuillez essayer ceci, cela fonctionne, il y a différentes façons de le faire.

#include <usual.h> 

int get_cpu(char *info) 
{ 
    FILE *fp; 
    char buffer[1024]; 
    size_t bytes_read; 
    char *match; 
    char *matchend; 
    /* Read the entire contents of /proc/cpuinfo into the buffer. */ 
    fp = fopen("/proc/cpuinfo", "r"); 
    bytes_read = fread(buffer, 1, sizeof(buffer), fp); 
    fclose(fp); 
    /* Bail if read failed or if buffer isn't big enough. */ 
    if (bytes_read == 0 || bytes_read == sizeof(buffer)) 
    return 0; 
    /* NUL-terminate the text. */ 
    buffer[bytes_read] == '\0'; 
    // match=buffer; 
    /* Locate the line that starts with "model name". */ 
    match = strstr(buffer, "model name"); 
    if (match == NULL) 
    return 0; 
    /* copy the line */ 
    strncpy(info, match, 41); 
} 

int main() 
{ 
    char info[255]; 
    memset(info, '\0', 255); 
    get_cpu(info); 
    printf("\nthe data we extracted: %s ", info); 
    getchar(); 
} 
+0

Qu'est-ce que c'est que "usual.h"? Et comment cela ne ** pas ** échouer de la même manière que le code dans la question? –

+0

Voilà où j'ai mis mes habituels inclus, donc c'est devenu: habituel, plus simple. Maintenant vous pouvez compiler et courir. Et il fonctionne. – BobRun

+0

Non, cela ne sera pas aussi long que '/ proc/cpuinfo' soit plus grand que 1024 octets. Même problème que dans la question. –