Я работаю над проектом CS, и меня смущает какой-то аспект кода.

Я попытался использовать «0», чтобы удалить символьное значение, хранящееся в fDig, и sDig для хранения целых чисел вместо символьных байтов, но каким-то образом, когда я сделал расстояние отрицательным, cerr прочитал какое-то случайное число, не предназначенное снова.

    else{
                int fDig = commandString[i+1+extra]-'0';
                int sDig = commandString[i+2+extra]-'0';
                int distance = fDig;


                if (isdigit(commandString[i+2])){distance = (fDig*10 + sDig);}
                if (extra == 1){distance = -distance;}

                cerr << distance << endl;
}

Например, если commandString в i+1+extra равно 3, а commandString в i+2+extra ничего нет, а это extra равно 1. Я получаю значение 18 в качестве вывода для расстояния.

-1
LHC2012 26 Окт 2019 в 21:17

1 ответ

Вычитание '0' волшебным образом не превращает символ в строке в целое число.

Вычитая '0', вы вычитаете из значения ASCII, чтобы получить смещение от ASCII 0:

'0' - '0' = 0x30 - 0x30 = 0
'1' - '0' = 0x31 - 0x30 = 1
'2' - '0' = 0x32 - 0x30 = 2
'3' - '0' = 0x33 - 0x30 = 3
...
'9' - '1' = 0x39 - 0x30 = 9

Однако, если у вас есть мусорные данные (которые вы всегда должны предполагать при вводе пользователем), вы получите мусорные результаты:

'-'  - '0' = 0x2d - 0x30 = -3
' '  - '0' = 0x20 - 0x30 = -16
'\0' - '0' = 0x00 - 0x30 = -48 (string terminator)
'\n' - '0' = 0x0a - 0x30 = -38

В стандартной библиотеке C/C++ есть много инструментов, написанных для этого.

Не беспокойтесь об разборе ASCII, если вы АБСОЛЮТНО не знаете, что делаете.

Для одного номера я предлагаю strtoll для C строки и stoll для std::strings, или для нескольких номеров в одной строке sscanf и istringstream.

Они обрабатывают шестнадцатеричные, отрицательные, восьмеричные, дополнительные пробелы и обработку ошибок, если вы используете их правильно, и намного, намного, НАМНОГО проще, чем ручной анализ.

0
EasyasPi 31 Окт 2019 в 17:47