Thread: map<char*, word> not working

  1. #1
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709

    map<char*, word> not working

    In my assembler I've mapped all mnemonics to their word representation (same for registers):

    Code:
    #define ADDENTRY(m, c, w) m.insert(entry(c, w))
    
    void CAssembler::Initialise()
    {
        typedef pair<char*, word> entry;
    
        ADDENTRY(opcodes, "nop", 0x0000);
        ADDENTRY(opcodes, "end", 0xFFFF);
        ADDENTRY(opcodes, "push", 0x0001);
        ADDENTRY(opcodes, "pop", 0x0002);
        ADDENTRY(opcodes, "mov", 0x0003);
        ADDENTRY(opcodes, "inc", 0x0004);
        ADDENTRY(opcodes, "dec", 0x0005);
        ADDENTRY(opcodes, "jmp", 0x0006);
        ADDENTRY(opcodes, "cmp", 0x0007);
        ADDENTRY(opcodes, "je", 0x0008);
        ADDENTRY(opcodes, "jne", 0x0009);
        ADDENTRY(opcodes, "jz", 0x000A);
        ADDENTRY(opcodes, "jnz", 0x000B);
        ADDENTRY(opcodes, "jgt", 0x000C);
        ADDENTRY(opcodes, "jlt", 0x000D);
        ADDENTRY(opcodes, "ld", 0x000E);
    
        ADDENTRY(registers, "pc", 0xF000);
        ADDENTRY(registers, "sp", 0xF001);
        ADDENTRY(registers, "r0", 0xF002);
        ADDENTRY(registers, "r1", 0xF003);
    }
    I've got this function which is supposed to return the word value from the map based on the token - it chooses which map to get it from:

    Code:
    word CAssembler::TranslateToken(char* token)
    {
        if (strcmp(token, "nop") == 0) 
            return opcodes[token];
        else if (strcmp(token, "end") == 0) 
            return opcodes[token];
        else if (strcmp(token, "push") == 0) 
            return opcodes[token];
        else if (strcmp(token, "pop") == 0) 
            return opcodes[token];
        else if (strcmp(token, "mov") == 0) 
            return opcodes[token];
        else if (strcmp(token, "inc") == 0) 
            return opcodes[token];
        else if (strcmp(token, "dec") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jmp") == 0) 
            return opcodes[token];
        else if (strcmp(token, "cmp") == 0) 
            return opcodes[token];
        else if (strcmp(token, "je") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jne") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jz") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jnz") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jgt") == 0) 
            return opcodes[token];
        else if (strcmp(token, "jlt") == 0) 
            return opcodes[token];
        else if (strcmp(token, "ld") == 0) 
            return opcodes[token];
    
        else if (strcmp(token, "pc") == 0) 
            return registers[token];
        else if (strcmp(token, "sp") == 0) 
            return registers[token];
        else if (strcmp(token, "r0") == 0) 
            return registers[token];
        else if (strcmp(token, "r1") == 0) 
            return registers[token];
        else
            throw ASInvalidToken();
    }
    But it doesn't return the word. Here's the code which uses it:

    Code:
    void CAssembler::Assemble(const char* fileName, const char* outFileName)
    {
        FILE* fin = 0, *fout = 0;
        char* token = 0;
        const char* delim = " ,\n";
        char* line = new char[260];
        word translated = 0;
    
        fin = fopen(fileName, "r");
        if (!fin) throw ASFileError();
    
        while (fgets(line, 260, fin) != 0) {
            token = strtok(line, delim);
    
            while (token != 0) {
                cout << token << "\t";
    
                if (IsDigit(token))
                    translated = atoi(token);
                else
                    translated = TranslateToken(token);
    
                cout << translated << endl;
                token = strtok(0, delim);
            }
        }
    
        fclose(fin);
        delete[] line;
    }
    Input:

    Code:
    ld r0, 10
    ld r1, 20
    push r1
    pop r0
    end
    Output:

    Code:
    ld      0
    r0      0
    10      10
    ld      0
    r1      0
    20      20
    push    0
    r1      0
    pop     0
    r0      0
    end     0
    Press any key to continue
    So the literals get properly mapped to their, well, nothing because they're literal, but the opcodes & operands don't. I don't know, maybe it's not a map problem, just a logic problem.

    Be gentle, it's late. (to me, I get up at the crack of dawn)

    EDIT1:

    Just ran this on each token as it's found:

    Code:
    for (unsigned i = 0; i < strlen(token); i++)
        cout << (int) *(token + i) << " ";
    Just to make sure nothing strange is causing strcmp() to fail.

    EDIT2: I just realised how pointless EDIT1 was since if strcmp() returns 0 I throw en exception. I should design my projects on paper.
    Last edited by cboard_member; 03-12-2006 at 03:21 PM.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  2. #2
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Try typedef pair<std::string, word>

  3. #3
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Trying.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  4. #4
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Thanky you
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

  5. #5
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    I'm not entirely sure I understand what's going on here, but I'm wondering if you can't simplify those functions (opcodes and registers are std::map<char*,word> right?):
    Code:
    void CAssembler::Initialise()
    {
        //typedef pair<char*, word> entry;
    
        //ADDENTRY(opcodes, "nop", 0x0000);
        opcodes["nop"] = 0x0000;
    }
    
    word CAssembler::TranslateToken(char* token)
    {
          if (opcodes(token).count()!=0)
            return opcodes[token];
          if (registers[token].count()!=0)
            return registers[token];
         throw ASInvalidToken();
    }
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The reason that string works but not char* is that string has built in copying and comparing, whereas the builtin comparing of a char* is pointer comparison.

    Also, I think JaWiB's TranslateToken version should use find so that it desn't automatically add an entry to the wrong map. For example, if token is "pc", then opcodes[token] will add pc to the map with a value of 0. If you use find instead, it won't be added, and "nop" will work correctly (since its value actually is 0).

  7. #7
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Also, I think JaWiB's TranslateToken version should use find so that it desn't automatically add an entry to the wrong map. For example, if token is "pc", then opcodes[token] will add pc to the map with a value of 0. If you use find instead, it won't be added, and "nop" will work correctly (since its value actually is 0).
    I don't follow your reasoning here. For example, if the token is "pc":
    Code:
     if (opcodes(token).count()!=0) //count should return 0
            return opcodes[token]; //won't be executed
    What am I missing
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    First, I assume you meant opcodes[token].count() with square brackets. That would only work if word has a count() member function, which it looks like it doesn't. Even if it did, using [] to access an element in a map adds a new element with a default value. Using find does not add an element. You're right that "pc" will work, but it wil have the side effect of adding an element to the map.

    If count() isn't a member of word, then the syntax would be if (opcodes[token] != 0). In that case, what if token is "nop"?

  9. #9
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Oh heh, talk about a brain fart, my code should have read:
    Code:
    if (opcodes.count(token)!=0)
    Edit: wow and I did it differently on the registers one. I'm not sure where my brain was today
    Last edited by JaWiB; 03-12-2006 at 10:56 PM.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Interesting, I didn't even realize that count was part of the interface, although for a map that holds unique keys does it have advantages over find()?

  11. #11
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    The only advantage I know of is that find() returns end() if no element is found and it's easier to type:
    Code:
    if (somemap.count(elem)!=0)
    //than
    if (somemap.find(elem)!=somemap.end())
    Edit: actually, now that I think of it, find() would probably be more efficient, and in fact my reference book says count() has linear complexity and find() has logarithmic complexity. Which makes sense because find would stop on the first element found, while count has to continue to the end
    Last edited by JaWiB; 03-12-2006 at 11:15 PM.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    For the record, you can have an STL map with character arrays by providing your own less-than predicate, as shown on the STL: Map page.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Although you still must be careful about what you insert. You must make sure that you never modify the value pointed to by the pointer inserted into the map (which is why the example is const char*).

  14. #14
    Supermassive black hole cboard_member's Avatar
    Join Date
    Jul 2005
    Posts
    1,709
    Wow thanks for all the info guys. I had a niggling that some of my functions were a little cumbersome.
    Good class architecture is not like a Swiss Army Knife; it should be more like a well balanced throwing knife.

    - Mike McShaffry

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function not working
    By sloopy in forum C Programming
    Replies: 31
    Last Post: 11-12-2005, 08:08 PM
  2. Program Not working Right
    By raven420smoke in forum C++ Programming
    Replies: 2
    Last Post: 09-16-2005, 03:21 AM
  3. Trying to eject D drive using code, but not working... :(
    By snowfrog in forum C++ Programming
    Replies: 3
    Last Post: 05-07-2005, 07:47 PM
  4. x on upper right corner not working
    By caduardo21 in forum Windows Programming
    Replies: 1
    Last Post: 02-20-2005, 08:35 PM
  5. cygwin -> unix , my code not working properly ;(
    By CyC|OpS in forum C Programming
    Replies: 4
    Last Post: 05-18-2002, 04:08 AM