Как напечатать строковое представление объекта в D?

Я хотел бы сделать что-то эквивалентное Python repr:

>>> x = "a\nb\nc"

>>> print x
a
b
c
>>> repr(x)
"'a\\nb\\nc'"

>>> print repr(x)
'a\nb\nc'

Как я могу сделать это в D? Есть ли директива формата, похожая на %r Python?

РЕДАКТИРОВАТЬ: я хочу иметь возможность печатать строки в их экранированной форме для целей отладки (я только начал изучать D и пишу глупые функции обработки текста).


d
person Ryszard Szopa    schedule 18.10.2010    source источник


Ответы (4)


В D строки не являются объектами, и когда вы используете escape-символы, вы фактически сохраняете символ, а не сам escape (что, как я ожидаю, делает и Python). Поэтому, если вы хотите преобразовать строку в ее экранированную форму, вам нужно будет изменить вывод самостоятельно (я не знаю какой-либо библиотечной функции для этого).

В противном случае объекты могут переопределить функцию toString(), которая должна создавать строковое представление объекта.

Обновление: вот пример repr в D. Но обратите внимание, поскольку исходный текст нигде не хранится в исполняемом файле, он также будет преобразовывать литеральные представления. Не должно быть проблем с Unicode, так как обычная целостность строки не нарушена.

import std.stdio;
import std.exception;

void main() {
    writeln(repr("This\nis\n\t*My\v Test"));
}

string repr(string s) {
    char[] p;
    for (size_t i; i < s.length; i++)
    {
        switch(s[i]) {
            case '\'':
            case '\"':
            case '\?':
            case '\\':
                p ~= "\\";
                p ~= s[i];
                break;
            case '\a':
                p ~= "\\a";
                break;
            case '\b':
                p ~= "\\b";
                break;
            case '\f':
                p ~= "\\f";
                break;
            case '\n':
                p ~= "\\n";
                break;
            case '\r':
                p ~= "\\r";
                break;
            case '\t':
                p ~= "\\t";
                break;
            case '\v':
                p ~= "\\v";
                break;
            default:
                p ~= s[i];
                break;
        }
    }

    return assumeUnique(p);
}
person he_the_great    schedule 18.10.2010

Строки обрабатываются, а управляющие последовательности заменяются во время компиляции. Во время выполнения информация теряется, и вам нужно будет отменить экранирование самостоятельно (возможно, уже есть какая-то стандартная функция экранирования), но она не встроена.

Если вы контролируете источник, вы можете использовать необработанные строки. Просто поставьте r перед строкой.

"a\tb" => "a    b"
r"a\tb" => "a\tb"
person Mafi    schedule 18.10.2010

В D есть два способа объявить строки WYSIWYG:

r"thestring"
`thestring`

Итак, следующая программа

import std.stdio;

void main()
{
    auto a = r"hello\nworld";
    auto b = `hello\nworld`;

    writeln(a);
    writeln(b);
}

отпечатки

hello\nworld
hello\nworld

Однако, если у вас есть произвольная строка, а не строковый литерал, и вы хотите иметь возможность печатать ее с символами новой строки и прочим, которые печатаются как их управляющие последовательности, вам придется выполнить некоторую обработку строк — вероятно, с использованием std.string.replace() чтобы заменить каждый символ его escape-последовательностью с дополнительными обратными косыми чертами. Например, чтобы избежать новых строк, вы должны сделать это:

str.replace("\n", "\\n");

Но вам придется делать это индивидуально для '\ t', '\ r', '\' и т. д. Я не знаю, как сделать это автоматически. Строки WYSIWYG просто позволяют избежать использования всех дополнительных обратных косых черт при построении строки.

person Jonathan M Davis    schedule 18.10.2010

Стандартная библиотека языка D не содержит такой функции, но написать ее несложно. Просто просмотрите строку и замените каждое вхождение "\n" на "\\n" и так далее.

person Peter Alexander    schedule 18.10.2010