2016-04-08 11 views
1

Ich muss ein Array von Zeichen für ein bestimmtes einfaches Format überprüfen und die Werte von zwei Zahlen gleichzeitig in ihm erhalten. Das Nachrichtenformat lautet: START-Nummernummer ENDE. Alles, was ich mit war dies einfiel: Format prüfen und Zahlen erhalten mit sscanf C++

int x,y; 
if (sscanf(buffer, "START %d %d END", &x, &y) != 2) 
    return false; 
... 
... 
... 
return true; 

Aber natürlich

gelingt es auch nach der Beendigung völlig anders zu sein, weil die Zahlen erhalten wurden. Was ist der beste Weg, es zu tun? Danke für Anregungen.

+0

Es sieht so aus, als hätten Sie den Inhalt des Puffers und Ihre Zeichenfolge "START% d% d END" durcheinander gebracht. sscanf erwartet einen Puffer, der Ihre Zeichenkette und eine zweite Zeichenkette mit Ihren Formatdaten enthält, d. h. "ssscanf" ("START 9 10 ENDE", "% s% d% d% s", buff1, & x, & y, buff2) '. Was versuchst du zu machen ? – auburg

+0

Rufen Sie sscanf mit Formatierungszeichenfolge "START% d% d" auf und wenn alles OK ist, dann rufen Sie sscanf mit Formatierungszeichenfolge "% s" auf und vergleichen Sie das Ergebnis mit "END". – pointer

+0

@ auburg, die Formatdaten ** sind ** "START% d% d END", d. H. Die Zeichenfolge muss diese gewöhnlichen Zeichen enthalten. Die Verwendung von% s im scanf-Format ist gefährlich und sollte immer vermieden werden. Ihr Vorschlag wäre in Ordnung, wenn Sie% 5s und% 3s verwenden würden. –

Antwort

1

Nach Überprüfung des C-Standards bin ich erstaunt, dass es keine tragbare Möglichkeit gibt, dies zu erkennen.

Unter Linux errno wird gesetzt und Sie können auch ferror verwenden. Unter Windows errno wird auch festgelegt, aber MSDN erwähnt ferror nicht.


Man könnte dies für eine chaotisch, aber tragbare Lösung stattdessen tun:

int x,y; 
char d; 
if (sscanf(buffer, "START %d %d EN%c", &x, &y, &d) != 3 || 'D' != d) 
    return false; 
+0

'ferror' ist für' sscanf' irrelevant, weil es nicht aus einem Dateistream liest. –

+0

@ JonathanWakely sorry Ich las die Dokumentation für 'fscanf' nicht' sscanf'. – Simple

+0

Ihre Lösung schlägt fehl für "Puffer" hält ** START END ** –

0

Versuchen
int x, y; 
size_t pos = -1; 
char str[4]; 
if (sscanf(buffer, "START %d %d %3s%zn", &x, &y, str, &pos) != 3 || strcmp(pos, "END") || pos != strlen(buffer)) 
    return false; 
//... 
return true; 
1

Ich habe immer mühsam, die Verwendung von sscanf() und ähnlichen Funktionen gefunden. Obwohl die anderen Lösungen viel eleganter sind, bevorzuge ich einen einfacheren und leichter zu wartenden Code, der auf strtok() basiert. Hier ist ein kleines Programm zum Experimentieren mit:

#include <cstdio> 
#include <cstring> 

int main() 
{ 
    char buf[250]; 

    const char* delimiters=" \n"; 

    while(fgets(buf,250,stdin)!=nullptr){ 
     // fgets() reads the newline... 
     printf("%s",buf); 
     // Tokenize the buffer using 'delimiters'. The nullptr will re-use the same buffer. 
     char* pBegin = strtok(buf,delimiters); 
     char* pNumb1 = strtok(nullptr,delimiters); 
     char* pNumb2 = strtok(nullptr,delimiters); 
     char* pEnd = strtok(nullptr,delimiters); 
     // Protect our strcmp from a nullptr(missing data) and do some validity tests. 
     if((pEnd!=nullptr)&&(strcmp(pBegin,"BEGIN")==0)&&(strcmp(pEnd,"END")==0)){ 
      printf(" Begin = '%s'\n",pBegin); 
      printf(" Numb1 = '%s'\n",pNumb1); 
      printf(" Numb2 = '%s'\n",pNumb2); 
      printf(" End = '%s'\n",pEnd); 
     }else{ 
      printf(" Error!\n"); 
     } 
    } 
} 

und einige Testdaten (mit einigen Leerzeilen am Ende):

BEGIN 106 635 END 
BEGIN 107 636 END 
BEGaN 108 637 ENDING 
BeGIN 115 644 End 
BEGIN 116 645 END 
BEGIN 117 646 END of it all 
BEgIN 128 657 END 
BEGIN 129 658 END 
BEGIN 130 659 Finish 
131 660 END 
BEGIN 662 END 
BEGIN 136 665 
BEGIN 136 
BEGIN 

Und dies würde die Ausgabe sein ...

BEGIN 106 635 END 
    Begin = 'BEGIN' 
    Numb1 = '106' 
    Numb2 = '635' 
    End = 'END' 
BEGIN 107 636 END 
    Begin = 'BEGIN' 
    Numb1 = '107' 
    Numb2 = '636' 
    End = 'END' 
BEGaN 108 637 ENDING 
    Error! 
BeGIN 115 644 End 
    Error! 
BEGIN 116 645 END 
    Begin = 'BEGIN' 
    Numb1 = '116' 
    Numb2 = '645' 
    End = 'END' 
BEGIN 117 646 END of it all 
    Begin = 'BEGIN' 
    Numb1 = '117' 
    Numb2 = '646' 
    End = 'END' 
BEgIN 128 657 END 
    Error! 
BEGIN 129 658 END 
    Begin = 'BEGIN' 
    Numb1 = '129' 
    Numb2 = '658' 
    End = 'END' 
BEGIN 130 659 Finish 
    Error! 
131 660 END 
    Error! 
BEGIN 662 END 
    Error! 
BEGIN 136 665 
    Error! 
BEGIN 136 
    Error! 
BEGIN 
    Error! 

    Error!