Я пытаюсь кодировать строку в base36.
static char *decode(unsigned long long value)
{
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof(buffer);
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while (value /= 36);
return _strdup(&buffer[offset]);
}
int main()
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64(original, NULL, 36);
char *decoded = decode(encoded);
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
Проблема здесь в том, что эти функции работают нормально: если строка, которую я пытаюсь кодировать, имеет ведущую 0, то декодированная строка - один символ (или более) меньше оригинала.
Как с этим бороться?
zeroCount
новую переменную в ваш основной, называемый zeroCount
в main
decode
, называемый zeroCount
zeroCount
нулей в original
на zeroCount
в main
buffer[--offset]
пока вы не будете потреблять весь zeroCount
перед return
Как это:
static char *decode( unsigned long long value, int zeroCount )
{ // introduced zeroCount argument there ^
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof( buffer );
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while ( value /= 36 );
while ( zeroCount-- ) buffer[--offset] = '0'; // <-- added this
return strdup( &buffer[offset] );
}
int main( )
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64( original, NULL, 36 );
int zeroCount = 0; // added
for ( int i = 0; i < sizeof original && original[i] == '0'; i++ ) // these
zeroCount++; // three
char *decoded = decode( encoded, zeroCount ); // <-- called along with zeroCount
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
Поскольку нет никакого очевидного правила для желаемого поведения 0
вам нужно, я должен был предположить, что вы хотели бы иметь много ведущих нулей, которые были у original
.
0
с будут печататься как 0
с, но, конечно же, нет, они скорее должны быть превращены в '0'
. Работает довольно хорошо прямо сейчас.
Если вы декодируете строку "01234"
в качестве строки base-16 (например), вы получаете целочисленное значение 4660
(0x1234
) - точно такое же целочисленное значение, которое вы получаете, декодируя строку "1234"
или "00001234"
как base-16. Преобразуя строку в целое число, вы выбросили любую информацию о ведущих нулях. Вы также отбросили любую информацию о прописных и строчных букв, считая, что A
и a
представляют одно и то же значение.
Преобразование этого целочисленного значения обратно в строку не приведет к восстановлению ведущего 0, если вы не добавите его явно. И если вы хотите добавить, что ведущие 0 (или несколько 0s) тогда и только тогда, когда они присутствовали в исходной строке, вам нужно будет как-то сохранить эту информацию.
Вы вызываете функцию tat, которая принимает строку, содержащую представление числового значения, и преобразует ее в unsigned long long
. Два строковых представления "00007" и "7" оба преобразуются в числовые 7, а ведущие нули теряются.
Если вы хотите, например, 00000036, чтобы скрыть до 00000010 в базе 36, вам просто нужно подсчитать нули, которые вы хотите, а затем решить, сколько из них нужно заменить (зависит ли это от относительной длины базовых 10 и базовых 36 строк?)
Но, похоже, в преобразованиях есть плохая практика. лучше, на мой взгляд, добавить ведущие нули при выводе значения. Как многие прокомментировали, они не имеют никакого значения и не должны быть частью логики преобразования.
Я предлагаю вам создать обертку вокруг вашего метода и передать ей параметр длины.
Например.
char * wrap_base36enc(int out_len, unsigned long long value){
char pre_str[MAX_VAL]="", *ans = base36enc(value);
len -= strlen(ans);
while(len--){
strcat(pre_str,"0");
}
strcat(pre_str,ans);
return pre_str;
}