Forum: Mikrocontroller und Digitale Elektronik sscanf() - Raspberry


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Sebastian (Gast)


Bewertung
0 lesenswert
nicht 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
sscanf (match, "MemTotal: %ld", &mem_tot);

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

Hier noch mal der ganze Teil.
static long get_mem_total (char *str) {
   FILE *fp;
   char buffer[1024];
   size_t bytes_read;
   char *match;
   long mem_tot;
   if((fp = fopen("/proc/meminfo", "r")) == NULL) {
      perror("fopen()");
      exit(EXIT_FAILURE);
   } 
   bytes_read = fread (buffer, 1, sizeof (buffer), fp);
   fclose (fp);
   if (bytes_read == 0 || bytes_read == sizeof (buffer))
      return 0;
   buffer[bytes_read] = '\0';
   /* Suchen nach der Stringfolge */
   match = strstr (buffer, str);
   if (match == NULL) /* Nicht gefunden */
      return 0;   
   sscanf (match, "???: %ld", &mem_tot);
   return (mem_tot/1024); /* 1MB = 1024KB */
}

von Sebastian (Gast)


Bewertung
0 lesenswert
nicht lesenswert
/...
    char buffer1[20];
    strcpy(buffer1, str);
    strcat(buffer1, ": %ld");
    printf("%s\r\n", buffer1);

    // auswerten
    sscanf (match, buffer1, &mem);
    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
sscanf (match, str+": %ld", &mem);

von Pittyj (Gast)


Bewertung
0 lesenswert
nicht 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)


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

von Karl H. (kbuchegg) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
>
> /...
>     char buffer1[20];
>     strcpy(buffer1, str);
>     strcat(buffer1, ": %ld");
>     printf("%s\r\n", buffer1);
> 
>     // auswerten
>     sscanf (match, buffer1, &mem);
>     return (mem/1024); /* 1MB = 1024KB */
> 
>
> So geht es, sieht aber nicht so optimal aus.

Wenn man schon sscanf benutzt, dann hindert einen nichts daran, auch 
sprintf zu benutzen.
  sprintf( buffer1, "%s: %%ld", str );
  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.

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

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

: Bearbeitet durch Moderator
von Chris F. (chris_de)


Bewertung
0 lesenswert
nicht lesenswert
So gehts noch einfacher und gibt dir noch mehr Infos aus:
#include <sys/sysinfo.h>
.
.
struct sysinfo device_sysinfo;
if( sysinfo(&device_sysinfo) != 0 )
{
  printf("Fehler!\r\n");
  return 1; //exit
}
.
.
printf("RAM_total = %llu;\r\n", device_sysinfo.totalram * (unsigned long long)device_sysinfo.mem_unit / 1024);
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)


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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.