2013-04-30 91 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()); 
});