Lesen von strings mit Leerzeichen aus einer Datei
Ich bin an einem Projekt arbeiten und ich habe gerade festgestellt ein wirklich nerviges problem. Ich habe eine Datei, welche alle Nachrichten, mein Konto erhalten. Eine Nachricht ist eine Datenstruktur, die so definiert ist:
typedef struct _message{
char dest[16];
char text[512];
}message;
dest
ist ein string, der keine Leerzeichen enthalten darf, im Gegensatz zu den anderen Feldern.
Strings erworben werden, die mit der fgets()
Funktion, so dest
und text
können "dynamische" Länge (von 1 Zeichen bis zu length-1 legit Zeichen). Beachten Sie, dass ich Sie manuell entfernen die neue-Zeile-Zeichen nach jedem string abgerufen, der von der Standardeingabe.
Den "inbox" - Datei wird die folgende syntax verwendet, um Nachrichten zu speichern:
dest
text
So, zum Beispiel, wenn ich eine Nachricht von Marco, die sagt: "Hello, how are you?" und eine weitere Meldung von Tarma, die sagt: "gehst du in die Turnhalle heute?", meine inbox-Datei würde wie folgt Aussehen:
Marco
Hello, how are you?
Tarma
Are you going to the gym today?
Ich Lesen möchte, den Benutzernamen aus der Datei und Speicher es in string s1, und dann tun die gleiche Sache für die Nachricht und speichern Sie es in string s2 (und dann wiederholen Sie den Vorgang, bis ein EOF-Zeichen), aber da text
Feld räumt Bereiche, die ich nicht wirklich verwenden fscanf()
.
Versuchte ich mit fgets()
, aber wie gesagt, die Größe jeder string ist dynamisch. Zum Beispiel, wenn ich fgets(my_file, 16, username)
es würde am Ende der Lektüre unerwünschte Zeichen. Ich brauche nur zu Lesen, die erste Zeichenfolge bis \n
erreicht ist, und dann Lesen Sie die zweite saite, bis der nächste \n
erreicht ist, wird diese Zeit inklusive Leerzeichen.
Jede Idee, wie kann ich dieses problem lösen?
fgets
hält an ein newline oder EOF. Wenn Sie haben entfernt die neue line, don ' T, die Sie bereits wissen, die genaue Länge der Zeichenfolge?- Die 16, die Sie übergeben, um
fgets()
ist die maximale Länge der Zeichenfolge.fgets()
hält an (16-1) chars oder newline oder EOF - Wenn ich empfangen von strings aus der Datei, ich weiß nicht, die genaue Länge kenne ich nur die maximale Länge einer Zeichenkette (16 chars für dest, 512 chars für text, einschließlich der \0) tut mir Leid für mich unklar.
- Vane Du hast Recht. Vielleicht sollte ich ändern die syntax, die ich verwenden, um Nachrichten schreiben innerhalb der Datei...
Du musst angemeldet sein, um einen Kommentar abzugeben.
%*c
überspringen der Zeilenumbruch nach dem Namen.Als die Länge der einzelnen string ist dynamisch, also, wenn ich du wäre, würde ich Lesen Sie zuerst die Datei für die Suche nach jeder string in Größe und erstellen Sie dann ein dynamisches array mit strings' Länge Werte.
Angenommen, Ihre Datei ist:
Also die erste Zeile die Länge ist
15
, die zweite die Länge der Linie ist16
und die Dritte Länge ist12
.Dann erstellen Sie ein dynamisches array für die Speicherung dieser Werte.
Dann, beim Lesen von strings übergeben, als 2. argument
fgets
das entsprechende element des Arrays. Wiefgets (string , arrStringLength[i++] , f);
.Aber auf diese Weise haben Sie zu Lesen, Ihre Datei zweimal, natürlich.
Können Sie
fgets()
leicht genug, solange du vorsichtig bist. Dieser code scheint zu funktionieren:Dem Lesen von code handle (mehrere) Leerzeilen vor der ersten Namen, die zwischen einem Namen und dem text, und nachdem der Letzte name. Es ist etwas ungewöhnlich in der Sie, wie es sich entscheidet, ob zum speichern der Zeile, Lesen Sie einfach in der
dest
odertext
Teile der Nachricht. Es nutztmemmove()
weil er genau weiß, wie viele Daten zu verschieben, und die Daten null ist beendet. Sie könnte ersetzen Sie es mitstrcpy()
wenn Sie es vorziehen, aber es sollte langsamer sein (die wohl nicht messbar langsamer), weilstrcpy()
zum testen, jedes byte als Kopien, abermemmove()
nicht. Ich benutzememmove()
denn es ist immer richtig;memcpy()
könnte hier verwendet werden, aber es funktioniert nur, wenn Sie garantieren, dass keine überlappung. Better safe than sorry; es gibt zahlreiche software-Fehler, ohne zu riskieren extras. Sie können sich entscheiden, ob der Fehler exit angemessen ist — es ist gut für test-code, aber nicht unbedingt eine gute Idee in den Produktions-code. Sie können entscheiden, wie Sie zu behandeln '0 Nachrichten' vs '1 Nachricht' vs '2 Nachrichten' etc.Können Sie leicht überarbeiten Sie den code für die dynamische Zuweisung von Speicher für das array von Nachrichten. Es würde leicht sein, um die Nachricht zu Lesen, in eine einfache
Message
variable inmain()
, arrangieren und kopieren Sie in das dynamische array, wenn Sie bekommen eine vollständige Nachricht. Die alternative ist die 'Gefahr' über die Zuweisung der array, aber das ist unwahrscheinlich, dass ein großes problem (Sie würden nicht wachsen das array nur einen Eintrag sowieso zu vermeiden quadratischen Verhalten, wenn der Speicher bewegt werden, während jede Zuweisung).Wenn es mehrere Felder bearbeitet werden, die für jede Nachricht (sagen, Eingangsdatum und Datum zu Lesen), dann würden Sie brauchen, um die Reorganisation der code einige mehr, wahrscheinlich mit einer anderen Funktion.
Beachten Sie, dass der code verhindert den reservierten Namensraum. Ein name wie
_message
ist reserviert für die 'Umsetzung'. Code wie dieser ist nicht Teil der Umsetzung (von der C-compiler und Ihre support-system), so sollte man nicht Namen erstellen, die mit einem Unterstrich beginnen. (Das über-vereinfacht die Einschränkung, aber nur leicht, und ist viel einfacher zu verstehen als die differenziertere version.)Code ist vorsichtig, nicht zu schreiben keine Magische Zahl mehr als einmal.
Beispiel-Ausgabe: