2012-04-29 17 views
13

Trong mã C++ của tôi, tôi muốn đọc từ một tệp văn bản (* .txt) và mã hóa mọi mục nhập. Cụ thể hơn, tôi muốn có thể đọc các từ riêng lẻ từ một tệp, chẳng hạn như "định dạng", "ngăn xếp", "Jason", "châu Âu", vv.Làm cách nào tôi có thể sử dụng dấu phân cách không mặc định khi đọc tệp văn bản với std :: fstream?

Tôi đã chọn sử dụng fstream để thực hiện tác vụ này và tôi không biết cách đặt dấu phân cách cho ký tự tôi muốn sử dụng (khoảng trắng, \n, cũng như dấu gạch nối và thậm chí dấu nháy đơn như trong "Mcdonal's"). Tôi thấy không gian và \n là dấu phân cách mặc định, nhưng dấu gạch ngang không, nhưng tôi muốn coi chúng là dấu phân cách để khi phân tích tệp, tôi sẽ nhận được từ trong "blah blah xxx animal - cat" đơn giản là "blah", "blah", "xxx", "động vật", "mèo".

Tức là, tôi muốn có thể nhận được hai chuỗi từ "chồng tràn", "bạn", , và vẫn có thể duy trì \n và không gian làm dấu phân cách cùng một lúc.

+0

đường nối (luồng, biến, dấu phân tách); –

+0

Bạn muốn lọc ra "động vật - mèo" vì nó chứa dấu gạch nối? Điều đó nghe có vẻ không giống với tôi. – Johnsyweb

+0

Tôi không cố gắng lọc chúng ra; Tôi đang cố đọc động vật và mèo như hai từ riêng biệt. – FrozenLand

Trả lời

16

Một xử lý istream "không gian trắng" như delimiters. Nó sử dụng một ngôn ngữ để cho nó biết ký tự là khoảng trắng. Một miền địa phương, lần lượt, bao gồm một ctype facet phân loại các loại ký tự. một khía cạnh như vậy có thể trông giống như thế này:

#include <locale> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 
#include <sstream> 

class my_ctype : public 
std::ctype<char> 
{ 
    mask my_table[table_size]; 
public: 
    my_ctype(size_t refs = 0) 
     : std::ctype<char>(&my_table[0], false, refs) 
    { 
     std::copy_n(classic_table(), table_size, my_table); 
     my_table['-'] = (mask)space; 
     my_table['\''] = (mask)space; 
    } 
}; 

Và một chương trình thử nghiệm nhỏ để hiển thị nó hoạt động:

int main() { 
    std::istringstream input("This is some input from McDonald's and Burger-King."); 
    std::locale x(std::locale::classic(), new my_ctype); 
    input.imbue(x); 

    std::copy(std::istream_iterator<std::string>(input), 
     std::istream_iterator<std::string>(), 
     std::ostream_iterator<std::string>(std::cout, "\n")); 

    return 0; 
} 

Kết quả:

This 
is 
some 
input 
from 
McDonald 
s 
and 
Burger 
King. 

istream_iterator<string> sử dụng >> để đọc các dây cá nhân từ luồng, vì vậy nếu bạn sử dụng trực tiếp, bạn sẽ nhận được kết quả tương tự. Các phần bạn cần đưa vào đang tạo ngôn ngữ và sử dụng imbue để làm cho luồng sử dụng ngôn ngữ đó.

+0

Vì vậy, bạn đang sử dụng studio trực quan? Tôi đặt mã trong studio trực quan (đúng) và nó không biên dịch ... – FrozenLand

+0

@ user1348863: Có, tôi đã thử nghiệm nó với Visual Studio 10. –

+1

Tuyệt vời! N.B: [** 'std :: copy_n()' **] (http://en.cppreference.com/w/cpp/algorithm/copy_n) là một C++ 11ism. Các trình biên dịch cũ hơn sẽ cần 'std :: copy (classic_table(), classic_table() + table_size, my_table);' (hoặc tương tự). – Johnsyweb

1

Bạn có thể sử dụng

istream::getline(char* buffer, steamsize maxchars, char delim) 

mặc dù điều này chỉ hỗ trợ một delimiter duy nhất. Để chia tách các dòng trên các dấu phân cách khác nhau của bạn, bạn có thể sử dụng

char* strtok(char* inString, const char* delims) 

có nhiều dấu phân cách. Khi bạn sử dụng strtok bạn chỉ cần vượt qua nó địa chỉ của bộ đệm của bạn lần đầu tiên - sau đó chỉ cần vượt qua trong một null và nó sẽ cung cấp cho bạn các mã thông báo tiếp theo từ nó đã cho bạn, trả về một con trỏ null khi không có hơn.

EDIT: Một thực hiện cụ thể sẽ là một cái gì đó giống như

char buffer[120]; //this size is dependent on what you expect the file to contain 
while (!myIstream.eofbit) //I may have forgotten the exact syntax of the end bit 
{ 
    myIstream.getline(buffer, 120); //using default delimiter of \n 
    char* tokBuffer; 
    tokBuffer = strtok(buffer, "'- "); 
    while (tokBuffer != null) { 
     cout << "token is: " << tokBuffer << "\n"; 
     tokBuffer = strtok(null, "'- "); //I don't need to pass in the buffer again because it remembers the first time I called it 
    } 
} 
+0

Vì vậy, bạn có thể cụ thể hơn không? Hãy nói rằng tôi muốn đọc stack-overflow như hai từ ngăn xếp riêng biệt và tràn, làm thế nào để làm điều này? (Tôi vẫn cần phải sử dụng không gian và \ n làm dấu phân cách cùng một lúc.) Ngoài ra, như, Hãy để cho và s. cảm ơn bạn! – FrozenLand

+0

Phiên bản đã chỉnh sửa phải được mã hóa trên \ n, ', - và không gian. – QuantumRipple

+0

Có vẻ tốt, nhưng nếu tệp của tôi là * .txt trong 1MB thì sao? Tôi phải đặt gì ở vị trí 120? – FrozenLand

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