3

I need to make a c++ program on Linux in which the used will only be able to input integers and no characters and special characters. Well for windows (where I have used the conio.h header file for getch()) below is the program which works fine.

#include<iostream>
#include<stdio.h>
#include<conio.h>
 int getOnlyIntegers()
 {
    int ch;
    long int num = 0;
    do
    {
        ch = getch();
        if(ch >= 48 && ch <= 57)
        {
            printf("%c",ch);
            num = (ch-48) + (num*10);
        }
        if(ch == 13)
        {
            break;
        }
    }while(1);
    return num;
 }
 int main()
 {
    int x;
    x = getOnlyIntegers();
    printf("\n%d", x);
    return 0;
 }

Now in Linux I'm using #include<curses.h> header file for using getch(); and the code is

#include<iostream>
#include<ctype.h>
#include "curses.h"
using namespace std;
int getOnlyNumbers()
{
    int ch;
    int num = 0;
    initscr();
    do
    {
        ch = getch();
        if(isdigit(ch))
        {
            cout<<ch;
            num = (ch - 48) + (num*10);
        }
        if(ch == '\n') // if the user press enter key
        {
            break;
        }
    }while(1);
    return num;
}
int main()
{
    int num;
    num = getOnlyNumbers();
    cout<<endl<<num;
    return endwin();
}

on compiling it I get a new screen (I guess that is probably due to initscr()) and every number, character and special character is getting printed on screen and if I press enter then also the screen remains as it was.

What correctness I need to do?

why I used getch()?

because variable ch will store whatever is entered through getch() without being displayed on the screen. So the main purpose of this program is to only show number on output as well as in input.

Here are some images of the screens :-

1> enter image description here

2> enter image description here

3> enter image description here

In the second Image when I press s, a and d then these characters are also getting displayed and I don't want that to be displayed.

  • Why do you use `getch()` at all? – alk Dec 27 '15 at 12:14
  • @alk so that if I enter a character the it will not get displayed on the screen. –  Dec 27 '15 at 12:16
  • Avoid the use of [*magic numbers*](https://en.wikipedia.org/wiki/Magic_number_%28programming%29) as much as possible. For [character classification](http://en.cppreference.com/w/cpp/string/byte#Character_classification) use existing functions like [`std::isdigit`](http://en.cppreference.com/w/cpp/string/byte/isdigit). In all other places use actual character literals instead, like e.g. `'\n'` instead of `13`. It will make the code clearer and easier to read, both for others and also yourself in a few months time. – Some programmer dude Dec 27 '15 at 12:18
  • @JoachimPileborg , okay on it.. –  Dec 27 '15 at 12:20
  • Also, if you want to enable or disable echoing temporarily in a Linux program, [there are ways to do that](http://man7.org/tlpi/code/online/dist/tty/no_echo.c.html). – Some programmer dude Dec 27 '15 at 12:22
  • @JoachimPileborg done with that... but still the problem is the same –  Dec 27 '15 at 12:24
  • I used this method because this is the simplest one . http://stackoverflow.com/questions/34474627/linux-equivalent-for-conio-h-getch –  Dec 27 '15 at 12:25
  • @JoachimPileborg yes, there are.. but what's the problem with this one? –  Dec 27 '15 at 12:26
  • When using curses is almost a requirement to use the curses input and output functions. If you turn off echoing using [`termios`](http://man7.org/linux/man-pages/man3/termios.3.html) you can still use e.g. `std::cin` to read formatted input. It's a little more work to setup but it will make the reading of the number much easier. – Some programmer dude Dec 27 '15 at 12:29
  • 1
    @JoachimPileborg The code and question has been edited as you demanded the code to be and still the problem stays. The initscr() still shows the character being entered and that I don't want. The method you told is awesome but this should also work. right? –  Dec 27 '15 at 12:46

3 Answers3

1

You will need to do at least these three things to get your code to work right, marked with comments below:

int getOnlyNumbers()
{
    int ch;
    int num = 0;
    initscr();
    // disable echo by calling noecho() function
    noecho();
    do
    {
        ch = getch();
        if(isdigit(ch))
        {
            // cast int to char to get correct printout,
            // and flush to force printing it without a newline.
            std::cout << static_cast<char>(ch) << std::flush; 
            num = (ch - 48) + (num*10);
        }
        if(ch == '\n') // if the user press enter key
        {
            break;
        }
    } while(1);
    return num;
}

As a side note, I would advise against using namespace std; even in a .cpp file, both in general, and especially when you are including extra libraries, like here. It's just too easy to have name conflicts, and seeming unexplainable strange behaviour. Better type out that std:: even if it feels repetitive, it'll save the "wasted" time many times over when it helps you avoid a mysterious bug.

Links as possible starting points for browsing documentation:

hyde
  • 60,639
  • 21
  • 115
  • 176
1

If you insist on mixing iostream and curses, there are a few problems remaining, fixed in this modified example:

  • initscr sets a flag telling curses to clear the screen on the next refresh. getch refreshes the screen.
  • OP's intent is not to provide a full-screen program; use filter for single-line prompts
  • just in case some output using curses was overlooked, use newterm to make curses' output go to the standard error (allowing one to redirect the output of the program)
  • endwin returns a -1 on error, which is probably not the intent for returning an exit-code from main.

Here is the revised example:

#include <iostream>
#include <ctype.h>
#include <curses.h>
using namespace std;
int getOnlyNumbers()
{
    int ch;
    int num = 0;
    filter();
    newterm(NULL, stderr, stdin);
    noecho();
    do
    {
        ch = getch();
        if(isdigit(ch))
        {
            std::cout << static_cast<char>(ch) << std::flush; 
            num = (ch - 48) + (num*10);
        }
        if(ch == '\n') // if the user press enter key
        {
            break;
        }
    } while(1);
    endwin();
    return num;
}
int main()
{
    int num;
    num = getOnlyNumbers();
    cout<<endl<<num;
    return 0;
}
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
-2

You need to look at the man page for isalpha, which includes entries for isdigit, isdigit_l and others. The code you have is truly horrible, and has no chance of working in any environment which uses non-ascii characters (e.g. a utf-8 environment).

MWiesner
  • 8,868
  • 11
  • 36
  • 70
  • The code has been edited as you demanded and still the problem stays. I will put some images of the console. Please wait :) –  Dec 27 '15 at 12:35
  • This answer is more like a comment. –  Dec 27 '15 at 13:04