C++ Eingabe von Int-Werten (in Vektor) mit string beenden?

Dosenfutter123

Cadet 1st Year
Registriert
Mai 2016
Beiträge
14
Guten Morgen,

ich möchte derzeit ein recht einfaches Programm schreiben. In einem Vektor mit Integer-Werten sollen beliebig viele Werte vom Benutzer eingegeben werden können, bis der Benutzer "END" eingibt.

Mein Problem ist, dass ich als Eingabe immer "input"(vom Typ int) in den Vektor pushe. Wäre es möglich, dass ich vor meiner push()-Funktion den Int-wert in einen String zu ändern, wenn keine Zahl eingegeben wird?
Mein Ansatz wäre aufjedenfall mit Templates zu arbeiten, damit zur Laufzeit bestimmt wird, um welchen Typ es sich handelt. Nur widerspricht sich mein Plan, wenn ich input schon als int deklariert habe.

Habe auch schon versucht die Zahlen in einen String-Vektor zu speichern, wo ich aber spätestens auf Probleme stoße, wenn ich mit den Zahlen Berechnungen machen will.

Hier der bisher geschriebene Code:

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

using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::vector;

vector <int> zahlen;

template <typename T>

int push(T &input)
{
  /*if (input == "END")       //nicht möglich, da immer int übergeben wird
  {
     return 1;
  }
  
  else*/ 
    zahlen.push_back(input);  
}


int main()
{
  int input;
   
  while (1)
  {
      cout << "Bitte Zahl eingeben. Zum Beenden 'END' eingeben: " << endl;
      cin >> input;

      push(input);
     
      if (push(input) == 1)
         break;
  }

}

Mit freundlichen Grüßen
Dosenfutter123
 
Zuletzt bearbeitet:
es wäre vermutlich einfacher, wenn du input als String anlegst, dann überprüfst ob es eine Zahl, "END" oder irgentwas anderes ist und das dann einsprechend in int umwandelst.(Kenne mich mit den C++ Methoden nicht aus, aber so würde ich das in Java machen)
 
"END" als AsciiString lässt sich natürlich nicht in einem int speichern. Du musst leider mit cin einen string einlesen, dann auf "END" prüfen und fals es kein "END" ist, nach int konvertieren mit der funktion : atoi
 
Ich würde das END gar nicht im Vector speichern (wozu auch?)
Ich würde nur die Zahlenwerte speichern.
cin gibt ja ein String zurück, also musst Du vor dem Push zu int konvertieren (z.B. via std::stoi).
 
Du solltest deinen Input niemals als INT deklarieren.
Wenn der User nur einmal was anderes eingibt, hast du dort deine Exception.
Deklarier den Input als String und prüf vorher auf dein "END", bevor du es deiner Methode als INT übergibst.
 
Danke für die schnellen Antworten. Habe jetzt meinen input als string deklariert und soweit funktionierts. Nur eine Frage ist aufgekommen:

Die atoi-Funktion hat nur mit einem char-Feld funktioniert (nicht mit einem string). Wenn ich dann die Abfrage
Code:
if (input == "END")
  {break;}

gemacht habe, wurde das END nicht akzeptiert. Wenn ich jedoch vorher eine Stringvariable deklariert habe, in der "END" steht:
Code:
string end = "END";

// ...

if (input == end)
  {break;}

hat das ganze funktioniert. An was genau liegt das?

Gruß Dosenfutter123
 
Zuletzt bearbeitet:
Shio schrieb:
Du solltest deinen Input niemals als INT deklarieren.
Wenn der User nur einmal was anderes eingibt, hast du dort deine Exception.
Deklarier den Input als String und prüf vorher auf dein "END", bevor du es deiner Methode als INT übergibst.

Nein, std::cin wirft keine exception aber wechselt in einen Fehlerzustand. Auf den müsstest du checken.

Hier mal als Beispiel wie du prüfen kannst ob du wirklich ein gültiges int bekommen hast:

Code:
int number = 0;

