2013-04-30 2 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::string и std::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

+0

@Sam добавлено больше деталей –

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()); 
}); 
Смежные вопросы