Как преобразовать целые числа, представленные в виде строки, в символы ASCII? - PullRequest
1 голос
/ 12 мая 2019

У меня есть строка ввода, которая может выглядеть так: «126022034056098012». Это результат объединения кодов символов ASCII, которые я прочитал из какого-то файла. Коды, например, 126 22 34 56 98 12. Проблема в том, как декодировать эту строку обратно в символы? Примечание: строка не должна содержать разделителей, кроме цифр (\, | и т. Д.). Что мне делать дальше?

Я нашел способ, который использует карту символов ASCII: ключ-> строка с числовым представлением символа ASCII, значение-> символ ASCII. В цикле я накапливаю входящие цифры в строке, пока строка не совпадет с каким-либо ключом на карте. При совпадении я конвертирую полученный код в символ. Я продолжаю, пока не закончатся входные данные. Но этот метод хорошо работает со строками и текстовыми файлами, но не работает с двоичными файлами.

функция, которая создает строку символов из строки кодов ASCII:

string Utils::from_number_to_ascii(string number, int size) {
    Utils ut;
    while(number.size() % 3) {
        number = "0" + number;
    }

    string out;
    for (int i = 0; i < size;){
        string st;
        auto it = ut.triple_dict.end();
        while (it == ut.triple_dict.end() && i < size){
            st += number[i++];
            it = ut.triple_dict.find(st);
        }
        out += it->second;
        st = "";
    }
    return out;
}

заполнение карты:

Utils::Utils() {
    for (int i = 0; i <= 255; i++){
        string s =  to_string(static_cast<int>(i));
        if (s.size() == 1) {
            s = "00" + s;
        } if (s.size() == 2){
            s = "0" + s;
        }
        triple_dict.insert(make_pair(s, static_cast<unsigned char>(i)));
    }
}

Нетрудно видеть, что я заполняю контейнер тремя байтами: если код символа ASCII представляет собой двузначное число, я добавляю его с "0", если код символа является однозначным числом, я добавляю его с помощью " 00 "сделать код трехзначным числом. Я делаю это для однозначного декодирования символа.

1 Ответ

2 голосов
/ 12 мая 2019

Если каждый код ascii представлен ровно 3 цифрами, мы можем сделать это довольно легко с помощью цикла:

std::string toAscii(char const* digits, size_t size) {
    std::string output(size / 3, '\0');
    for(char& c : output) {
        char d0 = *digits++; // Get 3 digits
        char d1 = *digits++;
        char d2 = *digits++; 

        int ascii_value = (d0 - '0') * 100 + (d1 - '0') * 10 + (d2 - '0'); 
        c = (char)ascii_value; 
    }
    return output; 
}

Пример использования

У меня есть c-строка с примеромinput, а также строка с ожидаемым выводом.Эта программа проверяет, что они равны.

int main() {
    auto&& input = "126022034056098012";
    std::string expected_output = {char(126), char(22), char(34), char(56), char(98), char(12)};
    std::cout << (toAscii(input, sizeof(input)) == expected_output); // Prints true
}

Добавляет ли fstream.write () '\ 0' в конец файла?

Нет. Если ваша строка содержит символ 0, онадобавлю, но не иначе.Мы можем проверить это сами с помощью небольшого примера кода.

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    {
        std::ofstream file("test.txt");
        std::string   message = "Hello!";

        file.write(message.data(), message.length());
        // file gets closed automatically 
    }
    {
        std::ifstream file("test.txt");


        while (file)
        {
            std::cout << file.get() << '\n';
        }
        // file gets closed automatically
    }
}

Когда я компилирую и запускаю этот код, он выдает следующее.Каждое значение соответствует значению соответствующего символа в "Hello!", за исключением последнего.-1 указывает, что вы достигли конца файла, но если бы вы использовали метод, подобный file.read, он не отобразился бы.\0 не отображается нигде в файле.

72
101
0
108
111
33
-1
...