Eingabestream lesen und sortieren

DarkSean

Erfahrenes Mitglied
Hallo,

ich bin noch C++-Anfänger und lerne gerade aus dem Buch "C++-Primer". Die Aufgaben da sind aber recht langweilig, weshalb ich probiere mir einen eigenen Taschenrechner zu programmieren. Nun scheitere ich aber daran eine Eingabe wie z.B. "1+1+1" nach Zahlen bzw. Operatoren zu sortieren, das heißt alle Zahlen sollen in einen Vektor "nums" und alle Operatoren in den Vektor "ops". Zum Testen lasse ich sie am Ende ausgeben. So sieht es bis jetzt aus:
C++:
#include <iostream>
#include <vector>
#include <cctype>

using namespace std;

const unsigned short &succ(0);
double num;
char op;
vector<double> nums;
vector<char> ops;

int main() {
 
    while (cin) {
        if (cin >> num)
            nums.push_back(num);
        else if (cin >> op)
            ops.push_back(op);
    }
 
    for (vector<double>::iterator i(nums.begin()); i != nums.end(); ++i )
        cout    <<  endl    <<  *i;
 
    for (vector<char>::iterator i(ops.begin()); i != ops.end(); ++i)
        cout    <<  endl    <<  *i;
 
    return succ;
}
Nun gibt das Programm schön alle Zahlen, aber leider nicht die Operatoren, also in dem Fall die beiden Plus-Zeichen, aus.

Vielen Dank schonmal!
 
Zuletzt bearbeitet:
Ich habe eine weitere Frage, und zwar möchte ich auch das Potenzieren implementieren und als Operatorzeichen das Zirkumflex ^ benutzen, allerdings möchte mein Programm dieses nicht als char akzeptieren.
Ich gebe zum Beispiel 1^1 ein und zähle die Anzahl der Zeichen, die keine Zahlen sind, so gibt mein Programm 0 aus, hingegen für die Eingabe 1+1 oder 1*1, so wie es sein soll, 1.
So sieht es bisher aus:
C++:
int readExpr() {
    while (cin >> num) {
        nums.push_back(num);
        if (cin >> op) 
            ops.push_back(op);
    }
    cout    <<  ops.size();
    return 0;
}
Beim Debuggen ist mir aufgefallen, dass die Eingabe 1^1 statt als zwei Zahlen mit einem Operator dazwischen eingelesen zu werden, stattdessen als Zahl 11 ohne Operator eingelesen wird. Benutze ich hingegen ein anderes Zeichen als Hochoperator (z.B. 'h') funktioniert alles tadellos. Wie kann ich nun aber das Zirkumflex benutzen?
 
Hallo DarkSean,

Ich hab nun auch ein bischen mit den std::cin herumgespielt und bin auch auf keinen grünen Faden gestoßen.

Ich habs mal mit RegEx versucht und bin auf folgendes Ergebnis gekommen:

Code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <regex>

int main()
{
  std::string input = "1. + 222 - 0 * 7.8 / 0.99 ^ 3";

  std::vector<double> numbers;
  std::vector<std::string> operants;

  const std::regex regex_number("([0-9]+([.][0-9]+)*)");
  const std::regex regex_operant("[/\\+-\\*\\^]");

  //std::getline(std::cin, input);

  try
  {
    for(auto it(std::sregex_iterator(input.begin(), input.end(), regex_number));
        it != std::sregex_iterator(); it++)
    {
      std::stringstream ss(std::smatch(*it).str());
      double number;
      ss >> number;
      numbers.push_back(number);
    }
    for(auto it(
        std::sregex_iterator(input.begin(), input.end(), regex_operant));
        it != std::sregex_iterator(); it++)
    {
      operants.push_back(std::smatch(*it).str());
    }
  }
  catch(std::regex_error err)
  {
    std::cout << err.what() << std::endl;
  }

  std::cout << "Numbers are:" << std::endl;
  for(auto &number : numbers)
  {
    std::cout << number << std::endl;
  }

  std::cout << "Operants are:" << std::endl;
  for(auto &operant : operants)
  {
    std::cout << operant << std::endl;
  }

  return 0;
}

Vll. krieg ichs ja mit std::cin auch noch hin.

Ok, ich gebs auf :p

mfg.
 
Zuletzt bearbeitet:
Mir ist gerade beim Rauchen der Gedanke gekommen, dass es da noch ein std::cin.get() gibt.

Damit kannst du Zeichen einlesen =)

Achte darauf, dass std::cin.get() einen Integer zurückliefert, diesen kannst du dann wieder auf ein char casten und ausgeben ;)

Wenn du aber dazwischen noch leerzeichen usw hast, ist das Filtern recht umständlich.
 
Das mit den Typumwandlungen (casten?) kann ich leider noch nicht, sonst hätte ich das einlesen wahrscheinlich anders gelöst, nämlich aus einer Stringkette mit getline(cin, .) dann die Zahlen und Operatoren aussortiert, allerdings weiß ich leider nicht, wie ich einen String in einen Zahlenwert wandeln kann bzw. in einen char-Wert.
RegEx kenn ich leider auch nicht, was macht das?

Vielen Dank aber schonmal für die Antwort!
 
Hab's nach ein bisschen Recherche doch mitm getline-Befehl hinbekommen, falls es jemanden interessiert, hier ein Code wie ich aus einer Eingabe die Zahlen extrahieren kann:
C++:
vector<double> readNums(string expr) {
    char c;
    vector<double> nums;
    double num(0);
    vector<string> numStrs;
    string numStr("");
    bool inNum(false), point(false);
    for (string::size_type i(0); i != expr.size(); ++i)
    {
        c = expr[i];
        if (isdigit(c)) {
            if (!inNum) {
                inNum = true;
            }
            numStr.push_back(c);
        }
        else if (c == '.' || c == ',')
            if (!point) {
                numStr.push_back('.');
                if (!inNum)
                    inNum = true;
                point = true;
            }
            else {
                std::cerr    <<  "Error";
            }
        else {
            if (inNum) {
                inNum = false;
                point = false;
                numStrs.push_back(numStr);
                numStr = "";
            }
            else
                ;
        }
    }
   
    char lastChar = expr[expr.size()-1];
   
    if (isdigit(lastChar) || lastChar == '.' || lastChar == ',')
        numStrs.push_back(numStr);

    for (vector<string>::iterator i(numStrs.begin()); i != numStrs.end(); ++i) {
        num = atof((*i).c_str());
        nums.push_back(num);
    }
   
    return nums;
}
 
RegEx kenn ich leider auch nicht, was macht das?
Mit RegEx sind reguläre Ausdrücke gemeint.

Damit kannst du in Texten nach bestimmten Zeichenfolgen suchen.
Für RegEx erstellst du eine Art Pattern, ist im Prinzip eine eigene Syntax für RegEx,
nach der eine/mehrere Zeichenfolgen gesucht werden können.

So ziemlich die meisten Programmiersprachen unterstützten eigentlich RegEx.
 
Zurück