2016-10-25 3 views
0

Ich möchte nur ein Scanf zwingen, ein einzelnes Leerzeichen zu lesen und dann den Rest der Zeichenfolge speichern, bis ein Komma in einer Variablen gefunden wird. Ich kann es so nicht tun:C: Ein einzelnes Leerzeichen in einem scanf

char content[100]; 
fscanf(f, " %[^,\n],", content); 

, weil ich nicht content will gesetzt werden, wenn es eine anhängiges '\n' ist. Gibt es eine Möglichkeit, den Whitespace zu scannen?

Die Abhilfe, die ich bisher gefunden habe:

char space; 
fscanf(f, "%1[^\n]%[^,\n],", &space, content); 

Sorry für die dumme Frage und danken Ihnen im Voraus.

+0

Ihr Beispielcode stimmt nicht mit Ihren Wörtern überein. Du sagst ein einzelnes * Leerzeichen *, aber du scheinst stattdessen eine * neue Zeile * zu finden. Sie sagen, Sie möchten bis zu einem Semikolon (';') scannen, aber Sie scheinen zu versuchen, bis zu einem Komma (',') zu scannen. –

+0

Ich bin nicht mit der Newline, ich versuche genau das zu vermeiden. Aber du hast recht mit dem Komma, das habe ich schon korrigiert. –

Antwort

4

Ich bin der Annahme, dass der Code, den Sie Ihre Absicht besser präsentiert zum Ausdruck bringt als deine Worte, die auf den Angaben entsprechen. Inasmuchas Sie sagen ...

Die Abhilfe, die ich bisher gefunden habe:

char space; 
fscanf(f, "%1[^\n]%[^,\n],", &space, content); 

... Ich schließe daraus, dass dieser Code scheint Ihnen zu tun, was Sie wollen, und ich schließen dass Sie es als "Workaround" bezeichnen, statt als vollständig zufriedenstellende Lösung, da die Variable space berücksichtigt werden muss.

In der Tat ist es schlimmer als das: Wann immer scanf() erfolgreich das erste Feld übereinstimmt, ruft es undefined Verhalten durch Überschreiten der Grenzen von space. Das passiert, weil der Feldbezeichner [ mit nicht leeren Zeichenfolgen übereinstimmt, die nach ihrem Inhalt einen Terminator haben. Aber die gute Nachricht ist, dass die Beseitigung der Notwendigkeit für die zusätzliche Variable, die Sie sowieso zu tun scheinen, dieses Problem auch lösen wird.

Der einfachste Weg, dies zu tun wäre, um die Zuordnung Unterdrückungs Modifikator (*) mit dem entsprechenden Felddeskriptor anzuwenden:

fscanf(f, "%*1[^\n]%[^,\n],", content); 

den Rückgabewert überprüfen Sie sicher sein, zu bestimmen, ob irgendetwas zu vergeben wurde content. Es wird 1 sein, wenn eine nicht leere Zeichenfolge übereinstimmte und content zugewiesen wurde (nach dem Zuordnen, aber nicht Zuweisen der führenden Zeilenumbruch), -1, wenn die Datei f anfänglich an seinem Ende positioniert war oder wenn ein E/A-Fehler auftritt, oder 0 if vor dem Zuweisen von content tritt ein übereinstimmender Fehler auf.

aktualisieren:

Wie @chux beobachtet, das scanf Format oben ist nichts zum Schutz gegen die Grenzen des content im Fall Überholkupplung, dass die entsprechenden Daten sind breiter als es aufnehmen kann.Da Sie es als ein Array von 100 char sind zu erklären, kann es bis zu 99 Zeichen aufnehmen und einen Terminator, die Sie wie so überlaufen ist nicht sichergestellt werden kann:

fscanf(f, "%*1[^\n]%99[^,\n],", content); 

, dass Sie mit der Möglichkeit lässt, dass das Scannen stoppt Es wird jedoch entweder ein Zeilenumbruch oder ein Komma angezeigt, und der Rückgabewert hilft Ihnen nicht, diesen Fall von einem vollständig erfolgreichen Scan zu unterscheiden. In diesem Fall führt der Scan next zu einem übereinstimmenden Fehler (unter der Annahme, dass dasselbe Format verwendet wird). Es gibt mehr als eine Möglichkeit, das zu beheben, aber Sie sollten in Erwägung ziehen, das nachgestellte Komma aus Ihrem Format zu entfernen und stattdessen nach einem Komma zu suchen und es separat über einen Aufruf an fgetc() zu konsumieren.

+3

Ermutigen Sie, ein Breitenlimit wie '"% * 1 [^ \ n]% 99 [^, \ n] "zu aktivieren, um eine" gets() "- ähnliche Schwachstelle zu vermeiden. – chux

+0

Vielen Dank! Ich hatte das Problem mit dem Raum nicht erkannt. Und ja, ich verwende den Wert, den fscanf zurückgibt. –

+0

Gute Beobachtung, @chux. Antwort aktualisiert –

0

Und Sie müssen fscanf() verwenden, weil ...?

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

size_t myScan (
    const char * string, 
    char * outBuffer, 
    size_t outBufferMax 
) { 
    // No string 
    if (!string) return 0; 
    // First char not a space 
    if (string[0] != ' ') return 0; 
    // Find semicolon 
    size_t size = 0; 
    while (string[size + 1] != 0 && string[size + 1] != ';') size++; 
    // Doesn't fit into buffer! 
    if (size > outBufferMax) return 0; 

    memcpy(outBuffer, &string[1], size); 
    return size; 
} 


int main () { 
    size_t size = 0; 
    char content[100] = { 0 }; 
    char * test = " Hello World; Test Test; Foobar!"; 

    size = myScan(test, content, sizeof(content)); 
    printf("###%.*s###\n", (int)size, content); 

    size = myScan(&test[6], content, sizeof(content)); 
    printf("###%.*s###\n", (int)size, content); 

    size = myScan(&test[13], content, sizeof(content)); 
    printf("###%.*s###\n", (int)size, content); 

    size = myScan(&test[24], content, sizeof(content)); 
    printf("###%.*s###\n", (int)size, content); 

    // No position with a space in front! 
    size = myScan(&test[22], content, sizeof(content)); 
    printf("###%.*s###\n", (int)size, content); 


    return 0; 
} 

Ausgang:

###Hello World### 
###World### 
###Test Test### 
###Foobar!### 
###### 
+0

Weil es ein Ausschnitt für Null-Erfahrung Menschen ist, und ich bevorzuge, es einfach zu halten. –

+0

@ nessa.gp Ich habe C-Code geschrieben und arbeite seit vielleicht zwei Jahrzehnten an C-Projekten und habe die 'fscan()' -Syntax, die du in der Frage gepostet hast, nie geschrieben oder gesehen. Wie also ist das "einfach" und für Menschen mit "Null-Erfahrung", wenn nicht einmal C-Veteranen diese Syntax kennen? Und wie kann etwas einfach sein, wenn Sie hierher kommen und um Hilfe bitten müssen, weil Sie selbst nicht die richtige Syntax herausfinden können? Entschuldigung, aber das scheint mir unlogisch. – Mecki

+0

Ich habe wenig Erfahrung mit C. Ich wollte nur herausfinden, ob es einen Weg gibt, es zu tun. Ich war überrascht, dass, wenn Sie einen Charakter mit einer besonderen Bedeutung haben, es keine Möglichkeit gibt, dieses Verhalten zu blockieren und nur den ursprünglichen Charakter zu haben, etwas ähnlich wie% und %%, aber mit dem Leerzeichen. –

Verwandte Themen