2012-03-13 7 views
1

Итак, я пытаюсь написать прогам, который выполняет ту же задачу, что и grep. В конце я хочу программу, которая принимает четыре аргумента, вторая - это то, что нужно искать, третье - входной файл, а четвертый - выходной файл. Я думаю, что у меня есть хорошее представление о том, как это сделать, но, как обычно, теория становится легкой, а фактическое программирование меня пугает. В основном, где я сейчас, у меня есть файл, и я пытаюсь его найти и получить все строки, содержащие то, что я ищу, а также строку этого номера.Перезапись grep в C++

Я хочу использовать вектор для достижения этой задачи. Я не совсем уверен, как это сделать. Было бы проще пройти и добавить каждую строку в вектор по отдельности, а затем пройти и выделить те, которые имеют нужную строку, и использовать их местоположение в качестве номера строки? Я хотел бы думать, что есть способ только добавить эти строки к вектору, который содержит нужную строку, но тогда я не уверен, как получить номер строки. Я начал пару раз, а затем стер, что я, когда понял, что все это неправильно.

Это где я в настоящее время:

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

using namespace std; 

int main (int argc, char* argv[]){ 

// validate the command line info 
if(argc < 2) { 
    cout << "Error: Incorrect number of command line arguments\n" 
      "Usage: grep\n"; 
    return EXIT_FAILURE; 
} 

//Declare the arguments of the array 
string query = argv[1]; 
string inputFileName = argv[2]; 
string outputFileName = argv [3]; 

// Validate that the file is there and open it 
ifstream infile(inputFileName); 
if(!infile) { 
    cout << "Error: failed to open <" << inputFileName << ">\n" 
      "Check filename, path, or it doesn't exist.\n"; 
    return EXIT_FAILURE; 
} 

else{ 
vector<string> queries; 


} 

} 

} 
+1

Не могли бы вы найти что-то более легкое, например, решение гипотезы Пуанкаре или гипотезы Римана? Вы действительно _seen_ код для обработки регулярных выражений? :-) – paxdiablo

+1

Re: * # include * Большая часть сложности grep приведена выше. Оригинальный автор 'grep' тоже написал эту часть. Что вы пишете, это всего лишь тривиальная оболочка API-интерфейса регулярных выражений. Стараться. :) – Kaz

+0

Каждый должен что-то начать. :) Спасибо за помощь, ребята. – Sh0gun

ответ

2

Там нет необходимости использовать вектор. Мне кажется, вы должны просто пройти через входной файл строки за раз, используя std :: getline, попытаться сопоставить каждый из них с регулярным выражением и вывести строки, которые будут успешными сразу.

+0

Понятно, что я действительно новичок в использовании выходных файлов, и планировал провести некоторое чтение на них сегодня вечером. Было бы легко помещать их все в выходной файл, используя этот метод? Кроме того, используя этот метод, как бы сохранить, какая строка номера, чтобы сохранить их с линией, которую я печатаю. Просто цикл, который использует итератор в качестве номера строки? – Sh0gun

+0

@ Sh0gun Да, вывод в файл ничем не отличается от того, выполняете ли вы это из 'vector ', вы заполнили или вывели каждую строку сразу после ее соответствия. Чтобы получить номера строк, у вас будет счетчик, чтобы отслеживать, какой номер строки вы обрабатываете, и когда строка соответствует вам, вы просто используете значение этого счетчика в качестве номера строки. – bames53

+1

@ Sh0gun Кроме того, похоже, что вам, возможно, придется работать до последней программы. Я предлагаю вам написать программу, которая просто перекликается с входным файлом в выходной файл по строкам. Затем измените его, чтобы включить номера строк. затем измените его снова, чтобы выводить только строки, которые соответствуют некоторому условию, например четному номеру строки. Затем измените условие, чтобы проверить, соответствует ли строка регулярному выражению. – bames53

1

Большая часть сложности с реализацией полного grep будет обрабатывать десятки флагов, чтобы изменить, как это работает. Упрощенная версия, которая не пытается поддерживать эти запросы и просто ищет набор файлов для указанного шаблона, может быть довольно простой. Вариант C++ 11 выглядит примерно так:

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

class line { 
    std::string data; 
public: 
    operator std::string() const { return data; } 

    friend std::istream &operator>>(std::istream &is, line &l) { 
     return std::getline(is, l.data); 
    } 
}; 

void process(std::regex const &pattern, std::istream &file) { 
    typedef std::istream_iterator<line> in; 
    typedef std::ostream_iterator<std::string> out; 

    std::copy_if(in(file), 
       in(), 
       out(std::cout, "\n"), 
       [&](std::string const &s) {return std::regex_search(s, pattern);}); 
} 

int main(int argc, char **argv) { 
    if (argc < 2) { 
     std::cerr << "Usage: grep <pattern> [file specification]"; 
     return 1; 
    } 

    std::regex pattern(argv[1], std::regex::nosubs | std::regex::optimize); 

    if (argc < 3) 
     process(pattern, std::cin); 
    else 
     for (int i=2; i<argc; ++i) { 
      std::ifstream infile(argv[i]); 
      std::cout << "\t-- " << argv[i] << " --\n"; 
      process(pattern, infile); 
     } 
    return 0; 
} 

На Unix-подобных системах, вам не нужно делать ничего особенного, чтобы построить это. В Windows вы хотите связать с предоставленным компилятором объектным файлом, который обрабатывает globbing (например, setargv.obj, с MS VC++).