Search code examples
c++stringserial-portcarriage-return

Raw Carriage Return & New Line for Serial Port Write


I am new to C++, and I'm trying to generate a string "command\r\n". However, I need a raw carriage return & new line (see code bellow). I've tried R"(command\r\n)", but I don't think I have the right version to use raw strings. What are some alternative options (using Linux)?

Here is the code: I am trying to write to a serial port using a string command. The controller requires the \r\n.

//serial port write function

int write_only(int fd, string str) {
if (write(fd, str.c_str(), str.length()) == -1)
    {
        printf("write failed \n"); 
    }
}
// this call works 

write_only(fd, "command\r\n");

This call doesn't work but I need it so I can easily generate commands:

string buff = "command\r\n";
write_only(fd, buff);

Solution

  • Raw strings are mostly for situations when you don't want C escape sequences at all. This is especially useful in cases where the \ character is used with meaningful purposes inside the string itself, so you don't have to escape it at the programming language level.

    For example, imagine the case of POSIX or C++11 regular expressions, which have many characters with special meanings, and also use \ as the escape character to revert such characters back to their literal correspondents in the string to be matched. Now imagine that you want to parse a Windows-styled UNC name, in the form \\computer\share\pathname\filename. Compare the two possible ways of splitting those four components.

    // With C-style strings: every "\" in the string to be parsed requires
    // "\\" in regex level, and every "\" in regex level requires "\\" in
    // language level.
    regex unc_parser1("^\\\\\\\\([A-Za-z0-9._-]+)\\\\([^\\\\]+)\\\\((.*)\\\\)?([^\\\\]+)$");
    
    // With raw strings: each desired "\" has to be escaped only in regex level.
    regex unc_parser2(R"(^\\\\([A-Za-z0-9._-]+)\\([^\\]+)\\((.*)\\)?([^\\]+)$)");
    

    (Of course, things can get a lot more complicated than this simple example...)

    On the positive side, one possible solution to your problem is just to use simple compile-time string concatenation. For example, all the strings below will have the same sequence of characters.

    char s1[]="Line 1 has special char (\")\r\nLine 2: has special char (\\)\r\nLine 3 has no special chars\r\n";
    
    #define CRLF "\r\n"
    
    char s2[]=
        "Line 1 has special char (\")" CRLF
        "Line 2: has special char (\\)" CRLF
        "Line 3 has no special chars" CRLF
    ;
    
    char s3[]=
        R"(Line 1 has special char ("))" CRLF
        R"(Line 2: has special char (\))" CRLF
        R"(Line 3 has no special chars)" CRLF
    ;
    

    And to get raw strings to compile on Linux distros where C++11 isn't yet the default (all distros that I know of, BTW), you can just add -std=c++11 to your g++ or clang++ command invocation.