2013-04-30 157 views
1

我一直在試圖製作一個解析文本文件並將6條信息提供給對象數組的程序。對我而言,問題在於我遇到了如何處理文本文件的問題。我被告知,我需要做的第一步是編寫一些代碼,計算每個條目有多少個字母。該TXT文件的格式如下:使用strtok()解析文本文件

"thing1","thing2","thing3","thing4","thing5","thing6" 

這是我的代碼的當前版本:

#include<iostream> 
#include<string> 
#include<fstream> 
#include<cstring> 

using namespace std; 

int main() 
{ 
ifstream myFile("Book List.txt"); 

while(myFile.good()) 
{ 
    string line; 

    getline(myFile, line); 

    char *sArr = new char[line.length() + 1]; 
    strcpy(sArr, line.c_str()); 

    char *sPtr; 

    sPtr = strtok(sArr, " "); 

    while(sPtr != NULL) 
    { 
     cout << strlen(sPtr) << " "; 
     sPtr = strtok(NULL, " "); 
    } 
    cout << endl; 
} 
myFile.close(); 
return 0; 
} 

因此,有兩件事情讓我很難現在。

1)如何處理分隔符?

2)我如何處理「跳過」每行中的第一個引號?

回答

1

讀取字符串而不是c樣式的字符串。這意味着你可以使用方便的std方法。

std::string::find()方法應該可以幫助你找到你想要解析的每一件事情。

http://www.cplusplus.com/reference/string/string/find/

您可以用它來找到所有的逗號,這將給你的所有事情的開始。

然後,您可以使用std::string::substr()將字符串切分爲每個部分。

http://www.cplusplus.com/reference/string/string/substr/

你能設法得到通過傳遞比開始1以上,比事物的長度少1去掉引號的,你也可以使用

1

如果你必須使用strtok那麼這個代碼段應給予足夠的修改程序來解析您的數據:

#include <cstdio> 
#include <cstring> 

int main() 
{ 
    char str[] ="\"thing1\",\"thing2\",\"thing3\",\"thing4\",\"thing5\""; 
    char * pch; 
    printf ("Splitting string \"%s\" into tokens:\n",str); 
    pch = strtok (str,"\","); 
    while (pch != NULL) 
    { 
    printf ("%s\n",pch); 
    pch = strtok (NULL, ",\""); 
    } 
    return 0; 
} 

如果你沒有使用strtok那麼你應該使用std::string正如其他有dvised。使用std::stringstd::istringstream

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

int main() 
{ 
    std::string str2("\"thing1\",\"thing2\",\"thing3\",\"thing4\",\"thing5\"") ; 

    std::istringstream is(str2); 
    std::string part; 

    while (getline(is, part, ',')) 
    std::cout << part.substr(1,part.length()-2) << std::endl; 

    return 0; 
} 
+0

將如何我完成了我使用std :: string必須做的事情?你能走過我嗎? – Sam 2013-04-30 02:17:12

+0

@Sam增加了更多細節 – 2013-04-30 02:39:32

1

對於初學者來說,不使用strtok,如果你能避免它(你很容易可以在這裏 - 你甚至可以儘量避免使用find一系列的功能一樣)。

如果你想在全行讀取,然後分析它:

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

// defines a new ctype that treats commas as whitespace 
struct csv_reader : std::ctype<char> 
{ 
    csv_reader() : std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask()); 
     rc['\n'] = std::ctype_base::space; 
     rc[','] = std::ctype_base::space; 
     return &rc[0]; 
    } 
}; 

int main() 
{ 
    std::ifstream fin("yourFile.txt"); 
    std::string line; 
    csv_reader csv; 
    std::vector<std::vector<std::string>> values; 
    while (std::getline(fin, line)) 
    { 
     istringstream iss(line); 
     iss.imbue(std::locale(std::locale(), csv)); 
     std::vector<std::string> vec; 
     std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(vec)); 
     values.push_back(vec); 
    } 
    // values now contains a vector for each line that has the strings split by their commas 
    fin.close(); 
    return 0; 
} 

,回答你的第一個問題。關於你的第二,你可以將它們添加到rc面具(也把他們當作空格)跳過所有的引號,也可以(直接或通過使用transform)之後帶他們出去:

std::transform(vec.begin(), vec.end(), vec.begin(), [](std::string& s) 
{ 
    std::string::iterator pend = std::remove_if(s.begin(), s.end(), [](char c) 
    { 
     return c == '"'; 
    }); 
    s.erase(pend, s.end()); 
});