Vector + Array



  • Ich mach wahrscheinlich wieder den größten Bockmist aber mal schauen was ihr sagt und hoffentlich hab ich diesmal mich auch dran gehalten alles vernünftig dazustellen und zu erklären also mein vorhaben:
    Ich möchte meinen vector<TokenType> Toki durch gehen und für jedes Token mit der Funktion Search die passende Übersetzung aus meinem 2D array (oder mehrdimensional?) suchen. Das ganz soll dann in dem vector<char> Trans gespeichert werden.

    Fehler:

    oopjs.cpp:140:31: Warnung: Vergleich zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlausdrücken [-Wsign-compare]
    oopjs.cpp:141:22: Fehler: ungültige Typen »unsigned char[int]« für Feldindex
    

    Der Fehler verwirrt mich und ich finde auch nichts bei Google.
    (Ach so schon alleine durch das erstellen des Beitrages habe ich aus anfänglichen 6 Fehler es auf einen Fehler + Warnung gebracht. 🙂 )

    Falls mein Ansatz komplett falsch ist und das so überhaupt nicht funktioniert bitte ich um Tipps wie ich es machen könnte. 🙂 Danke!

    .cpp

    #include "oopjs.h"
    
    #include <algorithm> 
    #include <vector> 
    #include <string> 
    #include <iostream> 
    #include <iterator>
    
    void Scanner::TranslateVeci(){
      for(std::vector<TokenType>::iterator it; Toki.begin() < Toki.end(); it++){
        int Scanner::Search(TokenType *it,unsigned char* TArray, size_t());  
      }
    }
    
    int Scanner::Search(TokenType *it , unsigned char* TArray, size_t()){
        for(int i = 0; i < size_t(); i++){ //Warnung
          if(*TArray[i][2] == *it){ //Fehler
    	Trans.push_back(i);
          }
        }
        return -1;
    }
    
    unsigned char* TArray[][2] = {
      {(unsigned char*)TT_LBRACKET,(unsigned char*)"("},
      {(unsigned char*)TT_RBRACKET,(unsigned char*)")"}, 
      {(unsigned char*)TT_LBRACE,(unsigned char*)"{"}, 
      {(unsigned char*)TT_RBRACE,(unsigned char*)"}"}, 
      {(unsigned char*)TT_COMMA,(unsigned char*)" "},
      {(unsigned char*)TT_SEMI,(unsigned char*)";"}, 
      {(unsigned char*)TT_COLON,(unsigned char*)":"}, 
      {(unsigned char*)TT_DOT,(unsigned char*)"."}, 
      {(unsigned char*)TT_PUBLIC,(unsigned char*)"this"}, 
      {(unsigned char*)TT_FUNC,(unsigned char*)"prototype"}, 
      {(unsigned char*)TT_CONS,(unsigned char*)"console"}, 
      {(unsigned char*)TT_QUOTE,(unsigned char*)"'"}, 
      {(unsigned char*)TT_STRING,(unsigned char*)"bla"}, 
      {(unsigned char*)TT_CLASS,(unsigned char*)"function"}, 
      {(unsigned char*)TT_HELLO,(unsigned char*)"hello"}, 
      {(unsigned char*)TT_BYE,(unsigned char*)"bye"}, 
      {(unsigned char*)TT_GREET,(unsigned char*)"greet"}, 
      {(unsigned char*)TT_NIL,(unsigned char*)" "} 
    };
    

    .h

    #ifndef OOPJS_H
    #define OOPJS_H
    
    #include <iostream> 
    #include <string> 
    #include <vector>
    #include <map>
    
    enum TokenType{                           // token definition
      TT_LBRACKET,
      TT_RBRACKET,
      TT_LBRACE,
      TT_RBRACE,
      TT_COMMA,
      TT_SEMI,
      TT_COLON,
      TT_DOT,
      TT_PUBLIC,
      TT_FUNC,
      TT_CONS,
      TT_QUOTE,
      TT_STRING,
      TT_CLASS,
      TT_HELLO,
      TT_BYE,
      TT_GREET,
      TT_NIL
    };
    
    static const char *TokenTypStr[] = {     // for error message
      "TT_LBRACKET",
      "TT_RBRACKET",
      "TT_LBRACE",
      "TT_RBRACE",
      "TT_COMMA",
      "TT_SEMI",
      "TT_COLON",
      "TT_DOT",
      "TT_PUBLIC",
      "TT_FUNC",
      "TT_CONS",
      "TT_QUOTE",
      "TT_STRING",
      "TT_CLASS",
      "TT_HELLO",
      "TT_BYE",
      "TT_GREET",
      "TT_NIL"
    };
    
    class Token{
    private:
      TokenType myType;
      int myValue;
    public:
      Token(TokenType type = TT_NIL, int value = 0);
      TokenType getType() const { return myType; }
      int getValue() const { return myValue; }
      const char *toString() const { return TokenTypStr[myType]; }  // error message
      bool equal(TokenType type) const { return myType == type; }         //comparison
    };
    
    class Scanner{
    public:
      void veci();
      Scanner(const std::string& input);
      Token getNextToken();
      void TranslateVeci();
      int Search(TokenType *it,unsigned char* TArray, size_t());
    private:
      unsigned char* TArray[][2];
      std::vector<TokenType> Toki;
      std::vector<char> Trans;
      std::string myInput;
      unsigned int myPos;                                            //Position at input
      char myCh;                                                     //last char
      void skipSpaces();
      void readNextChar();
    };
    
    #endif
    

  • Mod

    for(std::vector<TokenType>::iterator it; Toki.begin() < Toki.end(); it++){
        int Scanner::Search(TokenType *it,unsigned char* TArray, size_t());  
      }
    

    😮 Bitte gib uns den richtigen Code, nicht irgendwelchen Unsinn.

    Der direkte Fehler:
    TArray ist vom Typ unsigned char*. Von welchem Typ ist dann TArray[i]? Was ist dann TArray[i][2]? Oder gar *TArray[i][2]?

    Das Programm ist so furchtbar, über den Rest verkneif ich mir mal jeden Kommentar. Hast du das selber programmiert? 😮



  • Hallo, ich hab jetzt nicht deinen ganzen Code durchgesehen aber bei der Warnung scheint dir sowas passiert zu sein:

    int var = -3;
    unsigned un = 5;
    
    if(un==var) // Erzeugt hier die Warnung
    {
    
    }
    
    un = var;
    cout<<un<<endl;  // Nööööö da kommt nicht -3 raus ;D
    

    Warnung: Vergleich von signed- und unsigned-Werten

    Jetzt sollte dir was auffallen.



  • Schau dir mal Zeile 11 an, die sieht komplett widersinnig aus. Was soll das bedeuten? Sieht so aus, als wolltest du eine Funktion aufrufen, hast aber einfach den Kopf der Funktionsdefinition aus Zeile 15 kopiert...

    Zeile 15: was ist der dritte Parameter? Du musst einen Typ und ggf einen Namen angeben für den Parameter. Schrägerweise ist das, was du dort angegeben hast, sogar ein Typ: Der Typ einer Funktion, die ein size_t zurückgibt und keine Argumente erwartet. Ziemlich sicher nicht das, was du willst. In Zeile 16 taucht nochmal size_t() auf, an der Stelle bedeutet es aber was anderes: ein default-Konstruiertes Objekt vom Typ size_t, bedeutet also 0u (eine vorzeichenlose Null). Sicher auch nicht das was du willst.

    Den Krempel mit dem mehrdimensionalen Array würde ich komplett weglassen, das bringt nichts außer Kopfschmerzen, mal davon abgesehen, dass du unten beim Befüllen in der ersten Spalte immer ein TokenType in einen unsigned char* castest, was bestenfalls sehr komisch riecht.
    Wieso benutzt du keine std::map?



  • int i = 0; i < size_t(); i++
    

    int ist vorzeichenbehaftet, size_t ist es nicht. Darum meckert er hier mit der Warnung, aber was das size_t() soll frag ich mich auch 😕.

    int Scanner::Search(TokenType *it,unsigned char* TArray, size_t());
    

    Was soll das sein und warum zur Hölle benutzt du size_t immer mit den Klammern?

    if(*TArray[i][2] == *it)
    

    Übrigens rufst du hier das Element mit dem Index 2 in einem Array mit 2 Elementen (dass es mehrere Dimensionen hat ist hier irrelevant) auf. Siehste den Fehler? Aber den wirst du erst zur Laufzeit mitbekommen.

    Was den Fehler angeht: Du hast TArray zum Zeitpunkt der Benutztung noch gar nicht deklariert.

    Abgesehen davon, dass der Code wie schon erwähnt wurde grauenvoll aussieht hier noch einige kleine Hinweise von mir:

    Einige dich, ob du zuerst private oder zuerst public Member deklarierst, sonst wird das ein elendiges Durcheinander.
    Typecasts sind meist eine Fehlerquelle, die du meist erst zur Laufzeit bemerkst. -> vermeiden
    Wenn eine Funktion nur einen Rückgabewert hat kannst du sie auch gleich als void vereinbaren.
    C-Strings sind nicht ohne Grund veraltet und man hat auch nicht ohne Grund std::string entwickelt.



  • Erstmal danke für alle antworten.

    SeppJ schrieb:

    Der direkte Fehler:
    TArray ist vom Typ unsigned char*. Von welchem Typ ist dann TArray[i]? Was ist dann TArray[i][2]? Oder gar *TArray[i][2]?

    Der Tobi schrieb:

    if(*TArray[i][2] == *it)
    

    Übrigens rufst du hier das Element mit dem Index 2 in einem Array mit 2 Elementen (dass es mehrere Dimensionen hat ist hier irrelevant) auf. Siehste den Fehler? Aber den wirst du erst zur Laufzeit mitbekommen.

    Was den Fehler angeht: Du hast TArray zum Zeitpunkt der Benutztung noch gar nicht deklariert.

    So richtig hab ich das noch nicht verstanden. Also muss das Array vor den Funktionen stehen?
    Muss ich also TArray[i][2] vorher deklarieren?

    Der Tobi schrieb:

    int i = 0; i < size_t(); i++
    

    int ist vorzeichenbehaftet, size_t ist es nicht. Darum meckert er hier mit der Warnung, aber was das size_t() soll frag ich mich auch 😕.

    int Scanner::Search(TokenType *it,unsigned char* TArray, size_t());
    

    Was soll das sein und warum zur Hölle benutzt du size_t immer mit den Klammern?

    pumuckl schrieb:

    Zeile 15: was ist der dritte Parameter? Du musst einen Typ und ggf einen Namen angeben für den Parameter. Schrägerweise ist das, was du dort angegeben hast, sogar ein Typ: Der Typ einer Funktion, die ein size_t zurückgibt und keine Argumente erwartet. Ziemlich sicher nicht das, was du willst. In Zeile 16 taucht nochmal size_t() auf, an der Stelle bedeutet es aber was anderes: ein default-Konstruiertes Objekt vom Typ size_t, bedeutet also 0u (eine vorzeichenlose Null). Sicher auch nicht das was du willst.

    Bassmaster schrieb:

    Hallo, ich hab jetzt nicht deinen ganzen Code durchgesehen aber bei der Warnung scheint dir sowas passiert zu sein:

    int var = -3;
    unsigned un = 5;
    
    if(un==var) // Erzeugt hier die Warnung
    {
    
    }
    
    un = var;
    cout<<un<<endl;  // Nööööö da kommt nicht -3 raus ;D
    

    Warnung: Vergleich von signed- und unsigned-Werten

    Jetzt sollte dir was auffallen.

    Gut also ich glaube da muss ich mir noch mal ein Kopf zu machen und es fliegt nun erstmal raus das size_t.

    pumuckl schrieb:

    Den Krempel mit dem mehrdimensionalen Array würde ich komplett weglassen, das bringt nichts außer Kopfschmerzen, mal davon abgesehen, dass du unten beim Befüllen in der ersten Spalte immer ein TokenType in einen unsigned char* castest, was bestenfalls sehr komisch riecht.
    Wieso benutzt du keine std::map?

    Hab ich über legt, mein Ausbilder hat mir den Tipp gegeben mit dem Array ich werd mir das aber jetzt mal mit einer std::map anschauen.

    Der Tobi schrieb:

    Abgesehen davon, dass der Code wie schon erwähnt wurde grauenvoll aussieht hier noch einige kleine Hinweise von mir:

    Einige dich, ob du zuerst private oder zuerst public Member deklarierst, sonst wird das ein elendiges Durcheinander.
    Typecasts sind meist eine Fehlerquelle, die du meist erst zur Laufzeit bemerkst. -> vermeiden
    Wenn eine Funktion nur einen Rückgabewert hat kannst du sie auch gleich als void vereinbaren.
    C-Strings sind nicht ohne Grund veraltet und man hat auch nicht ohne Grund std::string entwickelt.

    private public hab ich geändert.
    Welche Funktion meinst du? Die Search?
    und wo hab ich C-Strings? 😕

    SeppJ schrieb:

    Das Programm ist so furchtbar, über den Rest verkneif ich mir mal jeden Kommentar. Hast du das selber programmiert? 😮

    Ja hab ich sonst würdest du das wahrscheinlich nicht so doof finden. 🤡

    Alles im allen hab ich wohl noch viel falsch. Ich schau mir das jetzt noch mal mit der std::map an und überleg mir was neues. Danke soweit!



  • Mit dem Rückgabewert meint er ziemlich sicher die Search-Methode, da die bei dir immer -1 zurück gibt, egal was passiert. Was die C-Strings angeht meint er wohl die ganzen const char* im Header und die Stringliterale in der .cpp - Ob man für die Konstanten wirklich std::string verwenden sollte ist strittig, ich denke da gibts erstmal viel wichtigere Baustellen (z.B. dem Code erstmal einen Sinn zu geben...)



  • Was mir eigentlich Übelkeit bereitete waren die ganzen übergaben von const unsigned char* .

    Muss ich also TArray[i][2] vorher deklarieren?

    Du solltest am besten gar kein Array verwenden, sondern, wie schon gesagt std::map . Von Globalen Variablen allgemein: Hände weg!

    Gut also ich glaube da muss ich mir noch mal ein Kopf zu machen und es fliegt nun erstmal raus das size_t

    Je nachdem, size_t ist für die Länge von Dingen (besser kann ichs grad nicht formulieren) gedacht, wie der Name schon sagt, sollte man es am besten für Längen (z.B. von Strings, Vektoren u.ä.) verwenden, da diese schlecht negativ werden können und man somit eine feste Länge für alle solche Objekte hat. Aber der Einfachheit halber würd ich für nicht-negative Zahlen immer unsigned int und für den Rest int benutzen (Wobei size_t meist nur ein typedef auf unsigned int bzw. etwas ähnlich großes ist).



  • Ich hab nun noch mal bisschen rum gespielt und rum gedacht. Da kam mir die Idee das einfach direkt als das Zeichen in einen vector zu pushen wie ich es möchte. Problem ist nun dabei das es mit einem vectorstd::string geht es nicht. Mit einem vector<char> klappt es nur nicht mit längeren Zeichenketten. Was ja auch logisch ist. Jemand dazu eine Idee ob ich ihm das irgendwie umwandeln kann oder wie ich das hin bekomme.

    Ach so es geht um den vector<char> Trans;

    Token Scanner::getNextToken(){  
      std::string buf;
      skipSpaces();                          //to skip chars which are not used
      switch(myCh){
        case '(':
          readNextChar();
          Toki.push_back(TT_LBRACKET);
          Trans.push_back('(');
          return Token(TT_LBRACKET);
        case ')':
          readNextChar();
          Toki.push_back(TT_RBRACKET);
          Trans.push_back(')');
          return Token(TT_RBRACKET);
        case '}':
          readNextChar();
          Toki.push_back(TT_RBRACE);
          Trans.push_back('}');
          return Token(TT_RBRACE);
        case '{':
          readNextChar();
          Toki.push_back(TT_LBRACE);
          Trans.push_back('{');
          return Token(TT_LBRACE);
        case ',':
          readNextChar();
          Toki.push_back(TT_COMMA);
          Trans.push_back(',');
          return Token(TT_COMMA);
        case ';':
          readNextChar();
          Toki.push_back(TT_SEMI);
          Trans.push_back(';');
          return Token(TT_SEMI);
        case ':':
          readNextChar();
          Toki.push_back(TT_COLON);
          Trans.push_back(':');
          return Token(TT_COLON);
        case '.':
          readNextChar();
          Toki.push_back(TT_DOT);
          Trans.push_back('.');
          return Token(TT_DOT);
        case '"':
          readNextChar();
          Toki.push_back(TT_QUOTE);
          Trans.push_back('"');
          return Token(TT_QUOTE);
                                            //read as long its a letter
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': 
          while(isalpha(myCh)){
    	buf += myCh;   
    	readNextChar();
    	if(buf == "class"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_CLASS);
    	  Trans.push_back('prototype');
    	  return Token(TT_CLASS);
    	}
    	if(buf == "function"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_FUNC);  
    	  Trans.push_back('function');
    	  return Token(TT_FUNC);
    	}
    	if(buf == "public"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_PUBLIC);
    	  Trans.push_back('this');
    	  return Token(TT_PUBLIC);
    	}
    	if(buf == "hello"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_HELLO);
    	  Trans.push_back('hello');
    	  return Token(TT_HELLO);
    	}
    	if(buf == "bye"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_BYE);
    	  Trans.push_back('bye');
    	  return Token(TT_BYE);
    	}
    	if(buf == "greet"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_GREET);
    	  Trans.push_back('greet');
    	  return Token(TT_GREET);
    	}
    	if(buf == "console"){
    	  buf += myCh;
    	  readNextChar();   
    	  Toki.push_back(TT_CONS);
    	  Trans.push_back('console');
    	  return Token(TT_CONS);
    	}
          }   
          Toki.push_back(TT_STRING);
          Trans.push_back('bla');
          return Token(TT_STRING);
    
        default:
          if(myCh != 0){
    	std::cerr << "Error: not used Char '" << myCh << "'" << std::endl;
          }      
          break;
      }  
      return Token(TT_NIL);
    };
    

  • Mod

    Was ist deine Frage? Dass eine Liste von Zeichenketten etwas anderes bedeutet als eine Liste von Zeichen sollte doch wohl klar sein, oder? Oder ist dir insgesamt nicht bekannt, wie sich char, string, char* und char[] zueinander verhalten?



  • SeppJ schrieb:

    Was ist deine Frage? Dass eine Liste von Zeichenketten etwas anderes bedeutet als eine Liste von Zeichen sollte doch wohl klar sein, oder? Oder ist dir insgesamt nicht bekannt, wie sich char, string, char* und char[] zueinander verhalten?

    Ich hab doch sogar geschrieben das es klar ist, dass das so nicht funktioniert. Meine Frage ist dem nach ob man jetzt das irgendwie hin bekommt das man das ganz "Wort" dort rein bekommt.



  • Hallo Enno,

    warum sollte es denn mit einem vectorstd::string nicht gehen?
    Aber wofür benötigst du überhaupt den vector 'Trans'?



  • Th69 schrieb:

    Hallo Enno,

    warum sollte es denn mit einem vectorstd::string nicht gehen?
    Aber wofür benötigst du überhaupt den vector 'Trans'?

    Also ich hab es nicht hinbekommen mit vectoestd::string nicht hinbekommen das mich push_back dort rein zu bekommen.
    Na in vector<char> Trans soll das rein kommen?

    EDIT:
    Hab was gefunden was mir hilft:

    std::copy("function","function"+8,std::back_inserter(Trans));
    

Anmelden zum Antworten