user9420815
user9420815

Reputation:

How to stop backslashes from cancelling in conversion from QString to char array?

I am writing a QT widgets application that includes serial communication with an Arduino. I found a good header and cpp file on GitHub that makes communicating with an Arduino MUCH easier than it would be with QSerialPort.

However one difficulty that this presents is that the port name must be given as a char array in the format "\\.\COM1" for example. So I'm trying to add those backslashes before the COM port name, with this code:

QString currentPort = "\\\\.\\" + QString(ui->serialPortDropdown->itemText(index));
portName = currentPort.toLocal8Bit().data();

After initialising the array with this at the top of my cpp file:

char *portName;

After adding a few qDebug()s here and there, the QString is being set to how it should be, "\\\\.\\COM1" for example. But the char array is returning as "\\.\COM1". So the backslashes are cancelling other backslashes.

How do I overcome this?

Thanks in advance for any help :)

Upvotes: 0

Views: 819

Answers (3)

Robert Andrzejuk
Robert Andrzejuk

Reputation: 5222

This is normal behavior in C++ source files. And there is even more of them:

Escape sequences are used to represent certain special characters within string literals and character literals.

The following escape sequences are available (extra escape sequences may be provided with implementation-defined semantics):

 Escape      | Description                 |Representation
sequence     |                             |
-------------+-----------------------------+-------------------------------------------------------
  \'         | single quote                |byte 0x27 in ASCII encoding
  \"         | double quote                |byte 0x22 in ASCII encoding
  \?         | question mark               |byte 0x3f in ASCII encoding
  \\         | backslash                   |byte 0x5c in ASCII encoding
  \a         | audible bell                |byte 0x07 in ASCII encoding
  \b         | backspace                   |byte 0x08 in ASCII encoding
  \f         | form feed - new page        |byte 0x0c in ASCII encoding
  \n         | line feed - new line        |byte 0x0a in ASCII encoding
  \r         | carriage return             |byte 0x0d in ASCII encoding
  \t         | horizontal tab              |byte 0x09 in ASCII encoding
  \v         | vertical tab                |byte 0x0b in ASCII encoding
  \nnn       | arbitrary octal value       |byte nnn
  \xnn       | arbitrary hexadecimal value |byte nn
  \unnnn     | universal character name (arbitrary Unicode value); may result in several characters
             |                             |code point U+nnnn
  \Unnnnnnnn | universal character name (arbitrary Unicode value); may result in several characters
             |                             |code point U+nnnnnnnn

Source: Escape sequences

If this is a problem, then C++11 introduced a new type of string literal : raw string literal

Raw string literal. Used to avoid escaping of any character. Anything between the delimiters becomes part of the string.

Syntax :

prefix R " delimiter ( raw_characters ) delimiter "

  • prefix - (optional) One of L, u8, u, U
  • delimiter - A character sequence made of any source character but parentheses, backslash and spaces (can be empty, and at most 16 characters long)
  • raw_characters - Any character sequence, except that it must not contain the closing sequence ) delimiter "

Source: string literal


To solve the problem there are 2 solutions

  1. In every place where a backslash is needed insert 2 backlslashes : "\\\\\\\\.\\\\"

  2. Use a raw string : R"(\\\\.\\)"

Upvotes: 1

Sergio Monteleone
Sergio Monteleone

Reputation: 2886

The QString is being escaped. That is, special characters (including ) are specified using their escape sequence (here the Wikipedia article about escaping).

Since the escape sequence for the backslash character is \\, you just have to double your backslashes:

QString currentPort = "\\\\\\\\.\\\\" + QString(ui->serialPortDropdown->itemText(index));

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

The issue is that in an "ordinary" string literal as yours a backslash introduces "special" characters like, for example, a new line \n. To get one backslash, you have to enter two consecutive backslashes then, i.e. \\ to get \.

To overcome this, either enter each backslash twice, or use the raw format for specifying string literals:

int main() {

    const char* raw = R"foo(\\\\.\\)foo";
    cout << "raw: " << raw << endl;

    const char* notRaw = "\\\\.\\";
    cout << "not raw: " << notRaw << endl;

}

Output:

raw: \\\\.\\
not raw: \\.\

Note that the "foo("-part is custom; it can be anything of your choice which will not be contained in the inner part of the string literal.

Upvotes: 0

Related Questions