2009-03-16 36 views
7

Tôi đang làm việc trên một nhiệm vụ mà tôi phải đọc một tập tin và đếm số dòng và đồng thời đếm các từ trong đó. Tôi đã thử một sự kết hợp của getline và strtok bên trong một vòng lặp while, mà không hoạt động.Làm cách nào để tách tệp văn bản thành các từ?

tệp: example.txt (tệp cần đọc).

Xin chào, xin chào thật bất ngờ.
Chào mừng bạn đến với địa điểm này.
Có thể bạn có một kỳ nghỉ thú vị tại đây.
(3 dòng và một số từ).

Readfile.cpp

#include <iostream> 
#include <fstream> 
#include<string> 
using namespace std; 
int main() 
{ 
    ifstream in("example.txt"); 
    int count = 0; 

    if(!in) 
    { 
    cout << "Cannot open input file.\n"; 
    return 1; 
    } 

    char str[255]; 
    string tok; 
    char * t2; 

    while(in) 
    { 
    in.getline(str, 255); 
    in>>tok; 
    char *dup = strdup(tok.c_str()); 
    do 
    { 
     t2 = strtok(dup," "); 
    }while(t2 != NULL); 
    cout<<t2<<endl; 
    free (dup); 
    count++; 
    } 
    in.close(); 
    cout<<count; 
    return 0; 
} 
+0

Bạn cần phải nói nhiều hơn "không làm việc". Hãy cho chúng tôi biết bạn nhận được lỗi nào, hoặc điều CỤ THỂ mà chương trình của bạn thực hiện khác với bạn mong đợi, sau đó hỏi một câu hỏi cụ thể. Chúng tôi sẽ không gỡ lỗi hoặc viết lại bài tập về nhà cho bạn. – Blorgbeard

+17

Làm thế nào về một số ví dụ từ những điều sau đây: http://www.codeproject.com/KB/recipes/Tokenizer.aspx Họ rất hiệu quả và phần nào thanh lịch. Thư viện String Toolkit làm cho việc xử lý chuỗi phức tạp trong C++ đơn giản và dễ dàng. –

Trả lời

0

Hãy thử di chuyển tuyên bố cout<<t2<<end; bạn vào vòng lặp while của bạn.

Điều đó sẽ làm cho mã của bạn về cơ bản hoạt động.

Bạn có thể muốn xem this similar post để biết các cách tiếp cận khác.

0

Có những ví dụ như thế này được đăng trên internet. Đây là một chương trình đếm chữ mà tôi đã viết khi tôi còn học trung học. Sử dụng nó như là một điểm khởi đầu. Những điều khác tôi muốn chỉ ra là:

std :: stringstream: bạn std :: getline toàn bộ dòng, sau đó sử dụng std :: stringstream để cắt nhỏ thành các phần nhỏ hơn và mã hóa nó. Bạn có thể lấy toàn bộ dòng bằng cách sử dụng std :: getline và nhập nó vào một chuỗi std ::, sau đó bạn có thể chuyển tới std :: stringstream.

Một lần nữa, đây chỉ là một ví dụ và sẽ không thực hiện chính xác những gì bạn muốn, bạn sẽ cần phải sửa đổi nó để làm cho nó làm những gì bạn muốn nó làm!

#include <iostream> 
#include <map> 
#include <string> 
#include <cmath> 
#include <fstream> 

// Global variables 
     std::map<std::string, int> wordcount; 
     unsigned int numcount; 

void addEntry (std::string &entry) { 
     wordcount[entry]++; 
     numcount++; 
     return; 
} 


void returnCount() { 
     double percentage = numcount * 0.01; 
     percentage = floor(percentage + 0.5f); 

     std::map<std::string, int>::iterator Iter; 

     for (Iter = wordcount.begin(); Iter != wordcount.end(); ++Iter) { 
       if ((*Iter).second > percentage) { 
         std::cout << (*Iter).first << " used " << (*Iter).second << " times" << std::endl; 
       } 
     } 

} 

