2009-09-27 27 views
5

Cách an toàn nhất và tốt nhất để truy xuất một ký tự dài chưa được ký từ một chuỗi trong C++ là gì?Làm thế nào để bạn nhận được một unsigned dài ra khỏi một chuỗi?

Tôi biết một số phương pháp có thể.

Đầu tiên, chuyển đổi thời lượng dài đã ký từ atol.

char *myStr; // Initalized to some value somehow. 
unsigned long n = ((unsigned)atol(myStr)); 

Vấn đề rõ ràng với điều này là, điều gì xảy ra khi giá trị được lưu trữ trong myStr lớn hơn ký dài có thể chứa? Atol lấy gì?

Khả năng tiếp theo là sử dụng strtoul.

char *myStr; // Initalized to some value somehow. 
unsigned long n = strtoul(myStr, 0, 10); 

Tuy nhiên, điều này hơi phức tạp hơn đối với nhu cầu của tôi. Tôi muốn một chức năng đơn giản, chuỗi trong, unsigned dài cơ sở 10 ra. Ngoài ra, xử lý lỗi lá nhiều để được mong muốn.

Khả năng cuối cùng tôi tìm thấy là sử dụng sscanf.

char *myStr; // Initalized to some value somehow. 
unsigned long n = 0; 
if(sscanf(myStr, "%lu", n) != 1) { 
    //do some error handling 
} 

Một lần nữa, xử lý lỗi lá nhiều mong muốn và phức tạp hơn một chút so với tôi muốn.

Tùy chọn hiển nhiên còn lại là viết trình bao bọc xung quanh một trong các khả năng trước đó hoặc một số thứ mà chu kỳ qua chuỗi và chuyển đổi thủ công từng chữ số cho đến khi đạt đến ULONG_MAX.

Câu hỏi của tôi là, các tùy chọn khác mà google-fu của tôi không tìm thấy được là gì? Bất cứ điều gì trong thư viện std C++ sẽ xóa sạch một chuỗi thành một unsigned long và throw exceptions về thất bại?

Lời xin lỗi của tôi nếu đây là sự lừa đảo, nhưng tôi không thể tìm thấy bất kỳ câu hỏi nào khớp chính xác với tôi.

+0

'atol':" Nếu giá trị chính xác nằm ngoài phạm vi giá trị thể hiện, LONG_MAX hoặc LONG_MIN được trả về ". http://www.cplusplus.com/reference/clibrary/cstdlib/atol/ –

+0

Vài câu hỏi, tôi không chắc chắn liệu chúng có trùng lặp hay không: (1) http://stackoverflow.com/questions/1243428/convert- string-to-int-với-bool-fail-in-c/1243435 (2) http://stackoverflow.com/questions/1435253/c-syntax-question-if-var-type-int/1435268 – GManNickG

+3

Tôi không 't hiểu những gì bạn có chống lại strtoul. Đó là chức năng hoàn hảo cho việc này. Vượt qua 0 cho cơ sở và nó sẽ chuyển đổi số với bất kỳ chuỗi tiền tố cơ sở nào mà thư viện C của bạn hiểu, như "0x". –

Trả lời

5

Một cách để làm điều đó:

stringstream(str) >> ulongVariable; 
+0

Tôi đã chỉnh sửa câu hỏi để làm rõ hơn rằng tôi đang làm việc với các chuỗi kiểu C trong trường hợp này. Vì vậy, điều này sẽ có được streamstream (string (myStr)) >> ulongvariable. Mà cảm thấy lãng phí một không hiệu quả với tôi:/Tôi muốn nó là một cái gì đó sạch hơn và thẳng hơn về phía trước. –

+1

Thực ra, điều đó không cần thiết bởi vì 'std :: string' có một hàm tạo ngầm, lấy một chuỗi kiểu C làm tham số. Hàm khởi tạo đó cho phép bạn viết chỉ 'chuỗi ký tự (" bất cứ điều gì ")'. – hrnt

+0

* smack self * Tất nhiên. Mặc dù vậy, nó có kết quả của instantiating hai lớp - và tất cả các quản lý bộ nhớ vốn có trong đó - để làm những gì một chức năng đơn giản với một vòng lặp nội bộ duy nhất nên có thể thực hiện. Tôi ước gì có thứ gì đó được xây dựng trong thư viện chuẩn. –

5

Bạn có thể sử dụng strtoul với không có vấn đề. Hàm trả về một unsigned long. Nếu hội tụ không thể thực hiện trả về hàm 0. Nếu giá trị dài chính xác nằm ngoài phạm vi hàm trả về ULONG_MAX và biến toàn cầu errno được đặt thành ERANGE.

+0

Tìm lỗi xử lý lỗi kiểu ngoại lệ thay vì kiểu errno nếu có thể. –

+0

Xử lý lỗi kiểu lỗi ngoại lệ nhưng không có phí thông qua lớp học? Âm thanh một chút nghịch lý imo :) –

+0

Vâng, các chức năng có thể xử lý lỗi kiểu lỗi ngoại lệ. Tôi chỉ không muốn tạo ra hai lớp mà tôi không cần mỗi lần tôi muốn chuyển đổi một thời gian dài. Có vẻ như rất lãng phí! –

4
template <class T> 
T strToNum(const std::string &inputString, 
      std::ios_base &(*f)(std::ios_base&) = std::dec) 
{ 
    T t; 
    std::istringstream stringStream(inputString); 

    if ((stringStream >> f >> t).fail()) 
    { 
     throw runtime_error("Invalid conversion"); 
    } 
    return t; 
} 


// Example usage 
unsigned long ulongValue = strToNum<unsigned long>(strValue); 
int intValue    = strToNum<int>(strValue); 

int intValueFromHex  = strToNum<int>(strHexValue,std::hex); 
unsigned long ulOctValue = strToNum<unsigned long>(strOctVal, std::oct); 
1

Jeffrey Stedfast has a beautiful post về cách viết trình phân tích cú pháp int cho Mono (trong C).
Nó tạo mã sử dụng các kiểu gốc (bạn cần 32 bit để phân tích cú pháp 32 bit) và mã lỗi cho tràn.

2

Nếu bạn có thể sử dụng thư viện tăng cường (www.boost.org) nhìn vào thư viện chuyển đổi - đó là một tiêu đề chỉ bao gồm

#include "boost/lexical_cast.hpp" 

sau đó tất cả các bạn cần làm là

unsigned long ul = boost::lexical_cast<unsigned long>(str); 
+0

Tôi sẽ xem xét các thư viện tăng cường, tôi đã xem xét sử dụng thư viện giải thích python để sử dụng boost có thể hoạt động tốt cho các nhu cầu của tôi. Nó sẽ được tốt đẹp nếu có một chức năng sạch đơn giản cho điều này mặc dù, đối với những người không muốn một sự phụ thuộc vào các thư viện tăng. –

0

cách mạnh mẽ sẽ viết một hàm tĩnh và sử dụng nó

bool str2Ulong(const string& str,unsigned long & arValue) 
{ 
    char *tempptr=NULL; 
    arValue=strtoul(str,tempptr,10); 

    return ! (arValue==0 && tempptr==str.c_str()); 

} 
+1

Ví dụ là sai, tempptr là (char *), strtoul mong đợi (char **) – nrathaus

1

Sử dụng chức năng "atol" trong xây dựng std

Ví dụ: std :: string input = "1024";

std :: atol (input.c_str());

Tham số dự kiến ​​sẽ là chuỗi loại c, vì vậy c_str() thực hiện điều đó cho bạn.

Các vấn đề liên quan