С++ Возврат каретки и перевод строки в строке

Я работаю со связью для некоторого оборудования, подключенного к TCP/IP, на С++. Оборудование требует, чтобы отправляемые команды заканчивались на \r\n.

Я использую файл конфигурации, из которого я читаю команды, используемые в общении.

У меня проблема в том, что команды \r\n интерпретируются как 4 символа, а не как возврат каретки и перевод строки.

Я пытался использовать string.data(), но получаю тот же результат, что и string.c_str().

Есть ли какая-нибудь хорошая функция, чтобы исправить это с самого начала, или мне нужно решить это с помощью обычной функции замены? Или какой-то другой способ, о котором я не подумал?

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

Спасибо за любую помощь

Изменить: файл конфигурации содержит строки, подобные этой.

MONITOR_REQUEST = "TVT?\r\n"


person user1728363    schedule 08.07.2013    source источник


Ответы (3)


Если данные в файле конфигурации требуют перевода, вы должны его перевести. Если не считать регулярных выражений (которые для этого явно избыточны), я не знаю ни одной стандартной функции, которая могла бы это сделать. Мы используем что-то вроде:

std::string
globalReplace(
    std::string::const_iterator begin,
    std::string::const_iterator end,
    std::string const& before,
    std::string const& after )
{
    std::string retval;
    std::back_insert_iterator<std::string> dest( retval );
    std::string::const_iterator current = begin;
    std::string::const_iterator next
            = std::search( current, end, before.begin(), before.end() );
    while ( next != end ) {
        std::copy( current, next, dest );
        std::copy( after.begin(), after.end(), dest );
        current = next + before.size();
        next = std::search( current, end, before.begin(), before.end() );
    }
    std::copy( current, next, dest );
    return retval;
}

для этого. Например, вы можете вызвать его с помощью "\\r\\n", "\r\n" для последнего аргумента.

person James Kanze    schedule 08.07.2013
comment
Это тоже может быть вариант решения. Каковы первые два аргумента? - person user1728363; 08.07.2013
comment
@user1728363 user1728363 Начальный и конечный итераторы строки, которую необходимо преобразовать. - person James Kanze; 08.07.2013

Похоже, ваш файл конфигурации на самом деле содержит 4 различных символа '\', 'r', '\' и 'n'... вы должны либо изменить файл (например, используя фактические окончания строк в файле для кодирования окончаний строк в строках, и даже тогда некоторые системы не будет использовать \r\n в качестве разделителей строк текстового файла) или выполнить замену/перевод, как вы предлагаете. Перевод является более переносимым подходом. Это также может быть довольно быстро ... просто сохраните два указателя/итератора/индекса в строке - один для позиции чтения и один для записи, и скопируйте их, уплотняя escape-нотацию.

person Tony Delroy    schedule 08.07.2013
comment
Да это верно. Как вы указываете, есть 4 отличительных символа. Каждая строка также заканчивается настоящим \r\n, но это не часть команды, и это то, что я прерываю при чтении файла конфигурации. - person user1728363; 08.07.2013
comment
Еще одно очень хорошее решение, легко расширяемое для обработки дополнительных экранированных символов (например, \a), если они встречаются. Только не забудьте проверить конец строки, увидев '\\'. - person James Kanze; 08.07.2013

Вам не нужно было кодировать что-либо в коде. Вы можете очень хорошо прочитать символы для добавления к исходящей строке из того же файла конфигурации.

Предполагая, что у вас есть пара значений имени в вашем файле conf:

APPEND_EOL="\n\r" str_to_send1="это тест%%ПРИЛОЖЕНИЕEND_EOL%%"

при разборе строки перед отправкой вы можете создать фактическую строку. Если вы не можете сохранить APPEND_EOL в той же строке, вы можете взять его из ENV со значением по умолчанию, если оно не определено, или, возможно, в другом вашем файле конфигурации.

person KK.    schedule 08.07.2013
comment
Звучит как вариант. - person user1728363; 08.07.2013