Programm



  • Ein vector der eine Liste von pair hält, wäre auch noch eine Idee:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <utility>
    
    int main()
    {
        std::vector<std::pair<std::string, std::string> > Numbers;
        std::string ArtikelNummer;
        std::string LagerNummer;
        while(ArtikelNummer != "0" && LagerNummer != "0")
        {
            std::cin >> ArtikelNummer;
            std::cin >> LagerNummer;
            Numbers.push_back(make_pair(ArtikelNummer, LagerNummer));
        }
        for(unsigned int i = 0; i < Numbers.size() - 1; i++)
        {
            std::cout << Numbers[i].first << " " << Numbers[i].second << std::endl;
        }
    }
    


  • cool. schöne lösungen.danke!!
    @jochen du sagst man muss die elemente noch mit einem wert versehen. kannst du das mal machen,wenn ich zb. habe: steh grad auf dem schlauch. Brauch mal ein Bsp.ums zu verstehen. seh grad en bezug nicht wirklich.

    art.nr. 105-10-2467.5 lagernummer: 2117
    art.nr. 108-48-4757.8 lagernummer: 3456
    art.nr. 140-47-4564.2 lagernummer: 4567

    gruss



  • Du kannst die Werte so initialisieren:
    Folgenden Code einfach in meinem Beispielprog an den Anfang von main() schreiben:

    Elemente[0].Artikelnummer="105-10-2467.5";Elemente[0].Lagernummer="2117";
    Elemente[1].Artikelnummer="108-48-4757.8";Elemente[1].Lagernummer="3456";
    Elemente[2].Artikelnummer="140-47-4564.2";Elemente[2].Lagernummer="4567";
    

    Das ist natürlich keine Optimale Lösung. Besser wäre es, wenn man die Werte aus einer Textdatei einlesen könnte. Werd dazu gleich mal was Posten.
    MfG, Jochen



  • So, Hier die Version, die die Werte aus einer Textdatei datei.txt einliest:
    (Auf das Abfangen eventueller Fehler habe ich mal verzichtet.)

    #include <string>
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    struct SElem
    {
    string Artikelnummer;
    string Lagernummer;
    }*Elemente;
    
    int main()
    {
    	ifstream dat_ein;
    	dat_ein.open("datei.txt",ios_base::in);
    	int Anzahl;
    	dat_ein >> Anzahl;
    	Elemente = new SElem[Anzahl];
    
    	for(int loop=0;loop<Anzahl;loop++)
    	{
    		dat_ein >> Elemente[loop].Artikelnummer;
    		dat_ein >> Elemente[loop].Lagernummer;
    	}
    
    	dat_ein.close();
    
    	string ArtNum;
    	bool found = false;
    	cout << "Artikelnummer: ";cin >> ArtNum;
    	cout << "Lagernummer: ";
    
    	for(int loop=0;loop<Anzahl;loop++)
    	{
    		if(Elemente[loop].Artikelnummer==ArtNum)
    		{
    			cout << Elemente[loop].Lagernummer;
    			found = true;
    			break;
    		}
    	}
    	if(found==false)cout << "(nicht gefunden)" << endl;
    	cin.get();
        delete[] Elemente;
    	return 0;
    }
    

    Der Inhalt der Datei:

    3
    105-10-2467.5	2117
    108-48-4757.8	3456
    140-47-4564.2	4567
    

    Die erste Zahl in der Textdatei zeigt dem Programm, wie viele Datensätze in der Datei enthalten sind. Danach kommen die Daten: Erst die Artikelnummer, dann die Lagernummer.

    MfG, Jochen


  • Mod

    Noch besser wäre es natürlich, wenn in der Textdatei gar nicht drinstehen muss, wieviele Datensätze es gibt. Das wäre nämlich ein extrem unpraktisches Dateiformat, wenn man beim zufügen von Datensätzen an zwei Stellen etwas ändern muss. Und noch schlimmer wäre es, wenn man Datensätze entfernt aber vergisst die erste Zeile zu ändern.

    Wie das genau geht, überlasse ich mal interessierten Lesern als Übung. Ist ganz einfach.



  • Hi Jochen. Habe ein ähnliches Prog. Aber wo speicher ich die datei.txt mit den infos ab? Muss ich nicht irgendwo einen Pfad angeben?

    MFG



  • Hallo,
    Die Datei datei.txt muss sich in dem selben Ordner befinden wie das Programm. Sollte sich die Datei sonstwo befinden, muss man natürlich noch einen Pfad mit angeben.

    MfG, Jochen



  • So, hier ist noch das Programm, das von SeppJ bevorzugt werden würde:

    #include <string>
    #include <iostream>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    struct SElem
    {
    string Artikelnummer;
    string Lagernummer;
    };
    
    int main()
    {
    	ifstream dat_ein;
    	dat_ein.open("datei.txt",ios_base::in);
    
    	vector<SElem> Elemente;
    
    	while(!dat_ein.eof())
    	{
    		SElem tmp;
    		dat_ein >> tmp.Artikelnummer;
    		dat_ein >> tmp.Lagernummer;
    		Elemente.push_back(tmp);
    	}
    
    	int Anzahl = Elemente.size();
    
    	dat_ein.close();
    
    	string ArtNum;
    	bool found = false;
    	cout << "Artikelnummer: ";cin >> ArtNum;
    	cout << "Lagernummer: ";
    
    	for(int loop=0;loop<Anzahl;loop++)
    	{
    		if(Elemente[loop].Artikelnummer==ArtNum)
    		{
    			cout << Elemente[loop].Lagernummer;
    			found = true;
    			break;
    		}
    	}
    	if(found==false)cout << "(nicht gefunden)" << endl;
    	cin.get();
    	for(int loop=0;loop<Anzahl;loop++)Elemente.erase(0);
    	return 0;
    }
    

    Der Inhalt der Datei müsste jetzt so aussehen:
    (So wie vorher, nur ohne die errste Zeile)

    105-10-2467.5	2117
    108-48-4757.8	3456
    140-47-4564.2	4567
    

    Stimmt, die Lösung ist schöner. Ich weiss zwar nicht, wie vector intern arbeitet, aber führt das nicht zu einer starken Heapfragmentierung, wenn immer Speicher für ein weiteres Element reserviert werden muss, wenn ein neues Element hinzugefügt wird?

    MfG, Jochen



  • Ich weiss zwar nicht, wie vector intern arbeitet

    http://www.sgi.com/tech/stl/Vector.html

    [3] When it is necessary to increase capacity(), vector usually increases it by a factor of two. It is crucial that the amount of growth is proportional to the current capacity(), rather than a fixed constant: in the former case inserting a series of elements into a vector is a linear time operation, and in the latter case it is quadratic.

    Und ueber Fragmentierung rede ich erst, wenn viel Speicher benoetigt wird. Desweiteren kann das Suchen auch beim Einlesen der Elemente stattfinden, dann spart man sich das Array. Auch das manuelle Loeschen der Elemente am Ende ist ueberfluessig, das passiert automatisch, wenn der Destruktor von std::vector aufgerufen wird. Ich weiss jetzt nicht genau, was erase macht, aber wenn von vorn geloescht wird, dann muss der restliche Inhalt staendig um eins nach vorne kopiert werden. Besser man beginnt hinten ...



  • Stimmt, das mit dem löschen ist nicht ganz so optimal. Noch einfacher ist es, wenn man gleich den Destruktor "manuell" aufruft. Oder sehe ich da etwas falsch?


  • Mod

    Jochen S. schrieb:

    Stimmt, das mit dem löschen ist nicht ganz so optimal. Noch einfacher ist es, wenn man gleich den Destruktor "manuell" aufruft. Oder sehe ich da etwas falsch?

    Faustregel: Man ruft NIEMALS Destruktoren manuell auf. Destruktoren werden automatisch aufgerufen, wenn der Programmfluss den Gültigkeitsbereich eines Objekts verlässt.



  • Jochen S. schrieb:

    Noch einfacher ist es, wenn man gleich den Destruktor "manuell" aufruft.

    Das will ich sehen! :p



  • _matze schrieb:

    Jochen S. schrieb:

    Noch einfacher ist es, wenn man gleich den Destruktor "manuell" aufruft.

    Das will ich sehen! :p

    Probiers aus. Es ruft den Destruktor auf, aber das Objekt ist weiterhin zugänglich.

    class MyClass
    {
    public:
    	MyClass() { std::cout << "Objekt erstellt" << std::endl ; }
    	~MyClass() { std::cout << "Objekt gelöscht" << std::endl ; }
    	void DoSomething() { std::cout << "Objekt ruft DoSomething() auf" << std::endl ; }
    };
    
    int main ( )
    {
    	MyClass Obj ;
    	Obj.~MyClass();
    	Obj.DoSomething() ;
    }
    


  • Gut, bei solch einer Klasse mag das ja funktionieren. Wenn du aber irgendwo Speicher reservierst (was ja auch vector tut) und diesem im Destruktor freigibst, kannst du nicht mehr ohne weiteres mit den Objekt arbeiten. Und knivil sagte, dass der Speicher im Destruktor von vector freigegben wird:

    knivil schrieb:

    Auch das manuelle Loeschen der Elemente am Ende ist ueberfluessig, das passiert automatisch, wenn der Destruktor von std::vector aufgerufen wird.

    Da dachte ich, dass man ja auch den Destruktor manuell aufrufen könne. In dem Fall würde also tatsächlich der Speicher freigegeben. Ein Weiterarbeiten mit dem Objekt wäre in dem Falle nicht mehr möglich.



  • Jochen S. schrieb:

    Ein Weiterarbeiten mit dem Objekt wäre in dem Falle nicht mehr möglich.

    Doch, aber mit undefiniertem Verhalten zur Laufzeit. Und das ist ja das Schlimme. pumuckl hat völlig Recht. Ausser bei seltenen Spezialfällen, wenn man auch Placement New verwendet, ruft man nie Destruktoren manuell auf. Entweder wird das Objekt über delete oder automatisch zerstört.

    Falls man vorzeitig den Speicher freigeben möchte, was meistens keine gute Idee ist, kann man immer noch den swap() -Trick anwenden:

    std::vector().swap(my_vector);
    

    Übrigens: Äusserst kreativer Threadtitel. 🤡



  • servus jungs. 👍

    ich muss zugeben ich bin sprachlos, und irgendwie ist das mir auch ein wenig zu hoch geworden 😞 ich kenn micht nicht mehr aus.
    Würde dieses Programm gern lauffähig machen. beim ausführen bekomme ich immer diese Fehlermeldung:

    Kompilierung läuft...
    Lagersystem.cpp
    C:\Dokumente und Einstellungen\Markus\Desktop\Lagersystem\Lagersystem.cpp(48) : error C2374: 'loop' : Neudefinition; Mehrfachinitialisierung
    C:\Dokumente und Einstellungen\Markus\Desktop\Lagersystem\Lagersystem.cpp(37) : Siehe Deklaration von 'loop'
    Fehler beim Ausführen von cl.exe.
    EInlaufkurven.obj - 1 Fehler, 0 Warnung(en)

    bin ratlos!!!!!!!!!!!!!
    Hab ich aber das Prinzip schon richtig geschnallt, dass die 2 Lösung besser auf Änderungen in der Liste reagiert. dh. wenn zb. eine neue art.nummer + Lagernummer hinzukommt,könnte ich die einfach dahinter anreihen.
    Beim nächsten ausführen wird diese Zahl mit ins prog integriert.!!!!!??????

    Gruss



  • Zeig doch mal, wie dein aktueller Code aussieht. Das ist ein eher kleiner Fehler, den du da bekommst.



  • Hallo,
    Hast Du etwas an dem Quelltext geändert? Bei mir lässt sich das Programm ohne Fehler kompilieren. Ich weiss ja nicht, welchen Compiler du benutzt, aber eigentlich dürfte es keinen Compiler geben, der den Code nicht kompiliert.
    Was du tun könntest, wäre folgendes:
    Du deklarierst loop gleich am Anfang von main() :

    int main()
    {
    int loop;
    // ... 
    }
    

    In den For-Schleifen müsstest du dann immer anstatt int loop = ... einfach nur loop = ... schreiben. Aber für konkrete Vorschläge müsste ich Einsicht in den Quelltext haben.

    MfG, Jochen



  • habs jetzt mal so gemacht wie dus im vorherigen beitrag geschrieben hast:

    #include <string>
    #include <iostream>
    #include <fstream>
    #include <vector>
    using namespace std;

    struct SElem
    {
    string Artikelnummer;
    string Lagernummer;
    };

    int main()
    {
    int loop;
    ifstream dat_ein;
    dat_ein.open("datei.txt",ios_base::in);

    vector<SElem> Elemente;

    while(!dat_ein.eof())
    {
    SElem tmp;
    dat_ein >> tmp.Artikelnummer;
    dat_ein >> tmp.Lagernummer;
    Elemente.push_back(tmp);
    }

    int Anzahl = Elemente.size();

    dat_ein.close();

    string ArtNum;
    bool found = false;
    cout << "Artikelnummer: ";cin >> ArtNum;
    cout << "Lagernummer: ";

    for(loop=0;loop<Anzahl;loop++)
    {
    if(Elemente[loop].Artikelnummer==ArtNum)
    {
    cout << Elemente[loop].Lagernummer;
    found = true;
    break;
    }
    }
    if(found==false)cout << "(nicht gefunden)" << endl;
    cin.get();
    for(loop=0;loop<Anzahl;loop++)Elemente.erase(0);
    return 0;
    }

    Das kompilieren funktioniert ohne fehler. beim anschließenden ausführen erscheint folgende fehlermeldung.

    --------------------Konfiguration: test - Win32 Debug--------------------
    Kompilierung läuft...
    test.cpp
    C:\Dokumente und Einstellungen\Markus\Desktop\test\test.cpp(48) : error C2374: 'loop' : Neudefinition; Mehrfachinitialisierung
    C:\Dokumente und Einstellungen\Markus\Desktop\test\test.cpp(37) : Siehe Deklaration von 'loop'
    Fehler beim Ausführen von cl.exe.

    test.exe - 1 Fehler, 0 Warnung(en)



  • Also, ich hab jetzt mal den Quelltext kopiert. Liess sich porblemlos kompilieren. Was hast du denn für einen Compiler? Ich bin jetzt etwas ratlos, aber du könntest ja mal versuchen, für jede Schleife eine andere Schleifenvariable zu nehmen, also:

    erste Schleife: for(int loop1=0;...)
    zweite Schleife: for(int loop2=0;...)
    ...
    Nicht vergessen, dann auch in der Schleife die anderen Variablen zu nehmen.
    Mal sehen, vielleicht klappt es dann.
    Was du noch machen solltest:
    Entferne die Schleife zwischen cin.get(); und return 0; am Ende de Programms.
    Bei mir hängt sich das Prgramm in dieser Schleife immer auf.

    MfG, Jochen


Anmelden zum Antworten