Code erklärung zyklische warteschlange
-
ich hab mich bisschen über zyklische warteschlange erkundigt .. verstehen tu ich es leider nicht viel..
hab hier einen kleinen code gefunden aber ich versteh nicht. den aufbau bzw. den "ablauf".. hier läuft irgendwas mit ner queue und pointer ab. auch wird hier irgendwas allokiert aber ich versteh davon nicht viel..außerdem versteh ich auch nicht wie ich die funktion getchar() zusammen bauen soll..
ich bin ein anfänger , der total mit komplexen c++ aufgaben bombadiert wird -.-'

#include <iostream> #include <string.h> using namespace std; void showmenu () { cout << "i(n)it, (i)nsert, (d)elete, (c)lear all, (p)rint all, print an(z), queue (a)endern (e)xit\n"; } int main() { int anz = 0; char **queue; queue = new char*[13]; unsigned int posinsert = 0; int posremove = 0; int count; int select; int initqueue; int i = 1, j; cout << " #### Zyklische Warteschlange ####" << endl; while (i != 0) { char input; //cout << "Bitte waehlen Sie einen Menuepunkt aus:\n\n"; showmenu (); cin >> input; getchar(); switch(input) { case 'n': delete [] queue; cout << "Wie gross soll die Queue werden? " << endl; cin >> initqueue; //char *queue; queue = new char*[initqueue]; break; case 'i': if (posinsert == 13) { posinsert = 0; cout << "Posinsert wurde inkrementiert und somit zurueckgesetzt" << endl; } if (anz == 13) cout << "Queue ist voll" << endl; else { cout << "Bitte geben Sie einen String ein: "; char pufferfeld[30]; cin >> pufferfeld; queue[posinsert] = new char [strlen(pufferfeld)]; strcpy(queue[posinsert], pufferfeld); anz++; posinsert++; } break; case 'd': if (posremove == 13) posremove = 0; if (anz == 0) cout << "Es gibt keine Elemente zum loeschen" << endl; else { queue[posremove] = ""; posremove++; anz--; cout << "Item geloescht" << endl; } break; case 'c': if (anz != 0) { for(count = 0; count <= anz; count++) { queue[count] = ""; } } else { cout << "Die Queue is noch leer !!! " << endl; } cout << "Alle Items geloescht" << endl; anz = 0; posinsert = 0; posremove = 0; break; case 'p': for (j = 0; j < 13; j++) { cout << (j+1) << " : " << queue[j] << endl; } break; case 'z': cout << "Die Queue besitzt " << anz << " Elemente" << endl; break; case 'a': case 'e': cout << "Ende\n"; i = 0; break; default: cout << "Falsche Eingabe\n"; break; } } }
-
Wie genau ist denn die Aufgabenstellung?
-
_matze schrieb:
Wie genau ist denn die Aufgabenstellung?
Programmieren Sie eine zyklische Warteschlange für C-Strings. Verwenden Sie ein char *
Feld konstanter Länge (z.B. 13) für die Pointer die auf die C-Strings zeigen. Lesen Sie
zum Einfügen eines Elements eine Zeichenkette von der Konsole ein (in ein Pufferfeld),
ermitteln seine Länge, allokieren den entsprechenden Speicherplatz dynamisch und fügen
den Eintrag in die Warteschlange ein. Entwickeln Sie Funktionen für:
Eintrag einfügen,
Eintrag entfernen,
Warteschlange auf der Konsole ausgeben,
Anzahl Einträge ausgeben,
Warteschlange neu initialisieren, d.h. alle Einträge entfernen und Warteschlange in den
Anfangszustand versetzen.
Verwenden Sie ein Menü zum Testen. Für die Warteschlangenlogik können Sie ihre
Ergebnisse aus Aufgabenblatt 6, Aufgabe 2 verwenden.
Modifizieren Sie Ihr Programm, so dass Sie einen zusätzlichen Menüpunkt
„Warteschlange initialisieren“ hinzufügen, wobei Sie die Länge der erzeugten
Warteschlange angeben können. Jetzt können Sie natürlich kein char * Feld konstanter
Länge mehr deklarieren. Sie müssen das char * Feld dynamisch mit Hilfe von new
erzeugen.
Modifizieren Sie Ihr Programm, so dass Sie einen zusätzlichen Menüpunkt
„Warteschlangen Länge ändern“ hinzufügen. Einträge in Ihrer Warteschlange sollen bei
diesem Menüpunkt erhalten bleiben. Vergrößern der Warteschlange soll auf jeden Fall
funktionieren. Verkleinern ist optional, d.h. muss nicht unbedingt implementiert werden.
Hinweis: Unter C-String verstehen wir ein char-Feld, das mit einem 0-Zeichen begrenzt ist.
Denken Sie an die Funktionen zur Unterstützung der C-Stringbehandlung z.B. strcpy()
oder strlen().
-
Die Aufgabe setzt doch offensichtlich auf auf Aufgabenblatt 6, Aufgabe 2. Was hast du denn da schon?
-
C-Strings in c++???? Sowas braucht man doch nicht, oder?
-
blatt 6 aufgabe 2
#include <string.h> #include <iostream> #include <stdio.h> using namespace std; int main (void){ char a1[81] , b2[81]; int k , i; cout<< " ersten String eingeben"<<"\n"; cin>>a1; cout<< "zweiten String eingeben"<<"\n"; cin>>b2; //länge ermitteln for (i=0; i<=80 ;i++) { if (a1[i] == '\0') break; } cout << " die länge des ersten strings ist"<<i<<endl; //cout<<a1<<" hat die länge "<< strlen(a1)<<endl; //cout<<b2<<" hat die länge "<< strlen(b2)<<endl; for (i=0; i<=80 ;i++) { if (b2[i] == '\0') break; } cout << " die länge des zweiten strings ist"<<i<<endl; k = strcmp(a1,b2); if(!k) cout<< "...beide strings sind gleich lang digga..." <<endl; else if(k<0) cout<< a1 << " <<< ist kleiner als >>>" <<b2 << endl; else cout<<a1<< " <<< ist groeßer als >>>"<<b2<< endl; cout<<a1<<b2<<endl;das bringt mir aber nicht viel -.-'
-
pyhax schrieb:
C-Strings in c++???? Sowas braucht man doch nicht, oder?
Doch. Aber in der Aufgabenstellung sind sie definitiv fehl am Platz.
-
**PUSH**
also jetziger stand ich hab gemerkt blatt6 lösung hilft mir garnicht