int main(int argc, char *argv[]) { 
     if (argc != 2) { 
       std::cerr << "Please call the program like follows: \n\t" << argv[0] 
         << " <file name>" << std::endl; 
       return 1; 
     } 

     std::string data; 

     std::ifstream fileRead; 
     fileRead.open(argv[1]); 
     while (fileRead >> data) { 
       addEntry(data); 
     } 
     std::cout << "Total words in this file: " << numcount << std::endl; 
     std::cout << "Words that are 1% of the file: " << std::endl; 
     returnCount(); 
} 
+0

Xin chào, Cảm ơn, Blorgbeard, Reed và X-Istence về các câu trả lời nhanh chóng. Tôi không cần phải phân tích cú pháp dòng, mà còn cần phải theo dõi đường lineNos. Câu lệnh vấn đề là tạo một danh sách các từ với các dòng mà chúng xuất hiện. –

+0

Ravi: Trong đó mã tôi vừa đưa cho bạn sẽ giúp bạn có một nửa ở đó. Chúng tôi không ở đây để làm bài tập về nhà cho bạn! –

+0

Ồ Không! Đó không phải là ý định của tôi. Tôi đang gặp rắc rối với phần đầu tiên. Một khi đó là cố định tôi có ý định làm phần còn lại của riêng tôi. –

5

Chỉ cần có quyền này !! Chỉ cần xóa tất cả các mã không cần thiết.

int main() 
{  
    ifstream in("example.txt"); 
    int LineCount = 0; 
    char* str = new char[500]; 

    while(in) 
    { 
     LineCount++; 
     in.getline(str, 255); 
     char * tempPtr = strtok(str," "); 
     while(tempPtr) 
     { 
      AddWord(tempPtr, LineCount); 
      tempPtr = strtok(NULL," ,."); 
     } 
    } 
    in.close(); 
    delete [] str; 
    cout<<"Total No of lines:"<<LineCount<<endl; 
    showData(); 

    return 0; 
} 

BTW tuyên bố vấn đề ban đầu là tạo chương trình chỉ mục chấp nhận tệp người dùng và tạo chỉ mục dòng của tất cả các từ.

+0

Vui lòng không sử dụng strtok. Nó sẽ trở lại để cắn bạn ngay sau khi bạn cần phải viết mã đa luồng. Một sự thay thế tốt với tiêu chuẩn C++ là std :: istringstream. – Tom

0

Nếu bạn có thể sử dụng thư viện tăng, tôi sẽ đề nghị sử dụng boost::tokenizer:

Việc tăng Tokenizer gói cung cấp một cách linh hoạt và dễ sử dụng để phá vỡ của một chuỗi hoặc ký tự khác chuỗi thành một loạt các thẻ. Dưới đây là một ví dụ đơn giản sẽ chia nhỏ cụm từ thành các từ.

// simple_example_1.cpp 
#include<iostream> 
#include<boost/tokenizer.hpp> 
#include<string> 

int main(){ 
    using namespace std; 
    using namespace boost; 
    string s = "This is, a test"; 
    tokenizer<> tok(s); 
    for(tokenizer<>::iterator beg=tok.begin();beg!=tok.end();++beg){ 
     cout << *beg << "\n"; 
    } 
} 
3

tôi đã không cố gắng biên soạn này, nhưng đây là một sự thay thế đó là gần như đơn giản như sử dụng Boost, nhưng nếu không có sự phụ thuộc thêm.

#include <iostream> 
#include <sstream> 
#include <string> 

int main() { 
    std::string line; 
    while (std::getline(std::cin, line)) { 
    std::istringstream linestream(line); 
    std::string word; 
    while (linestream >> word) { 
     std::cout << word << "\n"; 
    } 
    } 
    return 0; 
} 
+0

+1 Đó là cách tôi sẽ làm. Bây giờ chỉ cần chèn các quầy và nó được thực hiện. – Frank

0
ifstream is {"my_file_path"}; 
vector<string> b {istream_iterator<string>{is},istream_iterator<string>{}}; 

Dont quên này bao gồm:

<iterator> 
Các vấn đề liên quan