Convert string with explicit escape sequence into relative character

前端 未结 5 1531
离开以前
离开以前 2020-12-06 17:13

I need a function to convert \"explicit\" escape sequences into the relative non-printable character. Es:

char str[] = \"\\\\n\";
cout << \"Line1\" <         


        
相关标签:
5条回答
  • 2020-12-06 17:47

    I'm sure that there is, written by someone, but it's so trivial that I doubt it's been specifically published anywhere.

    Just recreate it yourself from the various "find"/"replace"-esque algorithms in the standard library.

    0 讨论(0)
  • 2020-12-06 17:56

    Have you considered using printf? (or one of its relatives)

    0 讨论(0)
  • 2020-12-06 18:02

    You can do that fairly easy, using the boost string algorithm library. For example:

    #include <string>
    #include <iostream>
    #include <boost/algorithm/string.hpp>
    
    void escape(std::string& str)
    {
      boost::replace_all(str, "\\\\", "\\");
      boost::replace_all(str, "\\t",  "\t");
      boost::replace_all(str, "\\n",  "\n");
      // ... add others here ...
    }
    
    int main()
    {
      std::string str = "This\\tis\\n \\\\a test\\n123";
    
      std::cout << str << std::endl << std::endl;
      escape(str);
      std::cout << str << std::endl;
    
      return 0;
    }
    

    This is surely not the most efficient way to do this (because it iterates the string multiple times), but it is compact and easy to understand.

    Update: As ybungalobill has pointed out, this implementation will be wrong, whenever a replacement string produces a character sequence, that a later replacement is searching for or when a replacement removes/modifies a character sequence, that should have been replaced.

    An example for the first case is "\\\\n" -> "\\n" -> "\n". When you put the "\\\\" -> "\\" replacement last (which seems to be the solution at a first glance), you get an example for the latter case "\\\\n" -> "\\\n". Obviously there is no simple solution to this problem, which makes this technique only feasible for very simple escape sequences.

    If you need a generic (and more efficient) solution, you should implement a state machine that iterates the string, as proposed by davka.

    0 讨论(0)
  • 2020-12-06 18:08

    I think that you must write such function yourself since escape characters is a compile-time feature, i.e. when you write "\n" the compiler would replace the \n sequence with the eol character. The resulting string is of length 1 (excluding the terminating zero character).

    In your case a string "\\n" is of length 2 (again excluding terminating zero) and contains \ and n.

    You need to scan your string and when encountering \ check the following char. if it is one of the legal escapes, you should replace both of them with the corresponding character, otherwise skip or leave them both as is.

    ( http://ideone.com/BvcDE ):

    string unescape(const string& s)
    {
      string res;
      string::const_iterator it = s.begin();
      while (it != s.end())
      {
        char c = *it++;
        if (c == '\\' && it != s.end())
        {
          switch (*it++) {
          case '\\': c = '\\'; break;
          case 'n': c = '\n'; break;
          case 't': c = '\t'; break;
          // all other escapes
          default: 
            // invalid escape sequence - skip it. alternatively you can copy it as is, throw an exception...
            continue;
          }
        }
        res += c;
      }
    
      return res;
    }
    
    0 讨论(0)
  • 2020-12-06 18:08

    Here's a cute way to do it on Unixy platforms.

    It calls the operating system's echo command to make the conversion.

    string convert_escapes( string input )
       {
       string buffer(input.size()+1,0);
       string cmd = "/usr/bin/env echo -ne \""+input+"\"";
       FILE * f = popen(cmd.c_str(),"r"); assert(f);
       buffer.resize(fread(&buffer[0],1,buffer.size()-1,f));
       fclose(f);
       return buffer;
       }
    
    0 讨论(0)
提交回复
热议问题