-
Programmieren Sie eine zyklische Warteschlange für C-Strings. Verwenden Sie ein char * Feld konstanter Länge (z.B. 13) für die Pointer die auf die C-Strings zeigen.Modifizieren Sie Ihr Programm, so dass Sie einen zusätzlichen Menüpunkt „Warteschlangen Länge ändern“ hinzufügen. Einträge in Ihrer Warteschlange sollen bei diesem Menüpunkt erhalten bleiben. Vergrößern der Warteschlange soll auf jeden Fall funktionieren.//ist schon fuer den 2. absatz der ansatz, sonst bräuchtest du das new[] hier nicht. std::size_t warteschlangen_laenge = 13; char** warteschlange = new char*[warteschlangen_laenge]; std::size_t index_fuer_naechsten_eintrag = 0; void hinzufuegen(char* mich_fuegst_du_hinzu) { if(index_fuer_naechsten_eintrag > warteschlangen_laenge-1) /* geht nicht, da warteschlange voll ist - vergrößern? oder fehlermeldung? oder oder oder*/ warteschlange[index_fuer_naechsten_eintrag++] = mich_fuegst_du_hinzu; } /* ganz am ende noch: */ void gib_speicher_frei() { /* delete auf jeden eintrag der warteschlange */ /* delete[] auf warteschlange[] */ }Lesen Sie zum Einfügen eines Elements eine Zeichenkette von der Konsole ein (in ein Pufferfeld), ermitteln seine Länge, allokieren den entsprechenden Speicherplatz dynamisch und fügen den Eintrag in die Warteschlange ein.const std::size_t einlese_buffer_laenge = 512; char buffer_zum_einlesen[einlese_buffer_laenge+1]; buffer_zum_einlesen[einlese_buffer_laenge] = '\0'; //ich weiß nicht genau, ob das nötig ist, aber wenn man mehr als 512 zeichen eingibt, sollte strlen keine '\0' finden und über das ende hinaus lesen std::cin::getline(buffer_zum_einlesen, einlese_buffer_laenge); std::size_t einlese_laenge = strlen(buffer_zum_einlesen); char* neuer_string = new char[neuer_string]; strcpy(neuer_string, buffer_zum_einlesen); /* in warteschlange einfügen */usw.
das sind nur code-fetzen. am besten, du machst aus der warteschlange eine klasse.
mit den methoden
`Eintrag einfügen,
Eintrag entfernen,
Warteschlange auf der Konsole ausgeben,
Anzahl Einträge ausgeben,
Warteschlange neu initialisieren
`
das einlesen, packst du in eine extra funktion etc.
dann versuch mal was, draus zu machen und schreib dann, wie weit du gekommen bist, was du nicht verstehst etc.
bb
-
wizzam schrieb:
Programmieren Sie eine zyklische Warteschlange für C-Strings.
class ZyklischeWarteschlangeFuerC_Strings { ... };wizzam schrieb:
Lesen Sie
zum Einfügen eines Elements eine Zeichenkette von der Konsole ein (in ein Pufferfeld),
ermitteln seine Länge, allokieren den entsprechenden Speicherplatz dynamisch und fügen
den Eintrag in die Warteschlange ein.C_String Pufferfeld; cout << "Bitte geben Sie ein Wort ein: ", cin >> Pufferfeld; q.push( Pufferfeld );wizzam schrieb:
Entwickeln Sie Funktionen für:
Eintrag einfügen,void ZyklischeWarteschlangeFuerC_Strings::push( const C_String& data ); // insertwizzam schrieb:
Eintrag entfernen,
void ZyklischeWarteschlangeFuerC_Strings::pop(); // removewizzam schrieb:
Warteschlange auf der Konsole ausgeben,
void ZyklischeWarteschlangeFuerC_Strings::print( std::ostream& out );wizzam schrieb:
Anzahl Einträge ausgeben,
int ZyklischeWarteschlangeFuerC_Strings::size() const;wizzam schrieb:
Warteschlange neu initialisieren, d.h. alle Einträge entfernen und Warteschlange in den
Anfangszustand versetzen.void ZyklischeWarteschlangeFuerC_Strings::clear();wizzam schrieb:
Verwenden Sie ein Menü zum Testen.
(s.u.)
wizzam schrieb:
Modifizieren Sie Ihr Programm, so dass Sie einen zusätzlichen Menüpunkt
„Warteschlange initialisieren“ hinzufügen, wobei Sie die Länge der erzeugten
Warteschlange angeben können. Jetzt können Sie natürlich kein char * Feld konstanter
Länge mehr deklarieren. Sie müssen das char * Feld dynamisch mit Hilfe von new
erzeugen.
Modifizieren Sie Ihr Programm, so dass Sie einen zusätzlichen Menüpunkt
„Warteschlangen Länge ändern“ hinzufügen. Einträge in Ihrer Warteschlange sollen bei
diesem Menüpunkt erhalten bleiben. Vergrößern der Warteschlange soll auf jeden Fall
funktionieren. Verkleinern ist optional, d.h. muss nicht unbedingt implementiert werden.void ZyklischeWarteschlangeFuerC_Strings::reserve( int capacity );wizzam schrieb:
Hinweis: Unter C-String verstehen wir ein char-Feld, das mit einem 0-Zeichen begrenzt ist.
Denken Sie an die Funktionen zur Unterstützung der C-Stringbehandlung z.B. strcpy()
oder strlen().Also so:
struct C_String { private: char* m_str; };Diese Anforderung an C-String verlangsamt das ganze ziemlich, aber bitte ..
und gleich alles zusammen, weil bald Weihnachten ist:
#include <iostream> #include <iomanip> #include <cassert> #include <cstring> // strlen, strcpy struct C_String { C_String() : m_str(0) {} ~C_String() { clear(); } C_String( const C_String& b ) : m_str( 0 ) { std::size_t len = b.m_str == 0? 0: std::strlen( b.m_str ); if( len > 0 ) { m_str = new char[len + 1]; std::strcpy( m_str, b.m_str ); } } C_String& operator=( const C_String& b ) { C_String tmp( b ); tmp.swap( *this ); return *this; } C_String& operator+=( char c ) { // langsam, aber einfach zu programmieren std::size_t len = m_str == 0? 0: std::strlen( m_str ); char* str = new char[len + 2]; if( m_str ) std::strcpy( str, m_str ); str[len] = c; str[len+1] = char(0); delete[] m_str; m_str = str; return *this; } void clear() { delete[] m_str; m_str = 0; } void swap( C_String& b ) { std::swap( m_str, b.m_str ); } // -- C-String ausgeben friend std::ostream& operator<<( std::ostream& out, const C_String& s ) { for( const char* p = s.m_str; p && *p != char(0); ++p ) out << *p; return out; } // -- C-String einlesen friend std::istream& operator>>( std::istream& in, C_String& s ) { std::istream::sentry ok( in ); if( ok ) { s.clear(); std::istream::iostate state = std::ios_base::goodbit; const std::ctype< char >& ct = std::use_facet< std::ctype< char > >( in.getloc() ); for( std::istream::int_type m = in.rdbuf()->sgetc(); ; m = in.rdbuf()->snextc() ) { if( std::istream::traits_type::eq_int_type( m, std::istream::traits_type::eof() ) ) { state |= std::ios_base::eofbit; break; } const char c = std::istream::traits_type::to_char_type( m ); if( ct.is( std::ctype_base::space, c ) ) break; s += c; } if( s.empty() ) state |= std::ios_base::failbit; in.setstate( state ); } return in; } bool empty() const { return m_str == 0 || *m_str == char(0); } private: char* m_str; }; class ZyklischeWarteschlangeFuerC_Strings { public: ZyklischeWarteschlangeFuerC_Strings( int capacity = 13 ) : m_capacity( capacity ) , m_data( capacity == 0? 0: new C_String[m_capacity] ) , m_posinsert( 0 ) , m_posremove( 0 ) , m_anz( 0 ) {} ~ZyklischeWarteschlangeFuerC_Strings() { delete[] m_data; m_data = 0; } void push( const C_String& data ) // insert { if( m_anz >= m_capacity ) reserve( 2 * m_anz ); m_data[ m_posinsert ] = data; m_posinsert = inc( m_posinsert ); ++m_anz; } void pop() // remove { assert( !empty() ); m_data[ m_posremove ].clear(); m_posremove = inc( m_posremove ); --m_anz; } C_String& front() { assert( !empty() ); return m_data[ m_posremove ]; } void clear() { while( !empty() ) pop(); } int size() const { return m_anz; } bool empty() const { return m_anz == 0; } void print( std::ostream& out ) { bool first = true; for( int i = m_posremove; i != m_posinsert || (first && !empty()); i=inc(i), first = false ) out << std::setw(3) << i << ": " << m_data[i] << "\n"; } int max_size() { return m_capacity; } void reserve( int capacity ) { while( size() > capacity ) // ggf. überzählige Einträge löschen pop(); C_String* data = new C_String[ capacity ]; C_String* dst = data; bool first = true; for( int src = m_posremove; src != m_posinsert || (first && !empty()); src=inc(src), first = false ) *dst++ = m_data[src]; delete[] m_data; m_capacity = capacity; m_data = data; m_posinsert = dst - data; if( m_posinsert >= m_capacity ) m_posinsert = 0; m_posremove = 0; } private: ZyklischeWarteschlangeFuerC_Strings( const ZyklischeWarteschlangeFuerC_Strings& ); ZyklischeWarteschlangeFuerC_Strings& operator=( const ZyklischeWarteschlangeFuerC_Strings& ); int inc( int i ) { if( ++i >= m_capacity ) i = 0; return i; } // -- Members int m_capacity; C_String* m_data; int m_posinsert; // index back; zeigt auf den ersten freien Platz hinter dem zuletzt eingefügten Element int m_posremove; // index front; zeigt auf das älteste eingefügte Element int m_anz; }; int main() { using namespace std; ZyklischeWarteschlangeFuerC_Strings q; cout << "i(n)it, (i)nsert, (d)elete, (c)lear all, (p)rint all, print an(z), (e)xit" << endl; for( char cmd; cout << "> ", cin >> cmd; ) { switch( cmd ) { case 'n': // Warteschlangen Länge ändern { int initqueue; cout << "Wie gross soll die Queue werden? " << endl; if( cin >> initqueue ) q.reserve( initqueue ); } break; case 'i': // Einfügen { C_String Pufferfeld; cout << "Bitte geben Sie ein Wort ein: ", cin >> Pufferfeld; q.push( Pufferfeld ); } break; case 'd': // delete (Entfernen) if( !q.empty() ) { C_String item = q.front(); q.pop(); cout << "Item '" << item << "' geloescht" << endl; } else cout << "Es gibt keine Elemente zum loeschen" << endl; break; case 'p': // print; auf der Console ausgeben q.print( cout ); break; case 'c': // clear; Warteschlange neu initialisieren q.clear(); cout << "Alle Items geloescht" << endl; break; case 'z': // Anzahl der Elemente in der Warteschlange ausgeben cout << q.size() << " Eintraege" << endl; break; case 'e': return 0; } } return 0; }wizzam schrieb:
ich bin ein anfänger , der total mit komplexen c++ aufgaben bombadiert wird -.-'

