Упражнение 3.4 K&R - C (СИ)
Формулировка задачи:
Дана функция:
поглядел видосы про доп код, понял что проблема в смещении бита знакового за пределы битовой сетки.
ну, и, правильно ли я понимаю что достаточно использовать тип double для принимаемого значения n, и там оно само приведется все по типам и заработает?
/* itoa: преобразование n в строку s */
void itoa (int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* сохраняем знак */
n = -n; /* делаем n положительным */
i = 0;
do { /* генерируем цифры в обратном порядке */
s[i++] = n % 10 + '0'; /* следующая цифра */
} while ((n /= 10) > 0); /* исключить ее */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}При условии, что для представления чисел используется дополнительный код, наша версия itoa не справляется с самым большим по модулю отрицательным числом, значение которого равняется -(2^n-1), где n — размер слова. Объясните, чем это вызвано. Модифицируйте программу таким образом, чтобы она давала правильное значение указанного числа независимо от машины, на которой выполняется.
Решение задачи: «Упражнение 3.4 K&R»
textual
Листинг программы
#include <stdio.h>
#include <math.h>
#define MAX 100
void itoa (int n, char s[]);
void reverse (char s[]);
int main (){
char s[MAX] = "";
int n;
printf("Введите число: ");
scanf("%d", &n);
itoa (n,s);
printf("%s \n", s);
return 0;
}
/* itoa: преобразование n в строку s */
void itoa (int n, char s[])
{
int i=0;
int sign;
if ((sign = n) > 0) /* если положительное */
n -= (n+n); /* делаем отрицательным */
do { /* генерируем цифры в обратном порядке */
s[i++] = abs(n%10)+'0'; /* следующая цифра */
} while (n /= 10); /* исключить ее */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
void reverse (char s[])
{
int i, j;
int temp;
for (j = 0; s[j] != '\0'; ++j) /* Получаем размер массива */
;
for (i = 0, j--; i < j; i++, j--){
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
Объяснение кода листинга программы
- Объединение двух строк с помощью оператора
+происходит в функцииitoaпри генерации цифр в обратном порядке. - В функции
mainиспользуется функцияscanfдля ввода целого числа в переменнуюn. - Функция
itoaвызывается в функцииmainдля преобразования числаnв строкуs. - В функции
itoaиспользуется циклdo-whileдля генерации цифр в обратном порядке. - В функции
itoaиспользуется оператор/= 10для деления числаnна 10 и получения следующей цифры. - В функции
itoaиспользуется функцияabsдля получения абсолютного значения числаn. - В функции
itoaиспользуется функцияreverseдля переворота строкиs. - В функции
reverseиспользуется циклforдля получения размера строкиs. - В функции
reverseиспользуется временная переменнаяtempдля обмена символами в строкеs. - В функции
mainвыводится строкаsс помощью функцииprintf. - В функции
mainиспользуется функцияscanfдля ввода числа. - В функции
mainвызывается функцияitoaдля преобразования числа в строку. - В функции
mainвыводится строкаsс помощью функцииprintf. - В функции
mainвозвращается значение 0, что означает успешный конец работы программы. - В функции
itoaиспользуется переменнаяsignдля хранения знака числаn. - В функции
itoaиспользуется оператор%для получения остатка от деления числаnна 10. - В функции
itoaиспользуется функцияabsдля получения абсолютного значения числаn. - В функции
itoaиспользуется переменнаяiдля хранения индекса текущей цифры в строкеs. - В функции
itoaиспользуется переменнаяjдля хранения индекса последней цифры в строкеs. - В функции
reverseиспользуется переменнаяtempдля обмена символами в строкеs.