Thread: A very SIMPLE program that is IMPOSSIBLE to create on Mac!

  1. #1
    Registered User
    Join Date
    Oct 2019
    Posts
    14

    A very SIMPLE program that is IMPOSSIBLE to create on Mac!

    Hello everyone! This is my first post so thanks for the community for letting me in and hope everybody is in great shape. I am an "amateur" programmer who only knows the C language, pretty much used to it.

    Well, maybe the "IMPOSSIBLE" in the title is a little hyperbolic, who knows, but I've spent literally almost 3 days searching to do a very basic program and I can't find out how!

    I am looking to make a program that starts counting the time when pressing the space button, then stops counting the time when the space button is pressed again, using clock() (for very precise time). Or in other words, how to make C calculate the time spent between pressing space button 2 times. That's it.

    On Mac, there is no library such as <conio.h>, we have <curses.h>, but does not have all functionalities.

    Main difficulties:
    1-I don't know how to make C understand that I want it to take into account a button I pressed without requiring ENTER.
    2- I found out Scanf pauses the clock(), so while waiting for the user the time is not calculated..... I must find a way for a program to be paused while calculating time simoultaneously.

    I hope my message was simple and clear.

    Thanks for anyone who has knowledge for help!
    Last edited by thomasak; 3 Weeks Ago at 10:03 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,484
    1. Ncurses has far more functionality than conio.h ever had. All you need to do is look.

    For example, getting a character without waiting.
    c - how to get a character from stdin without waiting for user to put it? - Stack Overflow

    2. clock() measures CPU time, so if you're not doing anything, then typically, you're not using the CPU either.
    Use clock_gettime(2): clock/time functions - Linux man page if you want to measure actual passage of time as measured by your apple watch.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    Thank you very much Salem, I will be working on this, I will come back here shortly for a feedback if I had managed to create my program or not.

  4. #4
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    I managed to get the information I wanted, but I keep getting this message "clang: error: linker command failed with exit code 1 (use -v to see invocation)"

    As an example, this is my code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <curses.h>
    
    char a;
    
    
    int main()
    {
        initscr();
        a=getch();
        if (a=='t') printf ("\nyes that's correct\n");
    }
    I have checked on the apple developper website (Mac OS X Manual Page For nodelay(3x)) and all these functions above are described here so they must exist in <curses.h>. If I try the program without initscr(); same exact message. Any program I make, works fine, but when I put either getch(), cbreak(), or initscr() automatically I get this error message.

    Here's the detailed error message I get:
    Undefined symbols for architecture x86_64:
    "_initscr", referenced from:
    _main in main.o
    "_stdscr", referenced from:
    _main in main.o
    "_wgetch", referenced from:
    _main in main.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    Process terminated with status 1 (0 minute(s), 0 second(s))
    0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
    Last edited by thomasak; 3 Weeks Ago at 10:44 AM.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,484
    Well you also need to link with the library as well.

    clang prog.c -lncurses
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Nov 2018
    Location
    Amberg in upper palatinate, Bavaria
    Posts
    27
    1-I don't know how to make C understand that I want it to take into account a button I pressed without requiring ENTER.

    For Linux i found this little Program:
    Code:
    /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
    /*
     * main.cc
     * 
     * chkkeystroke is free software: you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the
     * Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * 
     * chkkeystroke is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License along
     * with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/select.h>
    #include <termios.h>
    
    struct termios orig_termios;
    
    void reset_terminal_mode()
    {
        tcsetattr(0, TCSANOW, &orig_termios);
    }
    
    void set_conio_terminal_mode()
    {
        struct termios new_termios;
    
        /* take two copies - one for now, one for later */
        tcgetattr(0, &orig_termios);
        memcpy(&new_termios, &orig_termios, sizeof(new_termios));
    
        /* register cleanup handler, and set the new terminal mode */
        atexit(reset_terminal_mode);
        cfmakeraw(&new_termios);
        tcsetattr(0, TCSANOW, &new_termios);
    }
    
    int kbhit()
    {
        struct timeval tv = { 0L, 0L };
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(0, &fds);
        return select(1, &fds, NULL, NULL, &tv);
    }
    
    
    
    int main(int argc, char *argv[])
    {
        set_conio_terminal_mode();
    
        while (!kbhit()) {
            printf("XX");
        }
        
    return EXIT_SUCCESS;
        
    }
    If you want to have a source code for getch may
    be you can try thomething like this:
    Code:
    /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
    /*
     * main.c
     * Copyright (C) 2018 Josef Wismeth <josef@localhost>
     * 
     * getchtest is free software: you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the
     * Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * 
     * getchtest is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License along
     * with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    
    int getch(){
        struct termios oldt, newt;
        int ch;
        tcgetattr( STDIN_FILENO, &oldt );
        newt = oldt;
        newt.c_lflag &= ~( ICANON | ECHO );
        tcsetattr( STDIN_FILENO, TCSANOW, &newt );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
        return ch;
    }
    
    void clpuf(void)
     {
     while (getc(stdin) != '\n')
        ;
     }
    
    
    int main()
    {
     union scas
     {
      int des;
      unsigned short words[2];    
     };
    
      printf("Scantest\nPlease press a key: ");
      sa.des = getch();
      printf("Als int: %d", sa.des);    
      printf("Als short: %d  %d", sa.words[0] ,sa.words[1]);    
        return (0);
    }
    may be yo can write thomething like sthis here:
    Code:
    #ifndef GETCH_H_INCLUDED
    #define GETCH_H_INCLUDED
    
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h> //for new version of kbhit
    //#include <sys/time.h> old version
    
    /// reads from keypress, doesn't echo
    int getch(){
        struct termios oldt, newt;
        int ch;
        tcgetattr( STDIN_FILENO, &oldt );
        newt = oldt;
        newt.c_lflag &= ~( ICANON | ECHO );
        tcsetattr( STDIN_FILENO, TCSANOW, &newt );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
        return ch;
    }
    
    void clpuf(void)
     {
     while (getc(stdin) != '\n')
        ;
     }
    
       /// reads from keypress, echoes
    int getche(void)
        {
        struct termios oldattr, newattr;
        int ch;
        tcgetattr( STDIN_FILENO, &oldattr );
        newattr = oldattr;
        newattr.c_lflag &= ~( ICANON );
        tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
        return ch;
        }
    /*old: 
    
    // braucht Bestätigung mit Enter-Taste
    long kbhit(void)
    {
    struct timeval tv;
    fd_set read_fd;
    
    tv.tv_sec=0;
    tv.tv_usec=0;
    FD_ZERO(&read_fd);
    FD_SET(0,&read_fd);
    
    if(select(1, &read_fd, NULL, NULL, &tv) == -1)
    return 0;
    
    if(FD_ISSET(0,&read_fd))
     return 1;
    
    return 0;
    } 
    */
    
    // braucht keine Bestätigung mit Enter-Taste
    int kbhit(void)
    {
      struct termios oldt, newt;
      int ch;
      int oldf;
     
      tcgetattr(STDIN_FILENO, &oldt);
      newt = oldt;
      newt.c_lflag &= ~(ICANON | ECHO);
      tcsetattr(STDIN_FILENO, TCSANOW, &newt);
      oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
      fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
     
      ch = getchar();
     
      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
      fcntl(STDIN_FILENO, F_SETFL, oldf);
     
      if(ch != EOF)
      {
        ungetc(ch, stdin);
        return 1;
      }
     
      return 0;
    }
    #endif // GETCH_H_INCLUDED

    This examples were written on SUSE Linux tumbleweed with Anjuta 3.28.0
    and gcc (SUSE Linux) 9.2.1 20190903 [gcc-9-branch revision 275330]

    I hope you can take it also for your sytem

  7. #7
    Registered User
    Join Date
    Oct 2019
    Posts
    14

    Thank you rusyoldguy

    Thank you very much indeed! You intended to solve my problem 1 and you did, but unknowingly you also solved my problem 2. All I needed was the last kbhit function in your last code (3rd). As a matter of example here is my code.
    Code:
    #ifndef GETCH_H_INCLUDED
    #define GETCH_H_INCLUDED
    
    
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    
    int ch;
    unsigned long wait=0;
    
    
    int kbhit(void)
    {
      struct termios oldt, newt;
      int oldf;
    
    
      tcgetattr(STDIN_FILENO, &oldt);
      newt = oldt;
      newt.c_lflag &= ~(ICANON | ECHO);
      tcsetattr(STDIN_FILENO, TCSANOW, &newt);
      oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
      fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
    
    
      ch = getchar();
    
    
      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
      fcntl(STDIN_FILENO, F_SETFL, oldf);
    
    
      if(ch != EOF)
      {
        ungetc(ch, stdin);
        return 1;
      }
    
    
      return 0;
    }
    #endif // GETCH_H_INCLUDED
    
    
    
    
    
    
    int main(int argc, char *argv[])
    {
        while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
    
    
    }

    I just have to use clock() that I know how to do and it will not pause since calculating is being made while I wait for a keyboard hit. So really thank you very much indeed, days of frustration are over.

    CASE CLOSED

  8. #8
    Registered User
    Join Date
    Oct 2019
    Posts
    14

    Unhappy back to 0....

    Oh no I have to reopen this. In reality, in the middle of the program, it only works ONCE.... So I can't press another single character during the rest of the whole program.The program above for example if copied and pasted twice doesn't work... (code before main exactly as above):

    Code:
    int main(int argc, char *argv[])
    {
        while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
     
     while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
    
     
    }
    So with this code, when I press space only once, it prints the phrase "you typed space" twice and program is terminated. It doesn't take into account that I put kbhit() a second time... I am back to phase 1.
    Last edited by Salem; 3 Weeks Ago at 11:10 AM. Reason: codes are NOT tables

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,484
    Well ch is an undeclared and uninitialised variable in your code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    @Salem I have specified above that the code presented in my message is the exact same as in the previous message before main(). There it is if you like:

    Code:
    #ifndef GETCH_H_INCLUDED
    #define GETCH_H_INCLUDED
    
    
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    
    int ch;
    unsigned long wait=0;
    
    
    int kbhit(void)
    {
      struct termios oldt, newt;
      int oldf;
    
    
      tcgetattr(STDIN_FILENO, &oldt);
      newt = oldt;
      newt.c_lflag &= ~(ICANON | ECHO);
      tcsetattr(STDIN_FILENO, TCSANOW, &newt);
      oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
      fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
    
    
      ch = getchar();
    
    
      tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
      fcntl(STDIN_FILENO, F_SETFL, oldf);
    
    
      if(ch != EOF)
      {
        ungetc(ch, stdin);
        return 1;
      }
    
    
      return 0;
    }
    #endif // GETCH_H_INCLUDED
     
    
    int main(int argc, char *argv[])
    {
        while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
      
     while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
     
      
    }



  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,484
    Your use of global variables is awful.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    Does anybody has a solution? Even getchar, scanf, getc do not work twice in the same program!! it's impossible to use one of these twice in a program!

  13. #13
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    Ok, I solved my problem after almost 15 hours of frustration with an expression found on a forum to clear input buffer:
    Code:
    fseek(stdin,0,SEEK_END);

    So correcting the code above in my last message would be:
    Code:
    int main(int argc, char *argv[])
    {
        while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
    Code:
    fseek(stdin,0,SEEK_END);
    
     while (!kbhit())
        {
            wait++;
        }
        if (ch==' ') printf ("you typed space \n");
        if (ch=='\n') printf ("you typed enter\n");
     
      
    }
    


    Hope this will be useful for those who will visit this page asking the same question. Reading previous messages is
    crucial to understand this solution.
    Thank you for everybody who participated here.
    The 2 codes above are one code. I just don't understand why I can't post it here on the same code

    CASE CLOSED.
    Last edited by thomasak; 2 Weeks Ago at 02:08 AM.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,484
    I'm pretty sure that seeking to the end of the stream might well clear the input stream for you, but such behaviour isn't guaranteed by the standard.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Registered User
    Join Date
    Oct 2019
    Posts
    14
    Quote Originally Posted by Salem View Post
    I'm pretty sure that seeking to the end of the stream might well clear the input stream for you, but such behaviour isn't guaranteed by the standard.
    Yes but it's working perfectly. I spent almost 2 weeks to solve this simple problem and now it's solved. perhaps the guaranteed standard would be using cbreak() but after spending long hours trying to figure out how they work I couldn't. It just doesn't work, even when I try to initiate the <curses.h>

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Trying to create a simple array program
    By cyberjupiter in forum C Programming
    Replies: 23
    Last Post: 09-24-2017, 09:47 PM
  2. Replies: 22
    Last Post: 09-03-2013, 12:20 PM
  3. create a simple program using linked list
    By tillu in forum C++ Programming
    Replies: 1
    Last Post: 08-31-2011, 12:53 AM
  4. create a dll for C++ simple program and call from VB
    By motiz in forum C++ Programming
    Replies: 1
    Last Post: 01-09-2008, 04:54 AM
  5. Brainf#@k: an impossible program?
    By cerin in forum Tech Board
    Replies: 4
    Last Post: 04-25-2007, 07:36 PM

Tags for this Thread