Преобразование специальных символов (например, \ n) в их экранированные версии - PullRequest
0 голосов
/ 07 декабря 2010

Как преобразовать, например, "A\r\nB\tC\nD" в "A\\r\\nB\\tC\\nD" в C (++)?

В идеале использовать только стандартную библиотеку и бонусный бонус как для чистого C, так и для чистого C ++ решений.

Ответы [ 5 ]

3 голосов
/ 07 декабря 2010

Конечно, замените char на wchar_t и std::string на std::wstring, если вы используете строки широких символов.

std::string input(/* ... */);
std::string output;
for(std::string::const_iterator it = input.begin(); it != input.end(); ++it)
{
    char currentValue = *it;
    switch (currentValue)
    {
    case L'\t':
        output.append("\\t");
        break;
    case L'\\':
        output.append("\\\\");
        break;
    //.... etc.
    default:
        output.push_back(currentValue);
    }
}

Вы можете сделать это в C, но это будет сложнее, потому что вы заранее не знаете размер буфера (хотя вы можете угадать наихудший случай в 2 раза больше размера исходной строки). * 1008 Т.е. *

//Disclaimer; it's been a while since I've written pure C, so this may
//have a bug or two.
const char * input = // ...;
size_t inputLen = strlen(input);
char * output = malloc(inputLen * 2);
const char * inputPtr = input;
char * outputPtr = output;
do
{
    char currentValue = *inputPtr;
    switch (currentValue)
    {
    case L'\t':
        *outputPtr++ = '\\';
        *outputPtr = 't';
        break;
    case L'\\':
        *outputPtr++ = '\\';
        *outputPtr = '\\';
        break;
    //.... etc.
    default:
        *outputPtr = currentValue;
    }
} while (++outputPtr, *inputPtr++);

(Не забудьте добавить обработку ошибок в версию C для таких вещей, как сбои malloc;))

2 голосов
/ 07 декабря 2010

Вот кое-что, что я придумал ...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

inline char needs_escaping(char val) {
        switch(val) {
                case '\n': return 'n';
                case '\r': return 'r';
                case '\t': return 't';
        }
        return 0;
}

char *escape_string(char *in) {
        unsigned int needed = 0, j = 0, length = strlen(in), i;
        for(i = 0; i < length; i++) {
                if(needs_escaping(in[i])) needed++;
        }

        char *out = malloc(length + needed + 1);
        for(i = 0; i < length; i++) {
                char escape_val = needs_escaping(in[i]);
                if(escape_val) {
                        out[j++] = '\\';
                        out[j++] = escape_val;
                }
                else {
                        out[j++] = in[i];
                }
        }
        out[length + needed] = '\0';    
        return out;
}

int main() {
        char *in  = "A\r\nB\tC\nD";
        char *out = escape_string(in);
        printf("%s\n", out);
        free(out);
        return 0;
}
1 голос
/ 07 декабря 2010

Я сомневаюсь, что есть какая-либо стандартная библиотечная функция, которая делает это напрямую. Наиболее эффективным способом было бы просто перебирать входной буфер символ за символом, условно копировать в выходной буфер с некоторой специальной логикой конечного автомата для обработки '\' и т. Д.

Я уверен, что есть способы сделать это с различными комбинациями strchr() и др., Но это, вероятно, будет менее эффективным в общем случае.

0 голосов
/ 07 декабря 2010

Вот алгоритм на C #.Возможно, вы можете обращаться с ним как с псевдокодом и конвертировать его в C ++.

открытая статическая строка EscapeChars (string Input) {string Output = "";

foreach (char c in Input)
{
    switch (c)
    {
        case '\n':
            Output += "\\n";
            break;
        case '\r':
            Output += "\\r";
            break;
        case '\t':
            Output += "\\t";
            break;
        default:
            Output += c;
            break;
    }                
}
return Output;

}

0 голосов
/ 07 декабря 2010

Я бы создал таблицу поиска из 32 const char* литералов, по одному на каждый управляющий код (от ASCII 0 до ASCII 31). Затем я перебрал бы исходную строку, копируя неконтролирующие символы (ASCII> = 32) в выходной буфер и подставляя значения из таблицы поиска для ASCII 0--31.

Примечание 1: ASCII 0, очевидно, специально для строк C (не так для C ++.)

Примечание 2: Таблица поиска будет содержать C escape-последовательности для кодов, которые имеют их (\n, \r и т. Д.) И обратную косую черту плюс шестнадцатеричные / восьмеричные / десятичные коды для тех, которые не имеют.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...