0

I need a function that would give me the escaped special character from the letter character. It would apply only when it makes sense: 't', 'n', 'r', 'b', 'f', 'v'.

Right now, here is my implementation:

typedef struct SpecialCharacter
{
    SpecialCharacter( char letter, char special )
    {
        m_letter = letter;
        m_special = special;
    }

    char m_letter;
    char m_special;
} SpecialCharacter;

typedef std::vector<SpecialCharacter> SpecialCharacters;

static const SpecialCharacters& GetSpecialCharacters()
{
    static SpecialCharacters characters;
    if ( characters.empty() )
    {
        characters.push_back( SpecialCharacter( 'b', '\b' ) );
        characters.push_back( SpecialCharacter( 'f', '\f' ) );
        characters.push_back( SpecialCharacter( 'n', '\n' ) );
        characters.push_back( SpecialCharacter( 'r', '\r' ) );
        characters.push_back( SpecialCharacter( 't', '\t' ) );
        characters.push_back( SpecialCharacter( 'v', '\v' ) );
    }
    return characters;
}

static bool getEscaped( char letter, char& escaped )
{
    for ( SpecialCharacters::const_iterator iter = GetSpecialCharacters().begin();
          iter != GetSpecialCharacters().end();
          ++iter )
    {
        if ( letter == iter->m_letter)
        {
            escaped = iter->m_special;
            return true;
        }
    }
    return false;
}

I don't like the way I'm adding elements to the characters vector:

characters.push_back( SpecialCharacter( 'b', '\b' ) );

Would there be a way to do:

characters.push_back( SpecialCharacter( 'b' ) );

and then have something like:

SpecialCharacter( char letter )
{
    m_letter = letter;
    m_special = '\' + letter; // does not work, of course!
}

I'd like a way to merge '\' and 'n' into '\n', or get '\n' from 'n' by any different way...

Edit: case statement is what I had originally before I moved the code to a vector of struct (because I need a function to do the way around). So that would not be a good solution to my problem. I'd like to transform 'n' to '\n' without any kind of "lookup table"

jpo38
  • 19,174
  • 7
  • 62
  • 118
  • just curious, what's the intent? – sanjayk79 Feb 24 '15 at 11:19
  • Have to manually handle, protect and convert those characters for exporting scripts to be used by an external parser. One case is where user types a text "bbb\n" in a GUI and I need to replace "bbb\n" by "bbb\\n" to have '\n' be visible in an exported file rather than a real carriage return. But there are other conditions, where I need to map 'n' to '\n' or the way around in my code. – jpo38 Feb 24 '15 at 11:23
  • you can create a simple escaped_char[128] (for printable chars) e.g. escaped_char['f'] = '\f' and escaped_char['a'] = 'a'. Even after looking up the escaped char, i'm not sure how its going to help. Have a look at http://stackoverflow.com/questions/2417588/escaping-a-c-string – sanjayk79 Feb 24 '15 at 11:43

4 Answers4

3

n and \n are completely different characters. They are not related to each other in any way. \n is just a mnemonic. There is no formula.

Adam Sosnowski
  • 876
  • 5
  • 7
  • 1
    Macros do not magically invent relationships between two things. You can't just throw out the word "macro" as a response to some statement as if it means something out of context :P – Lightness Races in Orbit Feb 24 '15 at 11:20
  • I was thinking of a mcro syntiax that would magically merge ',\,n and ' into `'\n'`...as they are capable of merging strings together... – jpo38 Feb 24 '15 at 11:25
  • Even if that were possible, I would not recommend introducing a macro just so you can do `MAP_CHARACTER(n)` versus `mapCharacter('n', '\n')`. It is not more readable, it's less flexible, and hides the logic of a rather unnatural relationship. – tenfour Feb 24 '15 at 11:28
  • 1
    Characters are not strings. And when it comes to macros, a character literal is a preprocessor token. It can't be split, nor concatenated. – Adam Sosnowski Feb 24 '15 at 11:31
0

Your implementation looks fine, modulo optimisation using switch, constexpr and/or macros.

There is no relationship between 'x' and '\x', no fixed ASCII offset between them for all x.

So, you cannot do better than a lookup table.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
0

There is no special way to convert 'n' into '\n' because they are completely unrelated values; there is no pattern in the mapping you're performing. You are doing a simple integer mapping (in the case of 'n' to '\n', mapping 0x6E to 0x0A). I would recommend a simpler implementation than you're doing, especially for so few mappings:

static bool getEscaped( char letter, char& escaped )
{
    switch(letter)
    {
    case 'b':
        escaped = '\b';
        return true;
    case 'f':
        escaped = '\f';
        return true;
    case 'n':
        escaped = '\n';
        return true;
    case 'r':
        escaped = '\r';
        return true;
    case 't':
        escaped = '\t';
        return true;
    case 'v':
        escaped = '\v';
        return true;
    }
    escaped = letter;
    return false;
}

If you are absolutely dead-set on never having to actually specify the mapping explicitly, insisting that you leverage the relationship in C++ character escapes for your purposes, then you can write your own preprocessor to generate the switch statement I put above. I do not recommend this for handling only 6 cases.

In essence you are doing a little mapping from 6 integers to 6 other unrelated integers. Just use a switch.

tenfour
  • 33,679
  • 12
  • 73
  • 135
  • Yes I answered your question and provided a simpler alternative. – tenfour Feb 24 '15 at 11:29
  • @jpo38 You seem rather fixated on getting a particular answer. Why did you ask such an open question if you're only willing to accept the answer you want to hear? – tenfour Feb 24 '15 at 11:30
  • OK maybe my answer was badly asked. I don't want a solution using any kind of lookup table, because 'n' and '\n' syntaxes are so close that I would expect a piece of code able to create one from another. I'll update the question. – jpo38 Feb 24 '15 at 11:33
  • Taking that into account, I added another paragraph to my answer. – tenfour Feb 24 '15 at 11:33
-2

Perhaps this is what you are looking for?

https://stackoverflow.com/a/5612287/4405589

I can't think of a better way to solve this problem rather than use a switch-case statement or some kind of key-value pair at the moment.

Edit: added an example:

#include <iostream>

char GetSpecialCharacter(char c){
    switch(c){
        case 'n':
            return '\n';
        case 'r':
            return '\r';
        case 't':
            return '\t';
        // More espace character checks here...
        default:
            return '\0';
    }
}

int main(void){
    std::cout << "This is a " << GetSpecialCharacter('n') << "test.";
    return 0;
}
Community
  • 1
  • 1
Henri Korpela
  • 111
  • 11