Розбиття рядків C ++ на кілька рядків (синтаксис коду, не розбір)


77

Не слід плутати з тим, як розділити рядок розумно, наприклад:
Розділити рядок у C ++?

Я трохи заплутаний щодо того, як розділити рядок на кілька рядків у C ++.

Це звучить як просте запитання, але візьмемо такий приклад:

#include <iostream>
#include <string>
main() {
  //Gives error
  std::string my_val ="Hello world, this is an overly long string to have" +
    " on just one line";
  std::cout << "My Val is : " << my_val << std::endl;

  //Gives error
  std::string my_val ="Hello world, this is an overly long string to have" &
    " on just one line";  
  std::cout << "My Val is : " << my_val << std::endl;
}

Я усвідомлюю, що міг би використати std::string append()метод, але мені було цікаво, чи є якийсь коротший / елегантніший (наприклад, більше схожий на пітон, хоча очевидно, що потрійні лапки тощо не підтримуються в c ++), щоб розбити рядки в c ++ на кілька рядків заради читабельності.

Одне з таких місць, де це було б особливо бажано, це коли ви передаєте довгі рядкові літерали функції (наприклад, реченню).


2
Ось цікавий шматок: лексеру С ++ насправді не важливо, скільки лапок ви розміщуєте до і після рядка, лише за двома винятками. Кількість цитат, які ви використовуєте, має бути непарною, і вони повинні збігатися з обох сторін. """"" This is a valid string and will be parsed """"". Однак особливих властивостей, наданих цим рядкам, немає, вони просто поводяться як одинарні лапки.
Томас Ентоні

Цікава подяка, що поділилися цим ... чи є для цього якась корисна мета? Можливо, ви зможете використовувати це як тонкий тег для різних груп рядків у коді для зовнішнього аналізу за сценаріями perl / bash / python. Це приблизно все, що я зараз можу придумати. :)
Джейсон Р. Мік

@ThomasAnthony Це просто трапляється, тому що він буде розглядати цитати навколо кінця як купу порожніх рядків і об'єднувати їх разом - це не особливість, це стандартна поведінка C / C ++
texasflood

Відповіді:


126

Не кладіть нічого між рядків. Частиною етапу лексингу на C ++ є поєднання сусідніх рядкових літералів (навіть над новими рядками та коментарями) в один літерал.

#include <iostream>
#include <string>
main() {
  std::string my_val ="Hello world, this is an overly long string to have" 
    " on just one line";
  std::cout << "My Val is : " << my_val << std::endl;
}

Зверніть увагу, що якщо вам потрібен новий рядок у літералі, вам доведеться додати це самостійно:

#include <iostream>
#include <string>
main() {
  std::string my_val ="This string gets displayed over\n" 
    "two lines when sent to cout.";
  std::cout << "My Val is : " << my_val << std::endl;
}

Якщо ви хочете змішати #defineконстанту d цілого числа в літералі, вам доведеться використовувати деякі макроси:

#include <iostream>
using namespace std;

#define TWO 2
#define XSTRINGIFY(s) #s
#define STRINGIFY(s) XSTRINGIFY(s)

int main(int argc, char* argv[])
{
    std::cout << "abc"   // Outputs "abc2DEF"
        STRINGIFY(TWO)
        "DEF" << endl;
    std::cout << "abc"   // Outputs "abcTWODEF"
        XSTRINGIFY(TWO) 
        "DEF" << endl;
}

Тут є якась дивина через те, як працює оператор процесора stringify, тому вам потрібні два рівні макросів, щоб отримати фактичне значення, TWOяке потрібно зробити з рядкового літералу.


Чи можете ви змішувати інші предмети, як int константу? Якщо ні, як їх додати?
Джейсон Р. Мік,

@ Джейсон: Що ви маєте на увазі під змішуванням в константі int?
Eclipse,

моя_функція (arg_1, arg_2, "привіт світ, цей рядок має" ДВА "рядки!");
Джейсон Р. Мік,

4
Поєднання рядкових літералів є фактичною частиною лексичної фази (не попереднього процесора), оскільки поділ рядків, подібний до цього, визначається як частина мови.
Мартін Йорк,

1
@Jason, з вашого подальшого запитання, схоже, вам потрібно щось на зразок STRINGIFYмакросу вище.
Затемнення

10

Вони обоє буквально? Відокремлення двох рядкових літералів з пробілами те саме, що і конкатенація: "abc" "123"те саме, що "abc123". Це стосується як прямої С, так і С ++.


7

Я не знаю, це розширення в GCC чи це стандарт, але, схоже, ви можете продовжувати літеральний рядок, закінчуючи рядок зворотною рискою рискою (так само, як більшість типів рядків можна розширити в цій садибі в C ++ наприклад, макрос, що охоплює кілька рядків).

#include <iostream>
#include <string>

int main ()
{
    std::string str = "hello world\
    this seems to work";

    std::cout << str;
    return 0;
}

4
Цей буквальний синтаксис містить досить багато пробілів між worldіthis
SingleNegationElimination

@TokenMacGuy: справді так, я цього не помічав. Це досить легко виправити, якщо перемістити другий (і наступні) рядки до кінця вліво. Але це справді зіпсує вигляд вашого відступу.
rmeador

Так, це був мій початковий підхід, але я відмовився від нього через проблеми з відступами / інтервалами @SingleNegationElimination контури. Хороший зауваження, хоча.
Джейсон Р. Мік,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.