Praktikum Bildbearbeitung

Zum Betrachten der nächsten Seite "Bild ab" drücken oder nach unten scrollen.

Eine leere main Funktion

main.cpp:


int main(int, char **) {
  return 0;
}
      

Deklaration Parser

argparse.hpp:


#pragma once

#include <vector>

namespace bba {

enum Action {
  ACTION_NONE,
  ACTION_INPUT,
  ACTION_OUTPUT,
  ACTION_FILTER_IDENTITY
};

struct Operation {
  Action action;
};

typedef std::vector<Operation> Operations;

Operations parse_arguments(int argc, char *argv[]);

} // namespace bba
      
Dokumentation std::vector.

Implementierung Parser

Funktionsrumpf

argparse.cpp:


#include "argparse.hpp"

bba::Operations bba::parse_arguments(int argc, char *argv[]) {
  bba::Operations ops;
  return ops;
}
      

main.cpp:


#include "argparse.hpp"

int main(int argc, char **argv) {
  bba::parse_arguments(argc, argv);
  return 0;
}
      

Pointer von C-String zu std::vektor von std::string

argparse.cpp:


#include "argparse.hpp"
#include <string>

bba::Operations bba::parse_arguments(int argc, char *argv[]) {
  Operations ops;

  const std::vector<std::string> arguments(argv + 1, argv + argc);

  return ops;
}
      
Dokumentation std::vector Konstruktor (5), string Konstruktor (5).

Schleife und Ausgabe

in argparse.cpp:


…
#include <iostream>

  …
  for (size_t i = 0; i < arguments.size(); i++) {
    std::cerr << arguments[i] << std::endl;
  }
  …
      
Dokumentation std::cerrstd::ostream::<<

Stringvergleich

in argparse.cpp:


  for (size_t i = 0; i < arguments.size(); i++) {
    std::cerr << arguments[i] << std::endl;
    if (arguments[i] == "--input") {
      // TODO
    } else if (arguments[i] == "--output") {
      // TODO
    }
  }
      

Referenz als Alias


  for (size_t i = 0; i < arguments.size(); i++) {
    const std::string & action = arguments[i];
    std::cerr << action << std::endl;
    if (action == "--input") {
      // TODO
    } else if (action == "--output") {
      // TODO
    }
  }
      

Objekt zu std::vektor hinzufügen

in argparse.cpp:


    if (action == "--input") {
      Operation op;
      op.action = bba::ACTION_INPUT;
      ops.push_back(op);
    }
      

Struktur erweitern

in argparse.hpp:


#include <vector>
#include <string> // kann aus argparse.cpp entfernt werden

struct Operation {
  Action action;
  std::string filename;
};
      

Indizierter Zugriff auf std::vektor

in argparse.cpp:


      Operation op;
      op.action = bba::ACTION_INPUT;
      op.filename = arguments[i+1]; // Gefahr: keine Bereichskontrolle!
      ops.push_back(op);
      

Ausnahmen werfen

in argparse.cpp:


#include <stdexcept>

      …
      if (arguments.size() > i+1) {
        op.filename = arguments[++i];
      } else {
        throw std::runtime_error("Nicht genügend Argumente.");
      }
      
Dokumentation std::runtime_error.

Redundanz erkennen

in argparse.cpp:


    if (action == "--input") {
      Operation op;
      op.action = bba::ACTION_INPUT;
      if (arguments.size() > i+1) {
        op.filename = arguments[++i];
      } else {
        throw std::runtime_error("Nicht genügend Argumente.");
      }
      ops.push_back(op);
    } else if (action == "--output") {
      Operation op;
      op.action = bba::ACTION_OUTPUT;
      if (arguments.size() > i+1) {
        op.filename = arguments[++i];
      } else {
        throw std::runtime_error("Nicht genügend Argumente.");
      }
      ops.push_back(op);
    }
      

Statische Hilfsfunktion deklarieren und implementieren

in argparse.cpp:


std::string consume_argument(const std::vector<std::string> & arguments, size_t & i) {
  if (arguments.size() > i+1) {
    return arguments[++i];
  } else {
    throw std::runtime_error("Nicht genügend Argumente.");
  }
}
      

Referenz arguments ist konstant. Referenz i ist schreibbar.

Hilfsfunktion aufrufen

in argparse.cpp:


    if (action == "--input") {
      Operation op;
      op.action = bba::ACTION_INPUT;
      op.filename = consume_argument(arguments, i);
      ops.push_back(op);
    } else if (action == "--output") {
      Operation op;
      op.action = bba::ACTION_OUTPUT;
      op.filename = consume_argument(arguments, i);
      ops.push_back(op);
    }
      

Lokale anonyme Funktion deklarieren und implementieren

in argparse.cpp:


std::string consume_argument(const std::vector<std::string> & arguments, size_t & i) {
  …
}

bba::Operations bba::parse_arguments(int argc, char *argv[]) {
  …
}
      
verschieben und umformulieren zu

bba::Operations bba::parse_arguments(int argc, char *argv[]) {
  …
  auto consume_argument = [&arguments](size_t & i) {
    …
  }
  …
}
      

Anonyme Funktion aufrufen

in argparse.cpp:


bba::Operations bba::parse_arguments(int argc, char *argv[]) {
  …
  const std::vector<std::string> arguments(…);
  
  auto consume_argument = [&arguments](size_t & i) {…};
  
  for (…) {
    …
    if (action == "--input") {
      …
      op.filename = consume_argument(i);
      …
    } else if (action == "--output") {
      …
      op.filename = consume_argument(i);
      …
    }
  }
  …
}