Я пытаюсь удалить комментарии из своего файла .txt. Мой текстовый файл выглядит так:

(* Sunspot data collected by Robin McQuinn from *)
(* http://sidc.oma.be/html/sunspot.html         *)

(* Month: 1749 01 *) 58
(* Month: 1749 02 *) 63
(* Month: 1749 03 *) 70
(* Month: 1749 04 *) 56

Комментарии - это все между (* и *). Мне нужно сохранить только 58,63,70 и 56 из этого файла.

Мой код удаляет некоторые символы, но неправильно. Мой код выглядит так:

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <string>
#include <cctype>
#include <numeric>
#include <iomanip>

using namespace std;

int main() {

    int digit = 1;
    string filename;
    //cout for getting user path
    //the compiler parses string literals differently so use a double backslash or a forward slash
    cout << "Enter the path of the data file, be sure to include extension." << endl;
    cout << "You can use either of the following:" << endl;
    cout << "A forwardslash or double backslash to separate each directory." << endl;
    getline(cin, filename);

    //gets file
    ifstream infile{filename};
    istream_iterator<char> infile_begin{ infile };
    istream_iterator<char> eof{};
    vector<char> file{ infile_begin, eof };

    for(int i =0; i < file.size(); i++){
    if(!isdigit(file[i])) {
        if(file[i] != ')') {
            file.erase(file.begin(),file.begin()+i);
        }
    }
    }
    copy(begin(file), end(file), ostream_iterator<char>(cout, " "));
    }

Не следует ли мне использовать vector.erase()? Я знаю, что это неправильно в этом коде. Если это так, то какое решение лучше? Я знаю, что в C вы можете записать его в память и перейти к каждому месту, это будет лучший способ?

4
I'm here for Winter Hats 7 Сен 2016 в 18:25

3 ответа

Лучший ответ

Сначала я бы сохранил все как строку, подготовил бы строку и затем безопасно отправил бы результат в вектор. Теперь я использовал std :: regex для фильтрации вашего файла. Но это не самый простой способ.

#include <iostream>
#include <string>
#include <regex>
#include <fstream>

int main(){

    std::string file_name;
    std::cout << "Enter name/path of the txt file: ";
    std::getline(std::cin, file_name);
    std::ifstream file(file_name);

    std::vector<int> vec; //here save integers

    std::string text; //save current line here


    std::smatch match; //here the found "comment" get's saved, later to be removed from text

    std::regex remove("[\(\*]\.*[\*\)] *"); //the expression to search for
    //translation
    //     _[\(\*]   -> (*
    //     _\.*      -> any number of characters
    //     _[\*\)]   -> *)
    //     _ *       -> any number of whitespaces (important to cast to integer)..



    while (std::getline(file, text)){ //loop through all lines in file.txt

        if (std::regex_search(text, match, remove)){ //if a comment was found
            text.erase(text.begin(), text.begin() + match[0].length()); //remove the comment
        }

        if (!text.empty()) { //empty, line was a pure comment
            vec.push_back(std::stoi(text)); //else add integer to list
        }
    }


    std::cout << "The file contains:" << std::endl;
    for (int i = 0; i < vec.size(); i++){
        std::cout << vec.at(i) << std::endl;
    }

    return 0;
}

Выход:

Enter name/path of the txt file: file.txt
The file contains:
58
63
70
56

Конечно, использование std::stoi работает только в том случае, если нет символов после целого числа. Что ж, это всего лишь идея и, конечно же, ее можно изменить.

4
Stack Danny 7 Сен 2016 в 17:56

Вы можете использовать std :: getline, чтобы читать после закрытия {{X0 }}, то вы знаете, что следующее чтение будет вашим номером:

int main()
{
    std::ifstream ifs("test.txt");

    std::string line;
    while(std::getline(ifs, line)) // line by line
    {
        std::string skip;
        int value;

        // skip data upto and past ')', then read number
        if(std::getline(std::istringstream(line), skip, ')') >> value)
            std::cout << "found: " << value << '\n';
    }
}

Вывод:

found: 58
found: 63
found: 70
found: 56
0
Galik 11 Сен 2016 в 14:14

Как вы заметили, логика неверна. Вы удаляете символы с начала, если текущий символ не является цифрой или ).

Что вы, вероятно, захотите сделать, так это удалить комментарии, так почему бы не найти начало (* и конец *) и не удалить все, что находится между ними?

std::vector<std::string> fileContent;
std::string line;
while (std::getline(infile, line))
{
    //Find starting character sequence
    auto begin = line.find("(*");
    if (begin != std::string::npos)
    {
        //Find matching ending sequence, it's not a comment otherwise
        auto end = line.find("*)", begin);
        if (end != std::string::npos)
            line.erase(line.begin() + begin, line.begin() + end + 2);
    }

    fileContent.push_back(line);
}
2
Rakete1111 7 Сен 2016 в 16:09