Oxford 发表于 2019-12-3 22:20:38

用getch()来替换scanf()

编写自定义整数输入函数

函数原型为:int inputInt(int min, int max);

说明:入参min和max分别表示该函数输出的最小和最大值。

功能基本要求:

在windows操作系统下,使用codeblocks做为开发工具。函数实现过程中,只能使用getch()做为键盘的输入,不得使用scanf、gets之类的系统函数。以回车键结束输入,对于不符合要求的输入提供合理的解决方法,支持退格键,支持16进制输入(以0x或0X开始,16进制支持a-f和A-F),对于10进制方式的输入,不能以0开始输入。

调用示例:

    int x;

    x = inputInt(1, 500);

输入示例:

    输入“123<回车>”,则函数返回整数123

    输入“0x123<回车>”,则函数返回整数291

jackz007 发表于 2019-12-4 01:30:40

本帖最后由 jackz007 于 2019-12-4 01:46 编辑

#include <stdio.h>
#include <conio.h>

inputInt(void)
{
      char c , s                                                                        ;
      int a , d , e , k , m                                                                   ;
      bool f                                                                                  ;

      for(m = 0 ; (c = getch()) != 0x0d && m < 81 ;) {
                if(c == 8) {
                        if (m) {
                              printf("\b \b")                                                 ;
                              s = 0x00                                                 ;
                              m --                                                            ;
                        }
                } else {
                        s = c                                                             ;
                        printf("%c" , c)                                                      ;
                }
      }
      printf("\n")                                                                            ;
      for(; (s == 0x09 || s == 0x20) && m > 0 ; s = 0)                ;
      for(e = 0 ; (s == 0x09 || s == 0x20) && e < m ; e ++)                           ;
      for(k = e ; k < m + 1 ; k ++) s = s                                           ;
      m -= e                                                                                  ;
      e = 0                                                                                 ;
      if(m > 0) {
                if(m > 1 && s == '0' && (s == 'x' || s == 'X')) {
                        if(m > 2) {
                              for(f = true , k = 2 ; k < m && f ; k ++) {
                                        if(s >= '0' && s <= '9') d = s - '0'         ;
                                        else if(s >= 'a' && s <= 'f') d = 10 + s - 'a' ;
                                        else if(s >= 'A' && s <= 'F') d = 10 + s - 'A' ;
                                        else f = false                                          ;
                                        if(f) e = e * 16 + d                                    ;
                              }
                              if(! f) e = 0                                                   ;
                        }
                } else {
                        a = 0                                                                   ;
                        if(s == '-') a ++                                                    ;
                        if(m > a) {
                              if(s != '0') {
                                        for(f = true , k = a ; k < m && f ; k ++) {
                                                if(s >= '0' && s <= '9') d = s - '0'   ;
                                                else f = false                                  ;
                                                if(f) e = e * 10 + d                            ;
                                        }
                                        if(! f) e = 0                                           ;
                                        else if(a) e = -e                                       ;
                              }
                        }                        
                }
      }
      return e                                                                              ;
}

main(void)
{
      int d            ;
      d = inputInt()   ;
      printf("%d\n" , d) ;
}
      编译运行实况:
C:\Bin>g++ -static -o getint getint.c

C:\Bin>getint
                              0x123
291

C:\Bin>getint
                        123
123

C:\Bin>

      inputInt() 可以自动去掉输入数字过程中输入的前导以及尾随的空格及 TAB 字符。

Oxford 发表于 2019-12-4 12:16:56

      for(; (s == 0x09 || s == 0x20) && m > 0 ; s = 0)                ;
      for(e = 0 ; (s == 0x09 || s == 0x20) && e < m ; e ++)                           ;
      for(k = e ; k < m + 1 ; k ++) s = s                                           ;代没太看懂了,可而且段代码在codeblocks编译通过不了,但还是很感谢!{:9_232:}

bin554385863 发表于 2019-12-4 17:13:37

