Mini grep en c++

From Tuxunix
Jump to: navigation, search

Exemple


$ ./minigrep < /dev/null
$ ./minigrep < test_file
CORAL
No, no. I do, I do. I really do like it. But Marlin, I know
that the drop off is desirable with the great schools and
the amazing view and all, but do we really need so much
space?
$ ./minigrep do < test_file
minigrep do No, no. I do, I do. I really do like it. But Marlin, I know
the amazing view and all, but do we really need so much
$ ./minigrep -a so much < test_file 
the amazing view and all, but do we really need so much
   1./*
   2. * minigrep.cpp for (self)
   3. *
   4. * Made by tuxedo
   5. * Login <pierre@tuxedo.fr>
   6. *
   7. * Started on Wed 16 Mar 2007 15:18:39 tuxedo
   8. * Last update Fri 16 Mar 2007 14:22:37 tuxedo
   9.*/
  10.       
  11.#include <algorithm>
  12.#include <iostream>
  13.#include <string>
  14.#include <vector>
  15.       
  16.using std::string;
  17.using std::vector;
  18.     
  19.static string const WW_OPT = "-w";
  20.static string const AM_OPT = "-a";
  21.       
  22.void displayLine(string const& s) {
  23.    std::cout << s << std::endl;
  24.}
  25.       
  26.bool lineIs(string const& line, string trigger) {
  27.    // We must ignore ^ and $ here!
  28.    if (!trigger.empty()) {
  29.        if (^ == trigger[0])
  30.            trigger.erase(trigger.begin());
  31.        if (!trigger.empty() && $ == trigger[trigger.size() - 1])
  32.            trigger.erase(trigger.end() - 1);
  33.    }
  34.    return line == trigger;
  35.} // lineIs
  36.       
  37.bool lineContains(string const& line, string trigger) {
  38.    if ("" == trigger)
  39.        return true;
  40.    if (^ == trigger[0]) {
  41.        trigger.erase(trigger.begin());
  42.        if (!trigger.empty() && $ == trigger[trigger.size() - 1])
  43.            return lineIs(line, trigger);
  44.        return 0 == line.find(trigger);
  45.    }
  46.    if ($ == trigger[trigger.size() - 1]) {
  47.        trigger.erase(trigger.end() - 1);
  48.        string::size_type const pos = line.rfind(trigger);
  49.        return string::npos != pos && trigger.size() + pos == line.size();
  50.    }
  51.    return string::npos != line.find(trigger);
  52.} // lineContains
  53.       
  54.void grepAdjacent(vector<string> const& lines, vector<string> const& triggers,
  55.    bool matchWholeLines) {
  56.        vector<string>::const_iterator it = lines.begin();
  57.        while (lines.end() != (it = std::search(it, lines.end(), triggers.begin(), triggers.end(), matchWholeLines ? lineIs : lineContains))) {
  58.      
  59.      
  60.            std::for_each(it, it + triggers.size(), displayLine);
  61.            it += triggers.size();
  62.        }
  63.} // grepAdjacent
  64.       
  65.void grepDisjoint(vector<string> const& lines, vector<string> const& triggers, bool matchWholeLines) {
  66.
  67.    vector<string>::const_iterator it = lines.begin();
  68.    while (lines.end() != (it = std::find_first_of(it, lines.end(), triggers.begin(), triggers.end(), matchWholeLines ? lineIs : lineContains))) {
  69.
  70.      
  71.        displayLine(*it);
  72.        ++it;
  73.    }
  74.} // grepDisjoint
  75.       
  76.int main(int argc, char const * argv[]) {
  77.    // There is no simple way to force arguments at beginning of command line.
  78.    // Therefore, the ugly, tortuous way...
  79.    bool matchWholeLines = 1 < argc && argv[1] == WW_OPT;
  80.    bool useAdjacentMatches = matchWholeLines ? 2 < argc && argv[2] == AM_OPT : 1 < argc && argv[1] == AM_OPT;
  81.
  82.      
  83.    if (useAdjacentMatches && !matchWholeLines)
  84.        matchWholeLines = 2 < argc && argv[2] == WW_OPT;
  85.    // Now fetch search strings
  86.    int const triggerStart = (matchWholeLines ? 1 : 0) + (useAdjacentMatches ? 1 : 0) + 1;
  87.
  88.    vector<string> triggers;
  89.    for (int index = triggerStart; index < argc; ++index)
  90.        triggers.push_back(argv[index]);
  91.    // Fetch standard input
  92.    vector<string> lines;
  93.    string line;
  94.    while (getline(std::cin, line))
  95.        lines.push_back(line);
  96.    // Display results
  97.    if (triggers.empty())
  98.        std::for_each(lines.begin(), lines.end(), displayLine);
  99.    else if (useAdjacentMatches)
 100.        grepAdjacent(lines, triggers, matchWholeLines);
 101.    else
 102.        grepDisjoint(lines, triggers, matchWholeLines);
 103.    return 0;
 104.}

Correction rendu par tdd