2013-03-07 41 views
0

所以我見過很多人問這個,並沒有很多固定的答案在網上浮動。大多數情況下只檢查一個整數是否放置在一個字符串的位置,但如果輸入了一個浮點數,則會截斷下半部分,或者如果整數和字符被識別,則會截斷字符。我需要幫助編寫一段代碼來檢查用戶輸入,並要求用戶在他的輸入無效或有效/無效的組合時重試。我認爲基本的想法是創建一個字符串,因此它接受任何東西,然後使用sstream來操縱,然後回到int如果輸入是合法的,但我無法真正設法檢查其他部分。如果任何人遇到這種情況,或者可以幫助我,請將我鏈接到它。當我很好地瞭解要做什麼時,我會發布我的代碼。檢查在c + +中的合法整數輸入

+1

Boost的'lexical_cast'失敗的任何類雙重表示整數。 – chris 2013-03-07 15:33:11

+0

我不想使用外部庫,因爲我們不允許爲任務安裝外部庫。 btw仍然是一名學生。 – 2013-03-07 15:36:32

+0

在這種情況下,您可以檢查整個字符串是否被轉換。我知道這裏有一個很好的例子。 – chris 2013-03-07 15:37:31

回答

2

假設你不能使用boost::lexical_cast,你可以寫你自己的版本:

#include <sstream> 
#include <iostream> 
#include <stdexcept> 
#include <cstdlib> 
template <class T1, class T2> 
T1 lexical_cast(const T2& t2) 
{ 
    std::stringstream s; 
    s << t2; 
    T1 t1; 
    if(s >> std::noskipws >> t1 && s.eof()) { 
    // it worked, return result 
    return t1; 
    } else { 
    // It failed, do something else: 
    // maybe throw an exception: 
    throw std::runtime_error("bad conversion"); 
    // maybe return zero: 
    return T1(); 
    // maybe do something drastic: 
    exit(1); 
    } 
} 



int main() { 
    std::string smin, smax; 
    int imin, imax; 

    while(std::cout << "Enter min and max: " && std::cin >> smin >> smax) { 
    try { 
     imin = lexical_cast<int>(smin); 
     imax = lexical_cast<int>(smax); 
     break; 
    } catch(std::runtime_error&) { 
     std::cout << "Try again: "; 
     continue; 
    } 
    } 

    if(std::cin) { 
    std::cout << "Thanks!\n"; 
    } else { 
    std::cout << "Sorry. Goodbye\n"; 
    exit(1); 
    } 
} 
+0

這似乎是工作,但我的理解你做什麼是有點關閉。 – 2013-03-07 16:07:20

+0

所以這個頭文件接受模板t2並將其存儲在稱爲s的字符串流中。然後你將t1和if語句存儲區中的元素聲明爲noskipws(不知道這是什麼,我認爲它是爲了計算空白空間),然後將它存儲在t1中,只要s已經結束。 – 2013-03-07 16:16:08

+0

沒有「標題」。 ''lexical_cast'是一個函數模板,正如你所說的那樣,它將參數't2'存儲到'stringstream'中,然後從同一個字符串流中提取它的返回值't1'。其他一切都在檢查錯誤情況。 – 2013-03-07 16:19:01

1

C函數strtol(和它的兄弟姐妹)將能夠告訴你,如果它的字符串是完全消耗。

std::string str; 
char *endptr; 
std::cin >> str; 
long x = std::strtol(str.c_str(), &endptr, 0); 
if (*endptr != 0) 
    cout << "That's not a valid number..."; 
+0

這是說普通整數也不是數字,如果輸入字符或字符串,它也會崩潰。 – 2013-03-07 15:50:10

+0

添加缺少*使其工作... – 2013-03-07 15:51:08

2

您可以使用C++ 11 string conversion functions像短距起降

try 
{ 
    std::string value = ...; 
    long number = std::stol(value); 
} 
catch (std::invalid_argument const& e) 
{ 
    // no conversion could be performed 
} 

後評論更新:隨Visual Studio 2012一起提供的Visual C++ 11實現了std::stol作爲在<cstdlib>中聲明的strtol的方便包裝。我認爲可以肯定的是大多數C++ 11實現都以最優化的方式定義它,而不是達到std::stringstream機器。

+1

你有沒有機會看看它是如何實現的?我還沒有機會。希望不是字符串流,而是更像'strtol'。 – 2013-03-14 03:03:09

+0

@VladLazarenko好點,我根據我的發現更新了我的答案。 – mloskot 2013-03-14 11:46:24

0

我不知道是否有標準的C++的lib轉換時encapsule原始類型,如Java編寫,但這裏簡單,很基本實現會是什麼樣子

class Integer { 
    private: 
     int value; 
     void parse(string); 
    public: 
     Integer(string); 
     int intValue(); 
}; 

Integer::Integer(string sint) { parse(sint); } 
int Integer::intValue() { return value; } 

void Integer::parse(string sint) { 
    string::iterator its = sint.begin(); 
    while(its != sint.end() && (! (*its < '0' || *its > '9'))) { 
     its++; 
    } 
    if(its != sint.end()) { 
     throw sint + ": Input is not a valid integer."; 
    } 
    value = atoi(sint.c_str()); 
}