for(;;) {
    std::cout << "Enter number: ";
    std::cin >> number;
    if( wcin.good() )
        break;
    else {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

// An diesem Punkt ist die Eingabe des Users definitiv ein gültiger integer und kann benutzt werden.

string und integer sind fundamental unterschiedliche typen, die kannst du in C/++ nicht einfach durcheinander werfen!

Wenn Interesse besteht kann ich dir heute nachmittag mal ein komplettes, richtig funktionierendes Beispiel bauen. Schreib mir einfach mal genau was es tun soll, und ich poste es dann später.
 
Code:
#include <stdlib.h>
#include <string>
#include <iostream>

using namespace std;

int main () {

    int i,j;
    string str;
    int ints[64];

    i=0;
    while (true) {
        cin >> str;
        if (str == "END") break;
        ints[i++]=atoi(str.c_str());
    }

    for (j=0;j<i;j++) cout << ints[j];



return (0);
}

atoi Beispiel von mir auf die schnelle
Ergänzung ()

Code:
#include <stdlib.h>
#include <string>
#include <iostream>
#include <vector>

using namespace std;

int main () {

    uint i;
    string str;
    vector <int>ints;

    while (true) {
        cin >> str;
        if (str == "END") break;
        ints.push_back(atoi(str.c_str()));
    }

    for (i=0;i<ints.size();i++) cout << ints[i] << " ";

return (0);
}

Hier das ganze mit Vectoren
 
Zuletzt bearbeitet: (int -> uint)
Wenn ich eine etwas ideomatischere Lösung Vorschlagen dürfte:

Code:
#include <string>
#include <iostream>
#include <vector>
     
using namespace std;
     
int main () {     
    vector <int>ints;

    string str;
    while (cin >> str) {         
        if (str == "END") break;
        try {
           ints.push_back(stoi(str));
        } catch (...) {};
    }
     
    for (int i : ints) {
        cout << i << " ";
    }
     
}
Die überspringt auch ungültige Eingaben statt dafür Nullen zu generieren. Je nach dem, was für einen übersichtlicher ist kann man den Vergleich mit END auch in die while Bedingung ziehen.
 
Zuletzt bearbeitet:
Wow, das c++17 Feature mit

for(i:ints) cout <<i;

kannte ich noch nicht... Selbst das int i kann man weg lassen und nur i schreiben. Wird dann auto angenommen?

Wie kann ich in dieser Schleife denn sehen, das wievielte Element man gerade ausgiebt ?
Also, was wenn ich in der Schleife eine Berechnung machen möchte und das Ergebnis wieder an der gleichen Postition im vector abspeichern möchte?


Da beantworte ich meine Frage gleich selber:
for (auto &i: ints) i+=1;;
for (auto &i: ints) cout << i << " ";

Würde den aktuellen Vector +1 rechnen und abspeichern.
 
Zuletzt bearbeitet:
Code:
for ( auto& i: ints )

ist kein C++17, das ist C++11. ;)
 
GregoryH schrieb:
Code:
for ( auto& i: ints )

ist kein C++17, das ist C++11. ;)

Stimmt!


Code:
for ( i: ints )

ist aber c++17


Unlogisch erscheint mir wieso man den Type bei (auto &i : ints) angeben muss , aber bei (i:ints) nicht!
 
nebulus schrieb:
Code:
for ( i: ints )

ist aber c++17
Darf ich fragen, woher du die Information hast, dass diese Schreibweise in c++17 legal sein wird? Meines Wissens wurde das zwar mal vor ein paar Jahren vorgeschlagen, aber dann abgelehnt.
 
Danke für die hilfreichen Antworten - mein Programm funktioniert wie es funktionieren soll :)

Bin jetzt noch an einem ähnlich anderem Problem & hoffe, dass dies hier gleich mit abgearbeitet werden kann.
Folgendes Problem:
In einem Int-Vektor sollen nur Binärzahlen (also 0en und 1en) eingegeben werden. Sobald die Sequenz "1111110" erkannt wird, soll die Eingabe beendet werden.
Dies wäre einfach aber "unschön" umzusetzen indem ich meinen Vektor (z.B. vector <int> bits) in einer Schleife prüfe ob bits == 1 && bits[i+1] ==1 && ... && bits[i+6] == 0 ist.

Zudem soll das Programm nach 5 erkannten 1en mit einer Funktion immer eine 0 nach der letzten 1 hinzu-codieren. Eine andere Funktion soll diese 0en dann wieder herauscodieren können. Dies wäre zwar auch wieder mit einer Schleife wie oben beschrieben möglich, jedoch scheint mir dies nicht die eleganteste Lösung zu sein.

Gruß Dosenfutter 123
 
Um auf bit-Ebene zu arbeiten gibt es in C++ eine wunderbare Hilfe die genau so wie vector zum Standard gehört:
http://www.cplusplus.com/reference/bitset/bitset/
Links unten sind die Funktionen und der Konstruktor dokumentiert.

dh du machst:
std::bitset<32> myBitset(myVectorWithInts;
// Nun kann man auf myBitset arbeiten und zB mit myBitset[2] auf ein bit zugreifen.
Der Grund dafür ist, dass bitset als Konstruktor ein integer nehmen kann.
 
Bist Du dir sicher, das Du die Aufgabe richtig verstanden hast? Du willst in einem int Vector eine Binär Codierte Zahl als Dezimalzahl speichern?


Sinnvoller wäre es die Zahl binär einzulesen als String "0b00010001" und dann als 0x11 im integer abzuspeichern.
So speicherst Du aber Dezimal 10001 im integer ab, was 0x2711 entspricht aber in Wirklichkeit 0x11 sein soll...
Ergänzung ()

Miuwa schrieb:
Darf ich fragen, woher du die Information hast, dass diese Schreibweise in c++17 legal sein wird? Meines Wissens wurde das zwar mal vor ein paar Jahren vorgeschlagen, aber dann abgelehnt.

gcc vector.cpp -lstdc++ -Wall -g -O2 -std=c++11
vector.cpp: In Funktion »int main()«:
vector.cpp:20:9: Warnung: range-based for loop without a type-specifier only available with -std=c++1z or -std=gnu++1z
for ( i: ints) cout << i << " ";


gcc vector.cpp -lstdc++ -Wall -g -O2 -std=c++17
OK!
 
Zurück
Oben