2009-08-24 88 views
27

Tôi nhận thấy rằng câu hỏi này có thể đã được hỏi vài lần trong quá khứ, nhưng tôi sẽ tiếp tục bất kể.Chuyển đổi chuỗi có chứa một số thành số nguyên

Tôi có một chương trình sắp nhận được một chuỗi số từ đầu vào bàn phím. Các con số sẽ luôn ở dạng "66 33 9" Về cơ bản, mỗi số được phân tách bằng dấu cách và đầu vào của người dùng sẽ luôn chứa số lượng khác nhau của các số.

Tôi biết rằng việc sử dụng 'sscanf' sẽ hoạt động nếu số lượng các số trong mỗi chuỗi do người dùng nhập là không đổi, nhưng đây không phải là trường hợp của tôi. Ngoài ra, vì tôi mới sử dụng C++, tôi thích xử lý các biến 'chuỗi' hơn là các mảng ký tự.

+6

IMO thường thích 'std :: stri ng' trên bộ đệm ký tự thô không phải là dấu hiệu của "newbieness", mà là sự trưởng thành. – sbi

Trả lời

29

Tôi giả sử bạn muốn đọc toàn bộ dòng và phân tích cú pháp đó làm đầu vào. Vì vậy, trước hết lấy dòng:

std::string input; 
std::getline(std::cin, input); 

Bây giờ đưa rằng trong một stringstream:

std::stringstream stream(input); 

và phân tích

while(1) { 
    int n; 
    stream >> n; 
    if(!stream) 
     break; 
    std::cout << "Found integer: " << n << "\n"; 
} 

Hãy nhớ bao gồm

#include <string> 
#include <sstream> 
+18

Bạn có nghĩa là phân tích cú pháp: 'int n; while (stream >> n) {std :: cout << "Số nguyên tìm thấy:" << n << "\ n";} '? Sạch hơn nhiều –

1

Here is cách chia chuỗi của bạn thành chuỗi dọc theo khoảng trắng. Sau đó, bạn có thể xử lý từng cái một.

0

Hãy thử strtoken để tách chuỗi đầu tiên, sau đó bạn sẽ xử lý từng chuỗi.

2
#include <string> 
#include <vector> 
#include <sstream> 
#include <iostream> 
using namespace std; 

int ReadNumbers(const string & s, vector <int> & v) { 
    istringstream is(s); 
    int n; 
    while(is >> n) { 
     v.push_back(n); 
    } 
    return v.size(); 
} 

int main() { 
    string s; 
    vector <int> v; 
    getline(cin, s); 
    ReadNumbers(s, v); 
    for (int i = 0; i < v.size(); i++) { 
     cout << "number is " << v[i] << endl; 
    } 
} 
8
#include <string> 
#include <vector> 
#include <iterator> 
#include <sstream> 
#include <iostream> 

int main() { 
    std::string input; 
    while (std::getline(std::cin, input)) 
    { 
     std::vector<int> inputs; 
     std::istringstream in(input); 
     std::copy(std::istream_iterator<int>(in), std::istream_iterator<int>(), 
     std::back_inserter(inputs)); 

     // Log process: 
     std::cout << "Read " << inputs.size() << " integers from string '" 
     << input << "'" << std::endl; 
     std::cout << "\tvalues: "; 
     std::copy(inputs.begin(), inputs.end(), 
     std::ostream_iterator<int>(std::cout, " ")); 
     std::cout << std::endl; 
    } 
} 
+3

+1 khi bạn thay thế 1000 "std ::" s bằng một "không gian tên sử dụng tiêu chuẩn duy nhất"; và đề cập đến các tiêu đề bạn cần. –

+5

+1 miễn là bạn giữ tiền tố 'std ::'. Khả năng đọc của họ là chủ quan (tôi, được sử dụng cho họ, tìm thấy nó tốt hơn để đọc), nhưng sự rõ ràng nâng cao thông qua tên đầy đủ là mục tiêu. – sbi