本帖最后由 bin554385863 于 2019-12-4 22:11 编辑

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <ctype.h>
int inputInt()
{
    int result = 0, ct = 0, sz = 2;
    char f = '0';
    char *str = (char *)malloc(sizeof(char) * sz);
    while ((f = getch()) != '\r') //使用用动态数组存储读取的字符
    {
      str = f;
      putch(f);//回显
      ct++;
      char *tmp = (char *)malloc(sizeof(char) * (sz + ct));
      tmp = '\0';
      strcpy(tmp, str);
      free(str);
      str = tmp;
    }
    printf("\n");
    char res;
    res = '+';
    res = '\0';
    if (str == '-')
    {
      strcpy(res, str);
    }
    else
    {
      strcat(res, str);
    }
    free(str);
    if (res == '+') //如果是正数
    {
      if (res == '0' && (res == 'x' || res == 'X')) //如果是16进制数
      {
            for (size_t i = 3; i < strlen(res); i++)
            {
                if (isdigit(res) || ((res >= 'a') && (res <= 'f')) || (res >= 'A' && res <= 'F'))
                {
                  if (isupper(res))
                  {
                        res = (char)(58 + res - 'A');
                  }
                  else if (islower(res))
                  {
                        res = (char)(58 + res - 'a');
                  }
                }
                else
                {
                  perror("ERROR");
                  exit(1);
                }
                result = result * 16 + (res - 48);
            }
      }
      else //如果是10进制数
      {
            for (size_t i = 1; i < strlen(res); i++)
            {
                if (!isdigit(res))
                {
                  perror("ERROR");
                  exit(1);
                }
                else
                {
                  result = result * 10 + (res - 48);
                }
            }
      }
    }
    else if (res == '-') //如果是负数
    {
      if (res == '0' && (res == 'x' || res == 'X')) //如果是16进制数
      {
            for (size_t i = 3; i < strlen(res); i++)
            {
                if (isdigit(res) || ((res >= 'a') && (res <= 'f')) || (res >= 'A' && res <= 'F'))
                {

                  if (isupper(res))
                  {
                        res = (char)(58 + res - 'A');
                  }
                  else if (islower(res))
                  {
                        res = (char)(58 + res - 'a');
                  }
                }
                else
                {
                  perror("ERROR");
                  exit(1);
                }
                result = result * 16 + (res - 48);
            }
            result = -result;
      }
      else //如果是10进制数
      {
            for (size_t i = 1; i < strlen(res); i++)
            {
                if (!isdigit(res))
                {
                  perror("ERROR");
                  exit(1);
                }
                else
                {
                  result = result * 10 + (res - 48);
                }
            }
            result = -result;
      }
    }
    return result;
}
int main(int argc, char const *argv[])
{
    int x = inputInt();
    printf("%d", x);
    return 0;
}

==================================================
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-amcrwj1k.g4k --stdout=Microsoft-MIEngine-Out-34ojn3ac.qyj --stderr=Microsoft-MIEngine-Error-lmt4kyln.wpk --pid=Microsoft-MIEngine-Pid-n005cbfs.inj --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
123
123
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-pmbslost.gwc --stdout=Microsoft-MIEngine-Out-xfshvka4.qiy --stderr=Microsoft-MIEngine-Error-yph4nrau.az3 --pid=Microsoft-MIEngine-Pid-rb14fg1b.pdj --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
-123
-123
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-atgvy5or.llj --stdout=Microsoft-MIEngine-Out-bwe3hyko.wok --stderr=Microsoft-MIEngine-Error-311wjcni.l4e --pid=Microsoft-MIEngine-Pid-sr4c5jcp.ccq --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
0x123
291
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-sin3opxt.nyb --stdout=Microsoft-MIEngine-Out-a0fbswkr.b5g --stderr=Microsoft-MIEngine-Error-30dxkm0p.h2s --pid=Microsoft-MIEngine-Pid-nm2t0sdj.2bh --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
-0x123
-291
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-g1lrueul.yhg --stdout=Microsoft-MIEngine-Out-lnjuzxo5.muv --stderr=Microsoft-MIEngine-Error-wxti4a10.xew --pid=Microsoft-MIEngine-Pid-iswgkr3q.4lz --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
lk00
ERROR: No error

E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-teqodghs.ovy --stdout=Microsoft-MIEngine-Out-lrgunujb.g0t --stderr=Microsoft-MIEngine-Error-mneikxwz.koj --pid=Microsoft-MIEngine-Pid-i2gs0wvy.q3u --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
136l
ERROR: No error

E:\Users\admin\Documents\VScode\Code>c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-yil3vgkk.odh --stdout=Microsoft-MIEngine-Out-zsfp2ehb.0q0 --stderr=Microsoft-MIEngine-Error-00f454g2.5fu --pid=Microsoft-MIEngine-Pid-pw3cpvdv.fvf --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi
0xa
10
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-znatdx5t.ggl --stdout=Microsoft-MIEngine-Out-ngm1id0g.njp --stderr=Microsoft-MIEngine-Error-pdufa5ld.foa --pid=Microsoft-MIEngine-Pid-grtfoskv.aoo --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
-0xF
-15
E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-ov1xvfy5.oq3 --stdout=Microsoft-MIEngine-Out-mlidmuhj.t2c --stderr=Microsoft-MIEngine-Error-mc5uhumz.xwc --pid=Microsoft-MIEngine-Pid-twdsngu2.zzq --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
-0xB&
ERROR: No error

