2016-07-09 3 views
0

diese Frage mit einer Antwort eingebaut kommt, aber ich wollte trotzdem diese kleine Kriegsgeschichte teilen über die Chance, es jemand anderes helfen könnte ...Umwandlung gelingt mit _stscanf_s C-Library-Funktion, aber nicht tatsächlich

Gegeben eine Eingabe von "20160708", Siehst du, was mit den folgenden C-Anweisungen falsch ist? Diese werden von einigen Code exzerpiert, die überprüft, ob ein Software-Update verfügbar ist ...

struct tm ParseTime; 
memset(&ParseTime, 0, sizeof(ParseTime)); 

// Extract date information 
int ScanResult = _stscanf_s(UTCDate, _T("%4i%2i%2i"), 
    &ParseTime.tm_year, &ParseTime.tm_mon, &ParseTime.tm_mday); 

if (ScanResult != 3) 
    DEBUG_MESSAGE(MB_OK | MB_ICONERROR, _T("Debug: Unexpected Error"), 
    _T("ConvertUTCDateTime - could not scan UTCDate = '%s', ScanResult = %d"), 
    UTCDate, ScanResult); 

Wir haben nicht entweder, auf den ersten. Und der obige Code hat den Systemtest viele Male bestanden.

Aber am 8. Juli verursachte es eine Ausnahme in der späteren assert-Anweisung, ohne die DEBUG_MESSAGE auszugeben.

Debugging zeigte, dass, obwohl ScanResult mit dem erwarteten Wert von 3 geladen wurde, 3 Felder erfolgreich konvertiert, wurde das ParseTime.tm_mday Feld tatsächlich mit 0 geladen, eine ungültige Monatszahl!

Aber der 'i' Formatbezeichner gibt "Integer" an, richtig? Also, was ist das Problem?

+0

* Aber die 'i' Formatspezifizierer zeigt "Integer", richtig? Also, was ist das Problem? * Wie Sie herausgefunden haben, erlaubt es verschiedene Zahlenbasen, zu einem 'int' eingegeben zu werden. Vergessen Sie niemals [Murphys Gesetz] (https://en.wikipedia.org/wiki/Murphy%27s_law), insbesondere da andere Benutzer ihre eigenen Ideen haben, welche Daten eingegeben oder eingegeben werden sollen. –

Antwort

0

es uns kam es nachzuschlagen ...

Von C-Bibliothek Dokumentation (https://msdn.microsoft.com/en-us/library/6ttkkkhh.aspx)

i - An integer. 

Hexadecimal if the input string begins with "0x" or "0X", 
octal if the string begins with "0", otherwise decimal. 

Okay, "Eine ganze Zahl". Das ist in Ordnung, oder?

Aber ...

Lesen Sie die ganze Beschreibung ... OCTAL?!? Was wir hier haben, ist ein Rückfall in die 1970er Jahre!

Das ist richtig, das '0' Zeichen bewirkt, dass die Konvertierung auf Oktal umschaltet, und geht weiter und konvertiert auf Null. Dann endet die Konvertierung auf dem ungültigen (für Oktal) "8" oder "9" Zeichen, was bedeutet, dass der obige Code auf die schlechteste Weise nur am 8. und 9. des Monats oder im 8. oder 9. Monat scheitert!

Es ist fraglich, ob scanf mit einer "% 2i" -Formatspezifikation eine Konvertierung von "08" oder "09" als erfolgreich erachten sollte, aber tatsächlich - mit der aktuellen Microsoft CRT-Bibliothek sowieso.

Die Fehlerbehebung, natürlich, verwenden Sie "% 4u% 2u% 2u" für den Format-Spezifizierer, der explizit die Dezimal-Konvertierung wählt.

Moral der Geschichte ... Lesen Sie immer den ganzen Weg bis zum Ende des Absatzes.

Entweder das oder nicht neue Software am 8. oder 9. des Monats oder im August oder September freigeben. :-)

+1

Der PDP-11 wirft einen langen, langen Schatten. Achten Sie auf den Unterschied zwischen% i und% d. –

Verwandte Themen