+0

+1 sau khi thay thế bằng 'sử dụng không gian tên'. Sau đó, bạn có thể thay thế triển khai với một số khác và không cần phải đối phó với việc thay đổi không gian tên. – nothrow

1
// get string 
std::string input_str; 
std::getline(std::cin, input_str); 

// convert to a stream 
std::stringstream in(input_str); 

// convert to vector of ints 
std::vector<int> ints; 
copy(std::istream_iterator<int, char>(in), std::istream_iterator<int, char>(), back_inserter(ints)); 
1

giải pháp chung cho các giá trị unsigned (đối phó với tiền tố '-' mất một bool thêm):

template<typename InIter, typename OutIter> 
void ConvertNumbers(InIter begin, InIter end, OutIter out) 
{ 
    typename OutIter::value_type accum = 0; 
    for(; begin != end; ++begin) 
    { 
     typename InIter::value_type c = *begin; 
     if (c==' ') { 
      *out++ = accum; accum = 0; break; 
     } else if (c>='0' && c <='9') { 
      accum *= 10; accum += c-'0'; 
     } 
    } 
    *out++ = accum; 
     // Dealing with the last number is slightly complicated because it 
     // could be considered wrong for "1 2 " (produces 1 2 0) but that's similar 
     // to "1 2" which produces 1 0 2. For either case, determine if that worries 
     // you. If so: Add an extra bool for state, which is set by the first digit, 
     // reset by space, and tested before doing *out++=accum. 
} 
+0

+1 vì bạn trả lời câu hỏi như đã nêu ("số nguyên"), nhưng tôi nghĩ đây thực sự là một bước theo hướng ít chung chung hơn trong một số khía cạnh rõ ràng chỉ làm việc cho các số nguyên và không phải loại khác (IOW: "genericity" của "typename OutIter :: value_type accum = 0;" được phóng đại). Bạn sẽ xử lý các số dấu phẩy động như thế nào? Nếu bạn muốn viết một mini-lexer, đừng quên xử lý ký hiệu khoa học và Inf, NaN, vv –

+0

Vâng, nó sẽ chấp nhận 'short []', 'std :: vector ' và 'std :: list 'hoặc trên thực tế bất kỳ loại tích phân nào khác (bao gồm cả các loại được xác định thực hiện). Đồng bằng 0 sẽ chuyển đổi thành tất cả. Lý do tôi sử dụng valuetype vì vậy tôi sẽ không vô tình tràn một 'int' khi người dùng chuyển thành' __int128 [] 'và một chuỗi có số lớn. – MSalters

+0

Sử dụng value_type để tích lũy là hoàn toàn đúng cách để đi, nhưng tôi đoán tôi không thấy lý do tại sao bạn không thể chỉ sử dụng một istringstream thay vì lexer thủ công của riêng bạn. Sau đó, bạn có thể làm việc với bất kỳ loại nào được hiểu bởi toán tử <<() (tức là cải tiến "máy đánh chữ") mà không phải hy sinh tính chất "lặp đi lặp lại" của giải pháp hiện tại của bạn. Tôi cũng nghi ngờ rằng có nhiều khả năng làm việc với ký tự rộng, miền địa phương, v.v. –

18

Các C++ String Toolkit Library (Strtk) có giải pháp sau để vấn đề của bạn:

#include <iostream> 
#include <string> 
#include <deque> 
#include <algorithm> 
#include <iterator> 

#include "strtk.hpp" 

int main() 
{ 
    std::string s = "1 23 456 7890"; 

    std::deque<int> int_list; 
    strtk::parse(s," ",int_list); 

    std::copy(int_list.begin(), 
      int_list.end(), 
      std::ostream_iterator<int>(std::cout,"\t")); 

    return 0; 
} 

Bạn có thể tìm thêm các ví dụ khác Here

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