Forum: Mikrocontroller und Digitale Elektronik sscanf() - Raspberry


von Sebastian (Gast)


Lesenswert?

Hallo,

wie kann ich hier am besten sscanf anpassen, damit ich eine mehrfach 
verwendbare Funktion habe?

Die Funktion liest aus einem Debiansystem den Speicher aus. Die Funktion 
ist für "MemTotal" geschrieben. Aber anstatt nach MemTotal zusuchen, 
möchte ich gerne nach dem str suchen.

Eigentlich heißt es
1
sscanf (match, "MemTotal: %ld", &mem_tot);

Jedoch muss ich nun das MemTotal durch den inhalt des str ersetzen.

Hier noch mal der ganze Teil.
1
static long get_mem_total (char *str) {
2
   FILE *fp;
3
   char buffer[1024];
4
   size_t bytes_read;
5
   char *match;
6
   long mem_tot;
7
   if((fp = fopen("/proc/meminfo", "r")) == NULL) {
8
      perror("fopen()");
9
      exit(EXIT_FAILURE);
10
   } 
11
   bytes_read = fread (buffer, 1, sizeof (buffer), fp);
12
   fclose (fp);
13
   if (bytes_read == 0 || bytes_read == sizeof (buffer))
14
      return 0;
15
   buffer[bytes_read] = '\0';
16
   /* Suchen nach der Stringfolge */
17
   match = strstr (buffer, str);
18
   if (match == NULL) /* Nicht gefunden */
19
      return 0;   
20
   sscanf (match, "???: %ld", &mem_tot);
21
   return (mem_tot/1024); /* 1MB = 1024KB */
22
}

von Sebastian (Gast)


Lesenswert?

1
/...
2
    char buffer1[20];
3
    strcpy(buffer1, str);
4
    strcat(buffer1, ": %ld");
5
    printf("%s\r\n", buffer1);
6
7
    // auswerten
8
    sscanf (match, buffer1, &mem);
9
    return (mem/1024); /* 1MB = 1024KB */

So geht es, sieht aber nicht so optimal aus. Vielleich eine kürzere 
Lösung für diesen Abschnitt? Irgendware wie
1
sscanf (match, str+": %ld", &mem);

von Pittyj (Gast)


Lesenswert?

Doch, genau so geht das. (einfache Version)

Allerdings solltest du mit den Buffern aufpassen. Bei mir ist 
/proc/meminfo größer als 1024 Bytes. Das passt gar nicht in deinen 
'buffer' rein.

Als nächstes kann auch die Zeichenkette in *str ja länger als 14 sein. 
Dann gibt es den nächsten Bufferüberlauf in buffer1.

Und auf Unix reicht "\n". Das "\r" kann man sich sparen, das braucht nur 
Bill Gates.

von Dirk B. (dirkb2)


Lesenswert?

Da du ja schon sicher bist, das str in dem Text steht, kannst du auch 
hinter str das sscanf machen
1
   match = strstr (buffer, str);
2
   if (match == NULL) /* Nicht gefunden */
3
      return 0;   
4
   sscanf (match+strlen(str), ": %ld", &mem_tot);

von Karl H. (kbuchegg)


Lesenswert?

Sebastian schrieb:
>
1
> /...
2
>     char buffer1[20];
3
>     strcpy(buffer1, str);
4
>     strcat(buffer1, ": %ld");
5
>     printf("%s\r\n", buffer1);
6
> 
7
>     // auswerten
8
>     sscanf (match, buffer1, &mem);
9
>     return (mem/1024); /* 1MB = 1024KB */
10
>
>
> So geht es, sieht aber nicht so optimal aus.

Wenn man schon sscanf benutzt, dann hindert einen nichts daran, auch 
sprintf zu benutzen.
1
  sprintf( buffer1, "%s: %%ld", str );
2
  sscanf( match, buffer1, &mem );
(man beachte das %%)

(Noch besser wäre allerdings snprintf)

das Prinzip jedoch ist, wie schon geschrieben, ok. Nichts und niemand 
hindert einen daran, den Formatstring sich selbst mittels anderen 
Operationen zusammenzusetzen. String ist String und sscanf kümmert sich 
nicht darum, wo der herkommt.

>
1
> sscanf (match, str+": %ld", &mem);
2
>

Das jedoch funktioniert nicht. Man kann nicht 2 Pointer addieren.

: Bearbeitet durch User
von Chris F. (chris_de)


Lesenswert?

So gehts noch einfacher und gibt dir noch mehr Infos aus:
1
#include <sys/sysinfo.h>
2
.
3
.
4
struct sysinfo device_sysinfo;
5
if( sysinfo(&device_sysinfo) != 0 )
6
{
7
  printf("Fehler!\r\n");
8
  return 1; //exit
9
}
10
.
11
.
12
printf("RAM_total = %llu;\r\n", device_sysinfo.totalram * (unsigned long long)device_sysinfo.mem_unit / 1024);
13
printf("RAM_free = %llu;\r\n", device_sysinfo.freeram * (unsigned long long)device_sysinfo.mem_unit / 1024);

In dem struct steckt u.A. noch die Uptime, CPU-Load und die Anzahl 
laufender Prozesse.

Gruß

von Dirk B. (dirkb2)


Lesenswert?

Statt sscanf geht da auch gleich strtol
1
   match = strstr (buffer, str);
2
   len = strlen(str);
3
   if ((match == NULL) || (match[len] != ':')) /* Nicht gefunden */
4
      return 0;   
5
   mem_tot = strtol(match+len+1, NULL, 10);

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.