PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C] String bearbeiten



Primusio
25-03-2004, 20:16
Hallo Community, ich bräuchte eure Hilfe.

Ich möchte aus "/proc/net/dev" die Netzwerkinterfaces auslesen ohne "lo".

Kann mir jemand dabei helfen ? Finde keinen so rechten Lösungsansatz. Es soll so simpel wie möglich sein, da dort eh selten mehr als 5 Interfaces verzeichnet sind.

Wäre super nett, die Datei einlesen soweit bin ich, nur der Rest hapert.

MfG
Peter

nobody0
25-03-2004, 20:58
Zeilenweise einlesen z. B. so:



ifp = fopen (cline, "r");
for (in_line = 0; fgets (line, 128, ifp) != NULL; in_line++)
{ /* zeilenweise Einlesen bis Dateiende */
i = sscanf (line, "%hu.%hu.%hu,%hu.%hu.%hu,%hu,%s",
&wp[in_line].f_date_d, &wp[in_line].f_date_m,
&wp[in_line].f_date_y, &wp[in_line].l_date_d, &wp[in_line].l_date_m, &wp[in_line].l_date_y, &wp[in_line].bad_count, wp[in_line].in_symbol);
if (i != 8)
...

Primusio
25-03-2004, 21:16
Sorry aber in wie weit hilft mir das nun weiter ?

Ich sagte ja das einlesen kann ich schon, der Rest will nicht. Und den Code den du mir geschrieben hast, verstehe ich nicht, zuviele Punkte.

MfG
Peter

nobody0
25-03-2004, 21:58
Wenn Du die nach dem Muster Daten eingelesen hast, dann hast Du doch alle Daten (im C-internen Format, also z. B. vom Typ int für eine Ganzzahl); wo ist das Problem? :confused:

Primusio
26-03-2004, 09:06
Ach ja ?

Ich bin leider kein Profi, vn daher wäre eine genauere Beschreibung nett.

anda_skoa
26-03-2004, 09:26
fgets liest hier aus einem Stream, in diesem Falle eine Datei, eine bestimmte Anzahl Zeichen aus, aber maximal bis zu einem Newline (Zeilenende).

Im Beispiel dürfen die Zeilen also maximal 127 Zeichen lang sein, um ganz rein zu passen.

Dann wird mit sscanf aus dieser Zeichenkette "rausgelesen", mit fscanf könnte man das auch direkt aus der Datei machen.

Der Formatstring gibt dabei an, wie die Zeichenkette zerlegt werden soll und wie sie in die Variablen nach dem Formatstring aufgeteilt wird.

Das Format ist dabei ähnlich wie bei printf.

Ciao,
_

nobody0
26-03-2004, 09:36
Ja, aber er hat geschrieben

"Ich möchte aus "/proc/net/dev" die Netzwerkinterfaces auslesen"

"Ich sagte ja das einlesen kann ich schon, der Rest will nicht. "

Also ist das Einlesen schon erledigt; er braucht kein sscanf oder fgets mehr. Das Problem ist der unbekannte "Rest", was immer das auch ist.
Vielleicht will er erstmal wissen was er wissen will, oder er weiß einfach nicht was er will; jedenfalls ist "Rest" nichtssagend.

Primusio
26-03-2004, 12:07
Tut mir leid, ich habe mich wirklich alles andere als gut ausgedrückt.

Also als erstes möchte ich aus einer Datei nur die Zeilen haben die ein ":" beinhalten, dann soll beim ":" durchgeschnitten werden und er soll mir in einem array das vor dem ":" stehende ausgeben (ohne leerzeichen).
Dabei kann die Anzahl der Zeichen davor variieren, meist 4 bis 5.

Sorry nochmal wegen der blöden Formuliereung.

MfG
Primusio

nobody0
26-03-2004, 13:12
Also das Zeilen Einlesen steht ja in der Zeile mit for und beim sscanf braucht man

%s:%s

als Format. Im ersten String steht dann das, was vor dem Doppelpunkt ist (inkl. Leerzeichen).
Statt dem if (i != 8) in dem Beispiel braucht man if (i != 2) um das ":" in der Zeile abzufragen.

Primusio
26-03-2004, 15:40
Wie und welche Variablen muss ich denn da deklarieren ?

Wenn ich zuhause bin, probiere ich es einmal aus, aber die Hilfe mit den Variablen wäre schon nett.

MfG
Primusio

Primusio
26-03-2004, 16:13
Schon bin ich zuhause.



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

int main()
{
FILE *datei;
int i;
char *line;
int in_line;
char *eins[10];

datei = fopen("/proc/net/dev", "r");

for (in_line = 0; fgets (line, 500, datei) != NULL; in_line++)
{
i = sscanf(line, "%s:", &eins[in_line];
if ( i != 2)
printf("%s \n", &eins[in_line];
}
}

Was mache ich daran falsch ?
der gibt mir mehr als nur die 2 Interfaces aus.

nobody0
26-03-2004, 20:15
Also nachdem indent das Einrücken der Klammern richtig gesetzt hat, sieht es so aus:



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main ()
{
FILE *datei;
int i;
char *line;
int in_line;
char *eins[10];
datei = fopen ("/proc/net/dev", "r");
for (in_line = 0; fgets (line, 500, datei) != NULL; in_line++)
{
i = sscanf (line, "%s:", &eins[in_line];
if (i != 2) printf ("%s \n", &eins[in_line];}
}


Da fehlen also einige Klammern, wie auch gcc meldet:

blub.c: In function `main':
blub.c:15: error: parse error before ';' token
blub.c:16: error: parse error before ';' token

Mit void, exit und ein paar anderen Sachen wie line so definieren, dass damit Daten abgespeichert werden können ohne Segmentation violation zu bekommen sieht es so aus:



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

#define MAX_LENGTH 255

int
main (void)
{
static FILE *datei;
static int i, j;
static char line[MAX_LENGTH];
static int in_line;
static char eins[MAX_LENGTH][MAX_LENGTH];
static char foo[MAX_LENGTH];

datei = fopen ("/proc/net/dev", "r");
for (in_line = 0; fgets (line, 123, datei) != NULL; in_line++)
{
for (j = strlen (line)-1; j >= 0; j--)
{
if (':' != line[j])
line[j] = '\0';
else
{
line[j] = '\0';
break;
}
}
i = sscanf (line, "%s", eins[in_line]);
// if (i != 1)
printf ("in_line=%d, i=%d, %s, %s \n", in_line, i, eins[in_line], foo);
}
exit (0);
}



Damit das Einlesen richtig funktioniert müssen die Zeilen von hinten bis einschließlich zum : gelöscht werden.

Primusio
26-03-2004, 22:48
Super ich danke dir viel mals, das klappt jetzt.

Könntest du mir vielleicht noch verraten, wie ich die ausgelesenen Werte noch in ein --> globales <-- array bekomme ?


char *choices_netzwerk[] =
{

};

nobody0
27-03-2004, 01:16
Original geschrieben von Primusio
Super ich danke dir viel mals, das klappt jetzt.

Könntest du mir vielleicht noch verraten, wie ich die ausgelesenen Werte noch in ein --> globales <-- array bekomme ?


char *choices_netzwerk[] =
{

};

Das ist ein Pointer auf ein Array; damit kann man nur einen Pointer abspeichern.
Am besten ist erstmal alle Variablen als static zu deklarieren, denn nach dem Standard (kurz C99, gibt's online für 18$ bei www.ansi.org), werden die dadurch automatisch mit 0 nitialisiert.
Das globale Array muß zweidimensinal sein:

static choices_netzwer[MAX_LENGTH][MAX_HEIGHT];

obwohl es im Prinzip auch mit variabler Länge ginge, aber das hängt auch vom Compiler ab, ob der das schafft (u. ob das mit dem Code möglich ist, denn sizeof funktionert mit variabel langen arrays nicht).
Mit strcpy oder memcpy oder strncpy kann man dann von array zu array kopiert, aber ich würde direkt in das globale array einlesen.

Als Anfänger solltest Du Dir erstmal die C-FAQs durchlesen (gibt's auch als Buch) und den Standard besorgen, um da in Zweifelsfällen nachzulesen und in Lehrbüchern praktisch nie auftauchendes wie den Komma-Operator und den Qualifier restrict kennen zu Lernen. Allerdings gibt's bisher keinen Compiler, der den Standard zu 100 % einhält. Der gcc kommt ihm aber sehr nahe.
Weil der letzte ANSI-C-Standard alle vorherigen schon im Vorwort nicht nur ersetzt sondern auch zurückieht (d. h. als ungültig erklärt), ist "der" C-Standard seit 12.1.1999 das ANSI/ISO-C C99 (ISO/IEC 9899:1999(E), Date of ANSI Approval: 5/22/00), und das ist nahezu 5 Jahre alt.

Primusio
27-03-2004, 07:20
Ja das ist mir alles schon klar, das Problem ist nur, dass ich es dort hinein bekommen muss, da ein anderer Teil meines Programmes unter anderen auf sizeof besteht.

wraith
27-03-2004, 07:59
Original geschrieben von nobody0
denn sizeof funktionert mit variabel langen arrays nicht).
Sicherlich funktioniert das.Das ist der einzige Fall,wo sizeof zur Laufzeit ausgewertet wird.
(6.5.3.4 The sizeof operator,Example 3).


Das ist ein Pointer auf ein Array; damit kann man nur einen Pointer abspeichern.

Ich hätte das ja jetzt für ein Array von Zeigern auf char gehalten.


Allerdings gibt's bisher keinen Compiler, der den Standard zu 100 % einhält. Der gcc kommt ihm aber sehr nahe.

So nah,und doch so fern ;).
Momentan wohl der Beste
http://www.comeaucomputing.com/

nobody0
27-03-2004, 21:12
Original geschrieben von wraith
Sicherlich funktioniert das.Das ist der einzige Fall,wo sizeof zur Laufzeit ausgewertet wird.
(6.5.3.4 The sizeof operator,Example 3).


Ok, ich hatte das wohl mit C90 verwechselt.



Original geschrieben von wraith
Ich hätte das ja jetzt für ein Array von Zeigern auf char gehalten.
[/B]

So spät hatte ich das nicht allzu genau genommen; jedenfalls kann man damit keine Strings abspeichern sondern nur pointer auf strings. Für Strings fehlt noch allozierter Speicher.



Original geschrieben von wraith
So nah,und doch so fern ;).
Momentan wohl der Beste
http://www.comeaucomputing.com/ [/B]

Also insbesondere die Compiler für embedded Systeme erfüllen meist nicht einmal den ehemaligen C90 standard; da ist der gcc u. dessen Derivate um Größenordnungen besser, auch weil er full compiler ist, also beispielsweise bei undefinierten Ausdrücken oder Ausdrücken ohne Effekt oder der Abfrage von immer wahren/falschen Ausdrücken warnt.

Vor allem kann man beim gcc einstellen, ob er nach C90, C99, C89 oder einem anderen Stil compilieren soll:
http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Standards.html#Standards

Das kann man bei den meisten andern nicht!
Dies gilt auch für die Liste der C99 features:
http://gcc.gnu.org/c99status.html

Die kommerziellen Compiler-Hersteller haben sowas auch intern, aber da stellt man dann erst beim Benutzen fest, dass da noch mehr vom C99 fehlt und die Hersteller sich tot stellen, wenn man da mal nach so einer List fragt, selbst wenn man für Support bezahlt
:mad:

Primusio
30-03-2004, 12:01
Erst einmal danke für eure Hilfe, jetzt läuft es bis dahin.

Doch was mich verwundert, in "eins[in_line]" steht ja das jeweilige Interface, doch wieso kann ich in der FOR-Schleife, von dem Code den ihr mir gegeben habt keine IF-Abfrage darauf machen ?



if (eins[in_line] == "lo")
...


doch das geht nicht, für ihn ist eins[in_line] immer ungleich lo.

Könnt ihr mir da vielleicht noch einmal bitte helfen ?

nobody0
30-03-2004, 18:56
Ich bekomme hiermit:



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

#define MAX_LENGTH 255

typedef int T_int_ptr;

union bar
{
int *p_p;
int i_i;
char a_c[sizeof(int *)];
};

int
main (void)
{
static FILE *datei;
static int i, j;
static char line[MAX_LENGTH];
static int in_line;
static char eins[MAX_LENGTH][MAX_LENGTH];
static char foo[MAX_LENGTH];

datei = fopen ("/proc/net/dev", "r");
for (in_line = 0; fgets (line, 123, datei) != NULL; in_line++)
{
for (j = strlen (line) - 1; j >= 0; j--)
{
if (':' != line[j])
line[j] = '\0';
else
{
line[j] = '\0';
break;
}
}
i = sscanf (line, "%s", eins[in_line]);
// if (i != 1)
printf ("in_line=%d, i=%d, %s, %s \n", in_line, i, eins[in_line], foo);
}
exit (0);
}


Diese Ausgabe:
in_line=0, i=-1, ,
in_line=1, i=-1, ,
in_line=2, i=-1, ,
in_line=3, i=1, lo,
in_line=4, i=-1, ,
in_line=5, i=1, eth0,
in_line=6, i=-1, ,
in_line=7, i=1, eth1,
in_line=8, i=-1, ,
in_line=9, i=1, eth2,
in_line=10, i=-1, ,
in_line=11, i=1, sit0,
in_line=12, i=-1, ,


Das kommt ver der Zeilenlänge; das 123 muß durch MAX_LEHGTH ersetzt werden.
Mit 255 sieht es so aus:
in_line=0, i=-1, ,
in_line=1, i=-1, ,
in_line=2, i=1, lo,
in_line=3, i=1, eth0,
in_line=4, i=1, eth1,
in_line=5, i=1, eth2,
in_line=6, i=1, sit0,

Es gibt also erst ab Eingabezeile 2 etwas, wie auch der Rückgabewert von sscanf anzeigt.