..genau:xmas2: Werner
-
so wie ich das sehe, sollen die std::queuestd::string nachimplemntieren...
nur das eben als unterliegender Container statt einer normalen Liste oder eines Arrays eben eine Ringliste implementiert werden soll...Ich muss zugeben, dass mich anfangs das "Warteschlange für Strings" doch etwas irritiert hat :p
-
Werner, braucht man denn das Überladen des Shift-Operators (<<) wirklich? Das Objekt kann ja gut mit Zeigern auf char umgehen und macht das Ganze auch nicht viel anders, als du's geschrieben hast, oder liege ich falsch?
-
[Rewind] schrieb:
Werner, braucht man denn das Überladen des Shift-Operators (<<) wirklich? Das Objekt kann ja gut mit Zeigern auf char umgehen und macht das Ganze auch nicht viel anders, als du's geschrieben hast, oder liege ich falsch?
Ich gehe davon aus, das Du den
std::ostream& operator<<( std::ostream& out, const C_String& s )von Zeile 51 meinst.
Dein Einwand ist berechtigt. Der Streaming-Operator(oder ein Pendant) ist zwar notwendig, weil der (einzige) Member von C_String private ist, aber die Implementierung ist übertrieben. Das hat historische Gründe ..
Genauso gut, kürzer und performanter ist einfach:friend std::ostream& operator<<( std::ostream& out, const C_String& s ) { if( s.m_str ) out << s.m_str; return out; }Ich hatte vorher noch eine Längeninformation in
C_String, dadurch ist diese Implementierung entstanden und habe anschließend versucht die Aufgabestellung möglichst genau zu treffen und die Längeninformation weg rationalisiert; dabei blieb dann diese Implementierung inoperator<<übrig.Man sieht an meiner Lösung recht gut, dass man den
C_Stringeinfach durchstd::string, und anschließend dann auch gleichZyklischeWarteschlangeFuerC_Stringsdurchstd::queue< std:string >ersetzen kann - wie DrakoXP bereits bemerkt hat.
Es ist schon pervers, dass man regelmäßig von Anfängern verlangt, solchen Code zu schreiben, der in eine Library hinein gehört, statt ihnen beizubringen, wie man die Standard-Library benutzt
:xmas2: Werner
-
Werner Salomon schrieb:
Es ist schon pervers, dass man regelmäßig von Anfängern verlangt, solchen Code zu schreiben, der in eine Library hinein gehört, statt ihnen beizubringen, wie man die Standard-Library benutzt

Das stimmt schon, aber in den meisten Fällen betrachte ich solche Aufgaben als Übung. Zum einen fördert das das logische Denkvermögen und zum anderen wissen sie, wie es bei manchen Algorithmen "hinter den Kulissen" aussieht und wie sie funktionieren, was heutzutage nicht ganz selbstverständlich ist. Deine C-String-Klasse wäre dafür ein gutes Beispiel. Ich finde es ist nicht verkehrt, wenn sie das einmal gemacht haben, aber danach sollten sie auch die STL vernünftig lernen und immer bei Bedarf einsetzen dürfen.