Spalte einlesen und Zellen vergleichen



  • Hallo,

    ich habe ein "kleines" Problem und komme nicht weiter....

    Und zwar...ich habe eine CSV Datei, die ich einlese. 2 Spalten davon lade ich in die Map. Spalte 3: Name = Key und Spalte 4: Adresse = Value. Das klappt auch soweit.
    Das Problem ist, dass die Namen öfters vorkommen und die Map das nicht so annimmt, da immer nur ein Key mit einem Value vorhanden sein kann. Daher wollte ich nun die Spalte 2 mit ins Spiel bringen. Hier stehen die Levels von den Namen.

    Beispiel:

    Level Name Adresse
    1 A 123
    2 B 234
    3 C 345
    3 D 456
    4 E 567
    3 F 678
    4 E 789

    Wenn ich die Adresse vom ersten E rausbekommen möchte, möchte ich als Input folgenden eingeben: A.B.D.E
    Bei der Adresse vom zweiten E möchte ich folgendes eingeben: A.B.F.E

    Dieser Input soll ein zusammengesetzter String sein, der dann als Key in die Map geladen wird, damit eine genaue Zuordung vorliegt.

    Bis lang habe ich den Code(nur wie die bis lang in die Map geladen werden mit dem einfachen vorhandenen Key):

    getline(MyFile, String);
    if (String != Line) // If the line is not empty
    {
    Line = String;
    pointer_mychar = &String[0];
    pointer_mychar = strtok(pointer_mychar, delimiter);
    int i=0;
    int pairfind = 0;

    while(pointer_mychar != NULL)
    {if (i>1 && i<4) // Spalte Name and Address
    {

    if (pairfind == 0) {

    Name = newString;// der neu zusammen gesetzte string
    pairfind = 1;
    } else (pairfind == 1) {
    Address = pointer_mychar; // Spalte Adresse
    pairfind =2;
    }
    pointer_mychar = strtok(NULL, delimiter);

    i++;
    }

    Ich weiß leider nicht, wie ich das am besten hier noch eine Schleife hinzufügen kann, der dann die Spalte Level mit betrachtet und dann die Namen neu zusammensetzt zu einem neuen String und den in die Map läd....

    Ne Idee???


  • Mod

    Deine Beschreibung ist sehr unklar, aber ich werfe aufgrund folgenden Satzes mal das Stichwort multimap in dem Raum:

    Das Problem ist, dass die Namen öfters vorkommen und die Map das nicht so annimmt, da immer nur ein Key mit einem Value vorhanden sein kann.

    Falls das nicht sein sollte, wonach du suchst: Bitte verständlichere Frage stellen!



  • Das tut mir Leid, dass ich mich so unklar ausgedrückt habe....

    Also die Multimap wäre eine Möglichkeit, aber ich würde dann alle möglichen Treffer als Output erhalten. Das ist aber nicht gewollt. Ich möchte nur ein bestimmtes Output haben.

    Also ich möchte eigentlich die Spalte mit den Levels einlesen und die eben Zeile für Zeile vergleichen.

    j= level der aktuellen Zeile
    n = level der vorherigen zeile

    j>n dann in die Spalte der Namen gehen und den Namen von dem Level j and dem von n dran hängen
    j<n dann die vorherigen Zeilen überprüfen bis die Bedingung j>n ist und dann in die Spalte der Namen gehen und den Namen vom Level j and den vom n dran hängen
    j=n dann die vorherigen Zeilen überprüfen bis die Bedingung j>n ist und dann in die Spalte der Namen gehen und den Namen vom Level j and den vom n dran hängen

    Diesen zusammengesetzten Namen dann in die Map mit der zugehörigen Adresse in die Map laden.



  • Also möchtest du aus deiner Beispieleingabe irgendetwas wie das hier erzeugen:

    123: A
    234: A.B
    345: A.B.C
    456: A.B.D
    567: A.B.D.E
    678: A.B.F
    789: A.B.F.E
    

    https://ideone.com/9tuR7d

    std::vector<int> levels;
      std::string hangy;
    
      std::string name;
      for (int level, address; std::cin >> level >> name >> address;) {
        while (!levels.empty() && levels.back() >= level)
          levels.pop_back(), hangy.erase(hangy.size()-2);
        levels.push_back(level);
        hangy += name + ".";
        std::cout << address << ": " << hangy.substr(0, hangy.size()-1) << '\n';
      }
    


  • Danke dir, aber ich weiß jetzt nicht genau, ob ich das richtig verstanden habe.... Laut deinem Beispiel gebe ich als Input die Adresse ein und bekomme dann den Namen als Output raus, stimmt es? Aber eigentlich ist das ja genau anders rum gewollt...

    Kann ich das so ähnlich mit in mein Code (was ich in dem ersten Beitrag gepostet hab) mit einbauen? Wenn ja, weiß ich nicht genau, wo ich das machen kann, damit ich den Namen (Key) übergeben kann, damit es in die Map geladen wird.

    Wieso steht am Ende -2???
    levels.pop_back(), hangy.erase(hangy.size()-2);

    Tut mir Leid, dass ich so dumme Fragen stelle 😞



  • meine Frage wäre aich nocht..... in der csv datei stehen die levels in der 1. spalte. das muss doc auch irgendwie angegeben werden, damit man die werte aus der richtigen spalte ausliest oder?



  • YumiFerrari schrieb:

    Wieso steht am Ende -2???
    levels.pop_back(), hangy.erase(hangy.size()-2);

    Tut mir Leid, dass ich so dumme Fragen stelle 😞

    Dumme Fragen gibt's nicht 😉
    hangy.erase(hangy.size()-2) heißt nichts anderes als dass die letzten beiden Stellen des Strings gelöscht werden, daher die ' -2 ' siehe std::string::erase.

    YumiFerrari schrieb:

    meine Frage wäre aich nocht..... in der csv datei stehen die levels in der 1. spalte. das muss doc auch irgendwie angegeben werden, damit man die werte aus der richtigen spalte ausliest oder?

    Das Codestück

    std::cin >> level >> name >> address;
    

    liest stets die gesamte Zeile. Beim nächsten Durchlauf der for-Schleife ist dann zwangsläufig der Anfang der folgenden Zeile dran.

    Gruß
    Werner



  • ahh ja verstehe 🙂 danke!

    noch eine Frage... wie kann ich das denn mit meinem Code in Verbindung bringen? ich hab so einiges geschrieben und hab keine ahnung, wie ich das zusammen setzen kann.... hab hier ja nur einen teil rein gestellt.



  • okay... wenn ich mir das so anschaue ist das schwer zu sagen, ob man das so zusammenfügen kann..... dafür müsste man schon mehr vom programmcode sehen glaube ich....wenn du magst, dann kann ich dir das nachricht schicken bevor ich hier das voll packe mit code



  • YumiFerrari schrieb:

    noch eine Frage... wie kann ich das denn mit meinem Code in Verbindung bringen? ich hab so einiges geschrieben ....

    Du hast dies geschrieben

    YumiFerrari schrieb:

    getline(MyFile, String);
        if (String != Line) // If the line is not empty
        {
            Line = String;
            pointer_mychar = &String[0];
            pointer_mychar = strtok(pointer_mychar, delimiter);
            int i=0;
            int pairfind = 0;
    
            while(pointer_mychar != NULL)
            {
                if (i>1 && i<4) // Spalte Name and Address
                {
                    if (pairfind == 0) {
                        Name = newString;// der neu zusammen gesetzte string
                        pairfind = 1;
                    } else if (pairfind == 1) { // <====== hier fehlte das 'if'
                        Address = pointer_mychar; // Spalte Adresse
                        pairfind =2;
                    }
                    pointer_mychar = strtok(NULL, delimiter);
                    i++;
                }
    

    streng genommen macht das genau das was folgende zwei Zeilen machen:

    int level;
        MyFile >> level >> Name >> Address
    

    mehr ist es nicht!

    Was willst Du jetzt 'zusammenfügen'?

    Gruß
    Werner



  • im ernst????? ahahaha ich saß so lange an diesen paar zeilen 😞 hehe egal... so lern ich das ja zumindest....

    also ich soll eine csv datei einlesen und diese in eine map laden. nur ich hab mehrere namen die sich wiederholen mit einem anderen value aber. das hab ich ja schon geschrieben gehabt. daher wollte ich die levels mit berücksichtigen.....

    hier ist mein code.....

    typedef struct ODK_DATA_STRUCT
    {
    unsigned char dataType; // Data Type of memory
    ....
    } ODK_DATA_STRUCT; // Data structure for use with Read/Write functions
    // Self defined

    #define FILEPATH "..." // Hier bitte dateipfad einfügen
    #define MinColumnSize 1
    #define MaxColumnSize 4

    class TableReader {
    std::map<string, ODK_DATA_STRUCT> dataMap;

    public:
    ODK_DATA_STRUCT dataStructForShortName(string shortName);
    void getAddress(string searchname);
    TableReader();
    ~TableReader();

    private:
    map<string, ODK_DATA_STRUCT> loadMapFromCSV();
    };

    unsigned short shortFromString(string string) {

    stringstream ss(string);
    unsigned short i;
    if( (ss >> i).fail() )
    {
    //error
    //cout << "Error transcoding string " << string << "to number" << endl;
    return i;
    } else {

    return i;
    }

    }

    void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
    return;
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
    str.replace(start_pos, from.length(), to);
    start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
    }

    void split(const string& s, char c, vector<string>& v) {
    // Used to split strings by given delimiter (for analyzing the rtName)
    string::size_type i = 0;
    string::size_type j = s.find(c);
    while (j != string::npos) {
    v.push_back(s.substr(i, j-i));
    i = ++j;
    j = s.find(c, j);
    if (j == string::npos)
    v.push_back(s.substr(i, s.length( )));
    }
    }

    TableReader::TableReader() {
    dataMap = loadMapFromCSV();
    }

    TableReader::~TableReader() {
    // delete dataMap;
    }

    map<string, ODK_DATA_STRUCT> TableReader::loadMapFromCSV ()
    {
    ifstream MyFile;
    string String;
    int z=0; // Used for endless while loops
    string Zeile = " ";
    char delimiter[] = ";";
    char* pointer_mychar;
    map<string, ODK_DATA_STRUCT> names;

    MyFile.open (FILEPATH);
    if (!MyFile)
    {
    printf ("Fehler beim Oeffnen der Datei!\n");
    throw 10;
    }
    else
    // printf ("Die Datei wurde geoeffnet!\n");

    MyFile.seekg (0, ios::beg);

    while(z<1)
    {

    string shortName; // The short name given in the CSV file
    string rtName; // The rtName given in the CSV file
    string datatypeStringFromTable; // The data Type given in the CSV
    int dataTypeNumRep; // An integer representation of the datatypeStringFromTable
    ODK_DATA_STRUCT dataStruct; // The data struct to be filled
    vector<string> v; // Initing the vector where we are going to put the two parts of the rtName

    getline(MyFile, String);
    if (String != Zeile) // If the line is not empty
    {
    Zeile = String;
    pointer_mychar = &String[0];

    pointer_mychar = strtok(pointer_mychar, delimiter);

    int i=0;
    int pairfind = 0;

    while(pointer_mychar != NULL)
    {
    if (i>MinColumnSize && i< MaxColumnSize) // Reading column 2-4 only.
    {

    if (pairfind == 0) {
    shortName = pointer_mychar; // First collum is the short Name
    pairfind = 1;
    } else if(pairfind == 1) {
    rtName = pointer_mychar; // Second collum is the rtName which will be analyzed here
    size_t position =rtName.find("]");
    rtName.erase(0, position+1);

    split(rtName, ',', v); // Splitting by a ,

    pairfind = 2;
    } else {
    datatypeStringFromTable = pointer_mychar;

    dataTypeNumRep = i;
    pairfind = 0; // Resetting pairfind for a new round
    }
    }
    pointer_mychar = strtok(NULL, delimiter);

    i++;
    }
    } else {
    break;
    }

    string firstPartOfrtName;
    string secondPartOfrtName;

    if (v.size() == 2) {
    firstPartOfrtName = v[0];
    secondPartOfrtName = v[1];
    } else {
    firstPartOfrtName = "";
    secondPartOfrtName = "";
    }

    if (firstPartOfrtName.find("DB") != string::npos) {
    dataStruct.memoryArea = ODK_MEM_AREA_DB;
    replaceAll(firstPartOfrtName, "DB", "");
    dataStruct.dbNumber = shortFromString(firstPartOfrtName);

    } /hier folgen noch ein paar typen*/

    /* Second part of RTName after the comma */

    if (secondPartOfrtName.find("STRING") != string::npos) {
    replaceAll(secondPartOfrtName, "STRING", "");
    dataStruct.dataType = ODK_DATA_TYPE_STRING;
    vector<string> p;
    if (secondPartOfrtName.find(".") != string::npos ) {
    split(secondPartOfrtName, '.', p);
    if (p.size() >= 1) {
    dataStruct.areaOffset = shortFromString(secondPartOfrtName);

    dataStruct.maxSize = shortFromString(p[1]);
    }
    }

    else {
    dataStruct.areaOffset = shortFromString(firstPartOfrtName);
    }
    /*hier folgen wiederum weitere typen*/

    names.insert(std::pair<string, ODK_DATA_STRUCT>(shortName,dataStruct));
    // Inserting finished pair into map

    }

    cout << "Read Process Complete!" << endl; // Debbung logs
    cout << "Map size: " << names.size() << endl;
    MyFile.close(); // Datei wird geschlossen
    return names;
    }

    ODK_DATA_STRUCT TableReader::dataStructForShortName(string shortName){

    ODK_DATA_STRUCT dataStruct = dataMap[shortName];
    return dataStruct;
    }

    int main ()
    { TableReader tableReader;
    while (true) {
    cout << "Enter string to search for" << endl;
    string searchString;
    cin >> searchString;

    cout << "Data Type: " << dataTypeName << endl;
    cout << "Quantity: " << dStruct.quantity << endl;
    cout << "db Number: " << dStruct.dbNumber << endl;
    cout << "Memory Area: " << memAreaName << endl;
    cout << "Area Offset: " << dStruct.areaOffset << endl;
    printf ("bitNumber: %d\n", dStruct.bitNumber );
    //cout << "pBuff: " << dStruct.pBuff << endl;
    cout << "max Size: " << dStruct.maxSize << endl;
    // cout << "status: " << dStruct.status << endl;

    cout << "------------------------------------" << endl;
    }

    return 0;
    }



  • hier betrachte ich die levels gar nicht.... und das war die frage, wie ich das hier irgendwie mit berücksichtigen kann und dann eben wie bei dem einen beispiel von benutzer abfe die neuen keys, die nach dem level zusammen gesetzt worden sind ind die map lade. dann kann ich bei der eingabe auch den zusammengesetzen key eingeben und bekomme die richtige adresse raus.

    ich hoffe ich hab mich jetzt nicht unklar ausgdrückt oder so



  • hat einer ne idee???? ich bin immer noch nicht schlauer geworden.... 😞



  • Hallo YumiFerrari,

    YumiFerrari schrieb:

    hat einer ne idee???? ich bin immer noch nicht schlauer geworden.... 😞

    nein - bist Du anscheinend nicht.
    Wenn Du hier Hilfe bekommen möchtest, so biete es sich an, konkrete Fragen zu einzelnen Code-Stellen oder ähnliches zu stellen. Du kannst auch fragen, wie man ein bestimmtes Problem löst, aber Du stellst hier Code ein, der schwer zu lesen ist, Syntaxfehler enthält und bei dem nicht nachzuvollziehen ist, in wie weit der Code was mit Deinem anfangs geschilderten Problem zu tun hat.

    In Deinem ersten Beitrag dieses Threads geht es z.B.: um Level, Name und Adresse. Davon ist in Deinem Code nichts mehr zu finden.

    YumiFerrari schrieb:

    hier betrachte ich die levels gar nicht.... und das war die frage, wie ich das hier irgendwie mit berücksichtigen kann und dann eben wie bei dem einen beispiel von benutzer abfe die neuen keys, die nach dem level zusammen gesetzt worden sind ind die map lade. dann kann ich bei der eingabe auch den zusammengesetzen key eingeben und bekomme die richtige adresse raus.

    Von 'Name' und 'Adresse' ist nichts mehr zu sehen, dafür scheinen in der Datei Dinge wie "STRING" und "]" vor zukommen. Wie sieht denn diese Datei jetzt aus - das gleiche Format wie oben kann es nicht sein.

    Es wird Dir niemand sagen können, wie/wo der Level 'zu berücksichtigen' ist, weil gar nicht klar ist, was der Code unten mit der Problemschilderung oben zu tun hat.

    Versuche doch mal, uns zu erklären, was der Input Deines geplanten Programms ist und was als Output erwartet wird; am besten an Hand eines Beispiels.

    Gruß
    Werner



  • Hey,

    danke für die rückmeldung.... also das mit level name adresse war eigentlich nur ein beispiel gewesen....

    den code habe ich reingestellt, weil ich nicht genau wusste, wo ich genau die veränderung vornehmen kann.... aber grad bin ich soweit, dass ich weiß, wo genau ich das ansetzen muss.....gib mir kurz zeit, dann schilder ich den aktuellen standpunkt mit einer konkreten frage



  • die spalten sehen so aus.
    tagtype; level; shortname; rtname

    Die lese ich alle ein, was auch soweit klappt. Nun ist das so, dass ich verschiedene Levels (genau 6)habe. von denen ist es abhängig, was für ein Shortname herraus kommt. daher habe ich versucht levelContent1 - levelContent6 anzulegen, dass der inhalt in den pointer geladen wird.

    hierbei bekomme ich eine fehlermeldung. error C2440: '=': 'char *' kann nicht in 'int' konvertiert werden
    woran liegt das denn?

    C++ Code:

    getline(MyFile, String); 
            if (String != Line) // If the line is not empty
            {
                Line = String;
                pointer_mychar = &String[0];
                pointer_mychar = strtok(pointer_mychar, delimiter);
                int i=0;
                int pairfind = 0; 
    
                while(pointer_mychar != NULL) 
                {
                    if (i>=MinColumnSize && i<  MaxColumnSize) // Reading necessary column only.  
                    {  
                        if (pairfind == 0) {  
                            tagType = pointer_mychar; // First column is the tagType
    			pairfind = 1;
                        } else if (pairfind == 1) {  
                            level = pointer_mychar; // Second column is the level
                            pairfind = 2;
                        } else if (pairfind == 2) {  
                            shortName = pointer_mychar; // third column is the short Name
    
    			string levelContent1;
    		        string levelContent2;
    			string levelContent3;
    			string levelContent4;
    			string levelContent5;
    			string levelContent6;
    
    			if (level = 1){
    			    levelContent1 = pointer_mychar;
    			}
    			else if ( levelContent2 = 2){
    			     levelContent = pointer_mychar;
    			}
    			else if ( levelContent3 = 3){
    			     levelContent = pointer_mychar;
    			}
    			else if ( levelContent4 = 4){
    			     levelContent = pointer_mychar;
    			}
    			else if ( levelContent5 = 5{
    			     levelContent = pointer_mychar;
    			}
    			else if ( levelContent6 = 6{
    			     levelContent = pointer_mychar;
    			}
    
                            pairfind = 3;
                        } 
                        else if(pairfind == 3) {
                            rtName = pointer_mychar; // fourth column is the rtName which will be analyzed here
                            pairfind = 4;
                        } else {
                            datatypeStringFromTable = pointer_mychar;
    
                            dataTypeNumRep = i;
                            pairfind = 0; // Resetting pairfind for a new round
                        }
                    }
                    pointer_mychar = strtok(NULL, delimiter);
    
                    i++;
                }
            } else {
                break;
            }
    


  • Hallo YumiFerrari,

    Ich unterstelle mal, dass der genannte Compile-Error in den Zeilen 15 und/oder 18 und/oder 21 passiert.
    Das liegt daran, dass von den Variablen tagType , level oder shortName mindestens einer vom Typ int ist - und Du kannst keinen char* einem int zuweisen.

    Es wäre hilfreich, wenn Deine geposteten Codeschnipsel in sich vollständig sind; dazu gehören mindestens alle Typangaben der verwendeten Variablen.

    Gruß
    Werner



  • ..



  • .. irgendwie funktioniert das Editieren nicht mehr 😕



  • string tagType; // The tag type from the CSV file
            string level; // level from the csv file
            string shortName; // The short name given in the CSV file
            string rtName; // The rtName given in the CSV file
            string datatypeStringFromTable; // The data Type given in the CSV
            int dataTypeNumRep; // An integer representation of the datatypeStringFromTable
            ODK_DATA_STRUCT dataStruct; // The data struct to be filled
            vector<string> v; // Initing the vector where we are going to put the two parts of the rtName
    

    ich glaube das sollte es sein...

    bei mir zeigt es immer die zeilen ab 31 an... das mit dem levelContent... das habe ich auch neu hinzugefügt, weil ich den inhalt eben haben wollte.


Log in to reply