E:\Users\admin\Documents\VScode\Code>cmd /C "c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.2\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-1va50uaw.2g4 --stdout=Microsoft-MIEngine-Out-iaraai5w.xkb --stderr=Microsoft-MIEngine-Error-244syxg4.0da --pid=Microsoft-MIEngine-Pid-rg44mr2j.dws --dbgExe=D:\MinGW\bin\gdb.exe --interpreter=mi "
0xAFN
ERROR: No error

E:\Users\admin\Documents\VScode\Code>

ba21 发表于 2019-12-4 17:31:32

本帖最后由 ba21 于 2019-12-4 17:32 编辑

jackz007 发表于 2019-12-4 01:30
编译运行实况:



发错对像

ba21 发表于 2019-12-4 17:33:09


昨晚看了下,没完成,今 天又看了下,看楼上的代码实属高手看的代码,如 果不格式化好我是没法看下去。
所以我还是按我的思路搞了段代码,给参考下:
#include <stdio.h>
#include <conio.h>

/*
16进制字符串转10进制算法:

用变量a存放转换结果,赋初值为0

逐一取得字符串每个字符:从头一直取字符,直到遇到0为止

每取得一个字符:

-变量a自乘16

-判断字符是否数字字符,如果是数字字符则直接转换成数值

-否则,判断字符是否小写字母a~f,如果是转成10~15数值

-否则,判断字符是否大写字母a~f,如果是转成10~15数值

-将以上得到的数值加到变量a上,然后进行下一个字符的处理
*/
int h2d(char *s)
{
        int a=0;
        while ( *s )
        {
                a *= 16;
                if ( *s>='0' && *s<='9' )
                        a += *s - '0';
                else if ( *s>='a' && *s<='f' )
                        a += *s- 'a' + 10;
                else if ( *s>='A' && *s<='F' )
                        a += *s - 'A' + 10;

                s++;
        }

return a;
}

/*
16进制字符串转10进制算法:

用变量a存放转换结果,赋初值为0

逐一取得字符串每个字符:从头一直取字符,直到遇到0为止

每取得一个字符:

-变量a自乘10

-数字字符转换成数值
*/
int d2d(char *s)
{
        int a=0;
        while ( *s )
        {
                a *= 10;
                a += *s - '0';
                s++;
        }

return a;
}

int inputint()
{
        int i, x;
        char num = {'\0'};
        char ch;

/* 接受输入 */
        i=0;
        while( (ch=getch())!='\r')
        {
                // 退格
                if ( (ch == 8) && (i!=0) )
                {
                        num[--i] = '\0';
                        printf("\b \b"); // 实现退格回显
                        continue;
                }

                // 不是有效字符 continue
                if ( !( (ch>='0' && ch<='9') || (ch>='a' && ch<='f') || (ch>='A' && ch<='F') || (ch=='x' || ch=='X') ) )
                {
                        continue;
                }
               
                // 先接收第1位               
                if ( i==0 )
                {
                        // 第1位只能'0' - '9'
                        if ( !(ch>='0' && ch<='9') )
                                continue;

                        num = ch;
                        i++;
                        putch(ch); // 回显                               
                }
                else // 其它位
                {                       
                        if ( num=='0' )
                        {
                                // 16进制

                                if ( i==1 )
                                {       
                                        // 第2位只能接收x
                                        if (ch!='x' && ch!='X')
                                                continue;

                                }
                                else
                                {
                                        // 第2位后只能接收'0' - '9' 'a' - 'f'
                                        if ( !(ch>='0' && ch<='9') && !(ch>='a' && ch<='f') && !(ch>='A' && ch<='F') )
                                                continue;
                                }               

                        }
                        else
                        {
                                // 10进制

                                // 只能接收'0' - '9'
                                if ( !(ch>='0' && ch<='9') )
                                        continue;                       
                        }
                        num = ch;
                        i++;
                        putch(ch); // 回显       
                }

        }
        printf("\n");

/* 转换 */
        if ( num=='0')
                // 16 转 10
                x = h2d(num);
        else               
                // 10 转 10
                x = d2d(num);

        return x;
}

int main(void)
{
        int n;

        n = inputint();
       
        printf("%d\n", n);

        return 0;
}

jackz007 发表于 2019-12-4 18:31:46

本帖最后由 jackz007 于 2019-12-4 18:37 编辑

Oxford 发表于 2019-12-4 12:16
for(; (s == 0x09 || s == 0x20) && m > 0 ; s = 0)                ;
...

      问题出在代码中含有 bool 数据类型,C 不支持,C++ 支持。其实,这个问题很好解决,只要把文件的扩展名从 ".c" 改成 ".cpp" 就可以了。
      我使用的编译器和你的完全一样,你可以试试看。
页: [1]
查看完整版本: 用getch()来替换scanf()