функция — унарные операции в переполнении стека

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

int f( char *p )
{
int n = 0 ;
while ( *p != 0 )
n = 10*n + *p++ - '0' ;
return n ;
}

Это то, что я думаю, что программа делает.
p — указатель, а цикл while — DE-повторное сопоставление значений указателя, пока он не станет равным 0. Однако я не понимаю строку присваивания n, что делает ‘0’? Я предполагаю, что значение p изначально отрицательно, это единственный способ, которым оно достигнет 0 после приращения.

-1

Решение

Вы путаете число ноль (нет, ничего) с символом 0 (круг, возможно, с косой чертой). Обратите внимание, что ноль находится в отметках, поэтому это символ «0», а не ноль.

«0» — «0» = 0
«1» — «0» = 1
‘2’ — ‘0’ = 2

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

Итак, скажем, у вас есть эта последовательность цифр: «4», «2», «1». Как вы получаете число четыреста двадцать один из этого? Вы превращаете «4» в четыре. Затем вы умножаете на десять. Теперь у вас есть сорок. Преобразуйте «2» в два и добавьте. Теперь у вас есть сорок два. Умножьте на десять. Преобразуйте «1» в один и добавьте, теперь у вас есть четыреста двадцать один.

Вот как вы преобразуете последовательность цифр в число.

3

Другие решения

n Локальная переменная накапливает значение десятичного числа, которое передается этой функции в строке. Это реализация atoi, без проверки действительности.

Вот работа тела цикла:

n = 10*n + *p++ - ‘0';

Назначить на n результат умножения предыдущего значения n на десять плюс текущий код символа у указателя p меньше кода ноль; приращение p после разыменования.

Поскольку цифровые символы кодируются последовательно, *p-'0' выражение представляет собой десятичное значение цифры.

Допустим, вы разбираете строку "987", Как вы проходите через цикл, n начинается с нуля; тогда ему присваиваются следующие значения:

n = 10*0 + 9;  // That's 9
n = 10*9 + 8;  // That's 98
n = 10*98 + 7; // That's 987
2

Это плохо написано, если не сказать больше.

0) Используйте форматирование !:

int f(char* p)
{
int n = 0;

while (*p != 0)
n = 10*n + *p++ - ‘0?;

return n;
}

1) ? там синтаксически неверно. Это должно быть ' как отметил Крис (и ваши существующие тоже неправильно, но это, вероятно, потому что вы скопировали его с веб-сайта, а не из исходного файла), давая:

int f(char* p)
{
int n = 0;

while (*p != 0)
n = 10 * n + *p++ - '0';

return n;
}

2) Тип параметра не так ограничен, как должно быть. Так как *p никогда не изменяется (в соответствии с нашими целями), мы должны обеспечить это, чтобы убедиться, что мы не делаем ошибок:

int f(const char* p)
{
int n = 0;

while (*p != 0)
n = 10 * n + *p++ - '0';

return n;
}

3) У оригинального программиста была явно аллергия на читаемый код. Давайте разделим наши операции:

int f(const char* p)
{
int n = 0;

for (; *p != 0; ++p)
{
const int digit = *p - '0';
n = 10 * n + digit;
}

return n;
}

4) Теперь, когда операции немного более заметны, мы можем увидеть некоторые независимый функциональность, встроенная в эту функцию; это должно быть выделено (это называется реагированием) в отдельную функцию.

А именно, мы видим операцию преобразование символа в цифру:

int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.

return c - '0';
}

int f(const char* p)
{
int n = 0;

for (; *p != 0; ++p)
n = 10 * n + todigit(*p);

return n;
}

5) Итак, теперь ясно, что функция читает строку символ за символом и генерирует число цифра за цифрой. Этот функционал уже существует под именем atoiи эта функция небезопасна:

int todigit(const char c)
{
// this works because the literals '0', '1', '2', etc. are
// all guaranteed to be in order. Ergo '0' - '0' will be 0,
// '1' - '0' will be 1, '2' - '0' will be 2, and so on.

return c - '0';
}

int atoi_unsafe(const char* p)
{
int n = 0;

for (; *p != 0; ++p)
n = 10 * n + todigit(*p);

return n;
}

Это оставлено в качестве упражнения для чтения для проверки на переполнение, недопустимые символы (те, которые не являются цифрами) и так далее. Но это должно прояснить, что происходит, и то, как такая функция должна была быть написана с самого начала.

1

Это функция преобразования строки в число. Похожий на atoi.

Строка — это последовательность символов. Так что «123» в памяти будет:
‘1’, ‘2’, ‘3’, NULL,

р указывает на это.

Теперь, согласно ASCII, цифры кодируются от «0» до «9». «0» присваивается значение 48, а «9» присваивается значение 57. Таким образом, «1», «2», «3», NULL в памяти на самом деле: 49, 50, 51, 0

Если вы хотите преобразовать из символа «0» в целое число 0, вам придется вычесть 48 из значения в памяти. Вы видите, куда это идет?

Теперь вместо вычитания числа 48 вы вычитаете «0», что облегчает чтение кода.

1
По вопросам рекламы [email protected]