C getchar输入问题

时间:2013-11-23 12:55:02

标签: c 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
    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);
}

2 个答案:

答案 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中可能无法使用它;如果没有,请将其替换为函数名称。

对于输入199,该计划的输出为:

-->> 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;
}