我需要收到一行字符并将它们从写入的基数转换为十进制基数,只要输入一个字符就 。
我是通过使用以下功能完成的:
int inToDec(int base) //My assumption is that Enter will not be pressed as the first character - if it is, I am not sure what to do in that case
{
int numdec=0, c;//decimalized number, a variable for character inpu
while((c = getchar()) != '\n' && c != EOF)
{
if(c >= 97)//Checks if the char is an actual char
c = c - 'a' - 1;
else//or a digit char
c = c;
numdec += numdec * base + c;//every time another char is inputted, it multiplies the numdec by the base and adds the char's value in decimal base - which is essentially the algorithm for conversion to decimal base.
}
return numdec;
}
我的主要():
#include <stdio.h>
#include "funcs.h"
int main()
{
int option, fbase, tbase, num1, num2;
do
{
scanf("%d",&option);
switch(option)
{
case 1:
scanf("%d",&fbase);
num1 = inToDec(fbase);
num2 = inToDec(fbase);
outFromDec(num1+num2,fbase);
break;
case 2:
scanf("%d",&fbase);
num1 = inToDec(fbase);
num2 = inToDec(fbase);
if(num1>=num2)
outFromDec(num1-num2,fbase);
else
outFromDec(num2-num1,fbase);
break;
case 3:
scanf("%d",&fbase);
scanf("%d",&tbase);
num1 = inToDec(fbase);
outFromDec(num1,tbase);
break;
}
}while(option != 4);
return 0;
}
当我输入数字(在选项和所需的基数之后)并输入Enter继续下一个时,突然它开始一次又一次地打印一个字符而没有结束。我做错了什么,我该如何解决?或者,如果你不想向菜鸟解释一些明显的事实,我在哪里读到它(最好没有太多重要的技术谈话,因为我对编程比较新)。
outFromDec() -
void outFromDec(int num, int base) //converts num into the base given and prints
{
int count = 0 , temp = num, i;
char c;
while(temp != 0)
{
temp /= base;
count++;
}
temp = num;
do
{
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);
}
答案 0 :(得分:3)
此代码存在问题:
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
的选择可能是a
的ASCII或ISO 8859- n 或Unicode代码点。这会忽略大写字母,标点符号,并将数字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
的循环是正确的;清楚地打印数字的循环不是。你应该可以从那里拿走它;这是例行调试。请注意我如何使用print语句来查看发生了什么。如果仅通过查看代码无法解决问题,请在必要时打印出每个表达式的结果。
我观察到要在基数10中打印57,你会发现有两个数字要打印(count == 2
)。通过除以基数(10)count-1
次找到第一个数字;这将给你打印5。您可能需要从数字中减去5 * 10,以便循环中的下一个(在本例中为最后一个)时间,您将从7开始,然后打印。循环会停止。如果count
变为负数,则应确保循环中断。
这是一种格式化10位32位数字(甚至更多19位64位数字)的昂贵方法。但它可以使用。标准程序以相反的顺序收集数字并安排以相反的顺序打印出来。 (number % base
为您提供要打印的数字; number /= base
会减少要处理的数字位数。)
正如经常发生的那样,OP受到人为限制,可能不会使用字符串。呸!
这是一个看似强大的“读取整数”函数。它假定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
+000000123456789
000000123456789
-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
)。
不是特别容易;这就是为什么这些东西在库函数中编码。此外,“无字符串”要求意味着当存在无效字符或溢出时,我无法进行正确的错误报告。
答案 1 :(得分:0)
如果您在Windows中工作,请在fflush (stdin)
所在的循环之前添加getchar()
。那就是:
int inToDec(int base) //My assumption is that Enter will not be pressed as the first character - if it is, I am not sure what to do in that case
{
int numdec=0, c;//decimalized number, a variable for character inpu
fflush (stdin); /* flushes input buffer */
while(c = getchar() != '\n' && c != EOF)
{
if(c >= 97)//Checks if the char is an actual char
c = c - 'a' - 1;
else//or a digit char
c = c;
numdec += numdec * base + c;//every time another char is inputted, it multiplies the numdec by the base and adds the char's value in decimal base - which is essentially the algorithm for conversion to decimal base.
}
return numdec;
}