Этот код имеет проблемы:
while(c = getchar() != '\n' && c != EOF)
достаточно не круглые скобки - назначение оператора низкий приоритет. Оно должно быть:
while ((c = getchar()) != '\n' && c != EOF)
Другой набор проблем в коде преобразования в теле цикла:
if (c >= 97)
c = c - 'a' - 1;
else
c = c;
numdec += numdec * base + c;
Выбор 97
является предположительно ASCII или ISO 8859- п или Кодовая точка Unicode для a
. Это игнорирует буквы верхнего регистра, знаки пунктуации и обрабатывает цифры 0
до 9
, как будто они 48..57. Вероятно, вам нужно использовать #include <ctype.h>
. Он также не подтверждает, что «цифра» действительна для базы.
Однако при первом обращении к intToDec()
первый символ, прочитанный символом, является символом новой строки, оставленным scanf()
, поэтому первое число всегда равно нулю, если вы вводите цифры по одному в строке, как вам сказали.
Когда вы наконец доберетесь до outToDec()
, у вас есть интересная нумерология. Я добавил printf()
заявление для отслеживания входа функции и выхода, а также для ключевых точек в цикле:
void outFromDec(int num, int base)
{
printf("-->> %s: %d %d\n", __func__, num, base);
int count = 0, temp = num, i;
char c;
while (temp != 0)
{
temp /= base;
count++;
}
printf("Count: %d\n", count);
temp = num;
do
{
printf("count: %d; temp = %d\n", count, temp);
for (i = 1; i < count; i++)
temp /= base;
if (temp <= 9)
c = '0' + temp;
else
c = 'a' + temp - 1;
putchar(c);
count--;
temp = num/temp;
} while (temp != 0);
printf("<<-- %s\n", __func__);
}
__func__
является предопределенным идентификатором в C99, содержащее имя функции. Он может быть недоступен для вас в MSVC; если нет, замените его именем функции.
Для входов 1
, 9
, 9
, выход из программы был:
-->> inToDec: 9
<<-- inToDec: 0
-->> inToDec: 9
<<-- inToDec: 57
-->> outFromDec: 57 9
Count: 2
count: 2; temp = 57
6count: 1; temp = 9
9count: 0; temp = 6
6count: -1; temp = 9
9count: -2; temp = 6
И граф продолжал уменьшаться, а 6-х и 9-х продолжали чередовать.Кажется, вы пытаетесь изолировать цифры с самой значащей цифрой (MSD), обнаруженной в первую очередь. Петля, определяющая count
, верна; цикл печати цифр явно нет. Вы должны быть в состоянии взять это оттуда; это обычная отладка. Обратите внимание, как я использовал заявления печати, чтобы узнать, что происходит. Если вы не можете решить проблему, просто просмотрев код, при необходимости распечатайте результат каждого выражения.
Я заметил, что для печати 57 в базе 10 вы обнаружили, что для печати есть 2 цифры (count == 2
). Первая цифра будет найдена путем деления на основание (10) count-1
раз; это даст вам 5 для печати. Вероятно, вам нужно вычесть 5 * 10 из числа, так что следующее (в данном случае, последнее) время вокруг цикла, вы начнете с 7, которые вы будете печатать. Цикл остановится. Вы должны обеспечить разрывы цикла, если count
когда-либо будет отрицательным.
Это дорогой способ форматирования 10-значного 32-разрядного номера (или, что еще более важно, 19-разрядного 64-битного номера). Однако его можно заставить работать. Стандартная процедура собирает цифры в обратном порядке и организует их распечатку в обратном порядке. (number % base
дает цифру, которая будет напечатана, number /= base
уменьшает количество цифр слева обрабатывать.)
Как происходит довольно часто, то ФП в искусственных ограничений и не может использовать строки. Тьфу!
Вот функция «читать целое число», которая является правдоподобной. Это предполагает арифметику дополнения 2; он содержит утверждение, которое должно срабатывать, если оно когда-либо запускалось на машине, которая была знаковой величиной или дополнением 1 (но я ее не тестировал, у меня нет таких машин, доступных для тестирования).
Обратите внимание, что код накапливает число как отрицательное число и делает его положительным в конце, если он должен быть положительным. Это облегчает работу с INT_MIN, чем попытка накопить его как положительный int
.
Для целей упражнения я рассматриваю систему как бы sizeof(intmax_t) == sizeof(int)
(и, следовательно, sizeof(int) == sizeof(long)
и sizeof(int) == sizeof(long long)
); этот метод будет работать, если целочисленный тип был intmax_t
вместо int
. Обратите внимание, что стандарт C не исключает эту предполагаемую конфигурацию (но для стандарта требуется, чтобы CHAR_BIT * sizeof(int) >= 64
соответствовала реализации).
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
/* Read an integer from stdin without prompt: code is not allowed to use strings! */
enum { E_OK = 0, E_EOF = -1, E_INVCHAR = -2, E_OVERFLOW = -3 };
extern int read_an_int(int *value);
int read_an_int(int *value)
{
int number = 0;
int c;
int pos_neg = +1;
assert(-INT_MAX != INT_MIN); // Probably 2's complement
while ((c = getchar()) != EOF && isspace(c))
;
if (c == '-')
{
pos_neg = -1;
c = getchar();
}
else if (c == '+')
{
pos_neg = +1;
c = getchar();
}
if (c == EOF)
return E_EOF;
if (!isdigit(c))
return E_INVCHAR;
number = '0' - c; /* Negated digit */
while ((c = getchar()) != EOF && isdigit(c))
{
int d = '0' - c; /* Negated digit */
if (number < INT_MIN/10 || (number == INT_MIN/10 && d < INT_MIN % 10))
return E_OVERFLOW;
//printf("N1 %d; d %d; ", number, d);
number = number * 10 + d;
//printf("N2 %d\n", number);
}
if (c != EOF)
ungetc(c, stdin);
if (pos_neg != -1)
{
//printf("Should be switched (%d)(%d)\n", pos_neg, number);
if (number == INT_MIN)
return E_OVERFLOW;
number = -number;
//printf("Should be positive (%d)(%d)\n", pos_neg, number);
}
*value = number;
return E_OK;
}
static void gobble_input(void)
{
int c;
while ((c = getchar()) != EOF)
{
if (isdigit(c) || c == '+' || c == '-')
{
ungetc(c, stdin);
break;
}
printf("Skip %c\n", c);
}
}
int main(void)
{
int rc;
int number;
while ((rc = read_an_int(&number)) != E_EOF)
{
switch (rc)
{
case E_INVCHAR:
printf("Invalid character spotted\n");
gobble_input();
break;
case E_OVERFLOW:
printf("Input would have overflowed integer range %d..%d\n", INT_MIN, INT_MAX);
break;
case E_OK:
printf("Input number: %d\n", number);
break;
default:
assert(0);
break;
}
}
return 0;
}
Файл тестовых данных я использовал:
0
1
2
3
4
5
6
7
8
9
11
+123
1234
56789
+123456789
2147483647
2147483648
+00000
00000
-0000
+0000
-1
-2
-9
-21
-321
-4321
-2147483647
-2147483648
-2147483649
# Bogus data or partially bogus data
-
+
-213a
+213a
+.213
3.14159E+23
Выход был:
Input number: 0
Input number: 1
Input number: 2
Input number: 3
Input number: 4
Input number: 5
Input number: 6
Input number: 7
Input number: 8
Input number: 9
Input number: 11
Input number: 123
Input number: 1234
Input number: 56789
Input number: 123456789
Input number: 2147483647
Input would have overflowed integer range -2147483648..2147483647
Input number: 123456789
Input number: 123456789
Input number: 0
Input number: 0
Input number: -1
Input number: -2
Input number: -9
Input number: -21
Input number: -321
Input number: -4321
Input number: -2147483647
Input number: -2147483648
Input would have overflowed integer range -2147483648..2147483647
Invalid character spotted
Skip
Skip B
Skip o
Skip g
Skip u
Skip s
Skip
Skip d
Skip a
Skip t
Skip a
Skip
Skip o
Skip r
Skip
Skip p
Skip a
Skip r
Skip t
Skip i
Skip a
Skip l
Skip l
Skip y
Skip
Skip b
Skip o
Skip g
Skip u
Skip s
Skip
Skip d
Skip a
Skip t
Skip a
Skip
Invalid character spotted
Invalid character spotted
Input number: -213
Invalid character spotted
Skip
Input number: 213
Invalid character spotted
Skip
Invalid character spotted
Input number: 213
Input number: 3
Invalid character spotted
Input number: 14159
Invalid character spotted
Input number: 23
Обратите внимание, что последняя строка при условии, 3 действительных чисел (и два недопустимых символов, .
и E
).
Это не особенно легко; поэтому эти вещи закодированы в библиотечных функциях. Кроме того, требование «нет строк» означает, что я не могу выполнять достойную отчетность об ошибках при наличии недопустимых символов или переполнений.
Вы ничего не печатаете и на какой платформе вы находитесь? – haccks
Платформа? Не получите то, что вы просите, но если вы имеете в виду ОС и программное обеспечение, то я использую Visual C++ 2010 в Windows 7. – Sunspawn
Я спрашивал об ОС. Теперь опубликуйте функцию 'outFromDec', это поможет нам отладить ваш код. :) – haccks