2012-05-17 54 views
3

我有一個功能stoi這樣的:僅獲得一個簡單的數字在C/C++

static int *stoi(const char *c) { 
    int *r = new int[2]; 
    r[1] = sscanf(c, "%d", &r[0]); 
    return r; 
} 

當我給c = "a5"例如,它不工作。

當我給c = "543336535",它的工作原理。

但是,當我給c = "45sdfff-sdbsdf esg5sq4f"它將返回r[0] = 45,我不希望出現這種情況,因爲有一些非數字字符後,45 ...

我只希望我的函數讀取僅數字符串。

+3

選擇一個_single_語言 - C或C++? – ildjarn

+0

任何人,如果可能在C中,在C中,否則在C++中。 – gnidmoo

+0

'new int [2]'在C++中是一種很差的風格,使用'std :: array'或'std :: vector'。 – Fanael

回答

5

對最小的變化,你已經擁有的代碼,你可以使用的sscanf%n功能:

int chars_read; 
r[1] = sscanf(c, "%d%n", &r[0], &chars_read); 

如果chars_read小於字符串的長度,然後sscanf沒有消耗所有字符,所以字符串並不完全由一個整數組成。

The Linux documentation for scanf指出由Technical Corrigendum 1引入的附加示例與標準相矛盾,但與此同時,更新了標準以解決衝突。這裏是你如何解釋的sscanf實現不確定的行爲,面對結果,你可能會遇到:

switch (r[1]) { 
    case EOF: // empty string 
    break; 
    case 0: // doesn't start with numeric characters 
    break; 
    case 1: // starts with number; sscanf follows standards 
    case 2: // starts with number; sscanf follows TC1 
    if (c[chars_read] == '\0') 
     r[1] = 1; // we read entire string 
    else 
     r[1] = 0; // didn't read entire string; pretend we read nothing 
    break; 
    default: // shouldn't happen 
    assert(FALSE); 
} 
+0

感謝它現在的作品。 – gnidmoo

+0

['scanf' manpage](http://linux.die.net/man/3/scanf)警告不要使用'%n'格式的scanf返回值。設置'r [1] =(chars_read == strlen(c))'可能會更好。 – Dave

+0

謝謝你,@Dave。我認爲我的修訂版現在涵蓋了一切。如果沒有,請編輯。 –

3

如果你使用C,你可以使用strtol做可以稱之爲一個試探性的轉換。它會給你一個指向它可以轉換的數據結束的指針。如果這不是字符串的末尾,那麼無論它可以轉換,至少有一些垃圾。

如果您使用的是C++,您可能需要使用Boost lexical_cast,如果整個輸入轉換爲目標類型,將會成功,但如果其中任何一個未轉換,則會拋出異常。

相關問題