Thread: My first process program...

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    55

    My first process program...

    I looked up how to do this on a tutorial that used Code::Blocks, and it indeed works with my compilier without any errors or warnings I normally get with most Win32 API progams, but there are a few issues I would like to address here before I start doing this in some of my bigger projects.

    First Problem : I would like to get input in thread 1 WITHOUT pressing enter, and in this case, getch() did not do the trick. Is there any fairly simple way I could do this so I don't have to make the thread 2 ouput look funny? ( I plan to use multiple threads if I ever make console games in C, so it will be useful to know how to do that later on also)

    Second Problem : My macros for testing the system NORMALLY work, but when I tested this for the first time on a Windows XP professional edition it failed to clear the screen with the system command for windows as I wanted it to. Is there anyway to do this more reliably for both linux and windows?

    Note : ( I NORMALLY use a Windows 7 computer or an older Windows XP at my home. )


    Code:
    #include <process.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    
    #ifdef linux
    #define system LINUX
    #elifdef _WIN32
    #define system WINDOWS
    #elifdef _WIN64
    #define system WINDOWS
    #endif // linux
    
    
    
    
    int CLR(void);
    
    
    void GetInput(void *param)
    {
        char UserCommand;
    
    
        do
        {
            UserCommand = getchar();
        } while (tolower(UserCommand) != 'q');
    
    
        exit(EXIT_SUCCESS);
    
    
        _endthread();
    }
    
    
    void PrintOutput(void *param)
    {
        int o;
    
    
        for ( o = 0; o<INFINITE; o++ )
        {
            printf("Woohoo!");
    
    
            CLR();
    
    
            Sleep(1000);
        }
    
    
        _endthread();
    }
    
    
    int main()
    {
        HANDLE loop_thread[2]; // Declares an array for 2 processes
    
    
        loop_thread[0] = (HANDLE) _beginthread( GetInput, 0, NULL ); // Begins thread 1
        if ( loop_thread[0] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Exits with a failure if thread
                                                                        // was not created properly
        loop_thread[1] = (HANDLE) _beginthread( PrintOutput, 0, NULL ); // Begins thread 2
        if ( loop_thread[1] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Same error as bfore
    
    
        WaitForMultipleObjects(2, loop_thread, TRUE, INFINITE); // Wait for the threads to complete before exiting with 0
    
    
        return 0;
    }
    
    
    int CLR( void )
    {
        #ifdef system
    
    
        #if system == WINDOWS
        system("cls");
        #endif
    
    
        #if system == LINUX
        system("clear");
        #endif
    
    
        #endif // system
    
    
        #ifndef system
        return 1;
        #endif // system
    }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    For windows I would recommend using the Windows API calls instead of the system call. See this link: Clearing the Screen.

    For Linux depending on your "terminal" you may be able to use escape sequences to clear the terminal, or you may need to use the curses library, or possibly the termio functions.

    Jim

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    You have several problems with your preprocessing directives:

    Code:
    #include <process.h>
    #include <windows.h>
    Both headers are specific to Windows thus you need to guard their inclusion like
    Code:
    #ifdef _WIN32
    #include <process.h>
    #include <windows.h>
    #endif
    Code:
    #ifdef linux
    #define system LINUX
    #elifdef _WIN32
    #define system WINDOWS
    #elifdef _WIN64
    #define system WINDOWS
    #endif // linux
    "#elifdef" is not a standard preprocessor directive. You probably mean "#elif defined"

    Another problem is that you are "shadowing" the system() function if you do something like "#define system LINUX".
    You later have
    Code:
    system("cls");
    in your code which the preprocessor will change to
    Code:
    LINUX("cls");
    Bye, Andreas

  4. #4
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    I *fixed* the code taking the comments above into consideration, I also decided to make it a windows only program. This would make it easier to focus on one thing and be better for me since I only use windows computers anyways, and have no idea how most other computers that aren't windows basically work. There are still some questions I have that are left and that haven't been answered though.

    1 : Why do the threads I start require a void * param. When I think of a void pointer, usually I think of something that can hold any value, but if that is true, is it just a value you can pass locally to a thread?

    2 : I still would like it to be able to get input in the first thread without pressing the RETURN key( ENTER key, whatever name you like to call it ). Yes, I know there is documentation for it in the FAQ, but the win32 API one is made for C++, not C.

    I thank you for your help so far!


    Code:
    #ifdef _WIN32
    #define SYSTEM WINDOWS
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <process.h>
    #include <windows.h>
    #endif // _WIN32
    #ifdef linux
    #define SYSTEM LINUX
    printf("Linux is not supported in this program!");
    exit(EXIT_FAILURE);
    #endif // linux
    #ifndef SYSTEM
    printf("You are using a invalid computer for this program!");
    exit(EXIT_FAILURE);
    #endif // SYSTEM
    void cls( HANDLE hConsole );
    void clearstdinbffr(void);
    void GetInput(void *param)
    {
        char UserCommand;
        do
        {
            scanf("%1c", &UserCommand);
            clearstdinbffr();
        } while (tolower(UserCommand) != 'q');
        exit(EXIT_SUCCESS);
        _endthread();
    }
    void PrintOutput(void *param)
    {
        int o;
        HANDLE hStdout;
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
        for ( o = 0; o<INFINITE; o++ )
        {
            printf("Woohoo!");
            Sleep(1000);
            cls(hStdout);
        }
        _endthread();
    }
    int main() // <------------------ Main entry point is here
    {
        HANDLE loop_thread[2]; // Declares an array for 2 threads
        loop_thread[0] = (HANDLE) _beginthread( GetInput, 0, NULL ); // Begins thread 1
        if ( loop_thread[0] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Exits with a failure if thread
                                                                        // was not created properly
        loop_thread[1] = (HANDLE) _beginthread( PrintOutput, 0, NULL ); // Begins thread 2
        if ( loop_thread[1] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Same error as bfore
        WaitForMultipleObjects(2, loop_thread, TRUE, INFINITE); // Wait for the threads to complete before exiting with 0
        return 0;
    }
    void cls( HANDLE hConsole ) // Credit for this function goes to Microsoft's website's help section here :
    {                           // Clearing the Screen (Windows)
    
       COORD coordScreen = { 0, 0 };    // home for the cursor
       DWORD cCharsWritten;
       CONSOLE_SCREEN_BUFFER_INFO csbi;
       DWORD dwConSize;
    // Get the number of character cells in the current buffer.
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
       dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
       // Fill the entire screen with blanks.
       if( !FillConsoleOutputCharacter( hConsole,        // Handle to console screen buffer
                                        (TCHAR) ' ',     // Character to write to the buffer
                                        dwConSize,       // Number of cells to write
                                        coordScreen,     // Coordinates of first cell
                                        &cCharsWritten ))// Receive number of characters written
       {
          return;
       }
       // Get the current text attribute.
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
       // Set the buffer's attributes accordingly.
       if( !FillConsoleOutputAttribute( hConsole,         // Handle to console screen buffer
                                        csbi.wAttributes, // Character attributes to use
                                        dwConSize,        // Number of cells to set attribute
                                        coordScreen,      // Coordinates of first cell
                                        &cCharsWritten )) // Receive number of characters written
       {
          return;
       }
       // Put the cursor at its home coordinates.
       SetConsoleCursorPosition( hConsole, coordScreen );
    }
    void clearstdinbffr(void) { int c = ' '; while((c = getchar()) != '\n' && c != EOF); }

  5. #5
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    Made a mistake in the new code that I realized now, here is the new code.

    Code:
    #define SYSTEM WINDOWS
    
    
    #include <process.h>
    #include <windows.h>
    
    
    #else
    printf("You are using a invalid computer for this program!");
    exit(EXIT_FAILURE);
    #endif // _WIN32
    
    
    void cls( HANDLE hConsole );
    void clearstdinbffr(void);
    
    
    void GetInput(void *param)
    {
        char UserCommand;
    
    
        do
        {
            scanf("%1c", &UserCommand);
            clearstdinbffr();
    
    
        } while (tolower(UserCommand) != 'q');
    
    
        exit(EXIT_SUCCESS);
    
    
        _endthread();
    }
    
    
    void PrintOutput(void *param)
    {
        int o;
    
    
        HANDLE hStdout;
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    
    
        for ( o = 0; o<INFINITE; o++ )
        {
            printf("Woohoo!");
            Sleep(1000);
            cls(hStdout);
        }
    
    
        _endthread();
    }
    
    
    int main() // <------------------ Main entry point is here
    {
        HANDLE loop_thread[2]; // Declares an array for 2 processes
    
    
        loop_thread[0] = (HANDLE) _beginthread( GetInput, 0, NULL ); // Begins thread 1
        if ( loop_thread[0] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Exits with a failure if thread
                                                                        // was not created properly
        loop_thread[1] = (HANDLE) _beginthread( PrintOutput, 0, NULL ); // Begins thread 2
        if ( loop_thread[1] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Same error as bfore
    
    
        WaitForMultipleObjects(2, loop_thread, TRUE, INFINITE); // Wait for the threads to complete before exiting with 0
    
    
        return 0;
    }
    
    
    void cls( HANDLE hConsole ) // Credit for this function goes to Microsoft's website's help section here :
    {                           // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682022%28v=vs.85%29.aspx
    
    
    
    
       COORD coordScreen = { 0, 0 };    // home for the cursor
       DWORD cCharsWritten;
       CONSOLE_SCREEN_BUFFER_INFO csbi;
       DWORD dwConSize;
    
    
    // Get the number of character cells in the current buffer.
    
    
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
    
    
       dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
    
    
       // Fill the entire screen with blanks.
    
    
       if( !FillConsoleOutputCharacter( hConsole,        // Handle to console screen buffer
                                        (TCHAR) ' ',     // Character to write to the buffer
                                        dwConSize,       // Number of cells to write
                                        coordScreen,     // Coordinates of first cell
                                        &cCharsWritten ))// Receive number of characters written
       {
          return;
       }
    
    
       // Get the current text attribute.
    
    
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
    
    
       // Set the buffer's attributes accordingly.
    
    
       if( !FillConsoleOutputAttribute( hConsole,         // Handle to console screen buffer
                                        csbi.wAttributes, // Character attributes to use
                                        dwConSize,        // Number of cells to set attribute
                                        coordScreen,      // Coordinates of first cell
                                        &cCharsWritten )) // Receive number of characters written
       {
          return;
       }
    
    
       // Put the cursor at its home coordinates.
    
    
       SetConsoleCursorPosition( hConsole, coordScreen );
    
    
    }
    
    
    void clearstdinbffr(void) { int c = ' '; while((c = getchar()) != '\n' && c != EOF); }

  6. #6
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    Sorry again, please add these headers to that program in the above post at the very top :

    Code:
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>

  7. #7
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    #ifdef _WIN32
    #define SYSTEM WINDOWS
    Why do you want to define a new macro when "_WIN32" already does what you need (conditional compilation)?

    Code:
    #ifdef linux
    #define SYSTEM LINUX
    printf("Linux is not supported in this program!");
    exit(EXIT_FAILURE);
    #endif // linux
    The macro "linux" for a Linux system is outdated and not conforming to the C standard. You should rather use "__linux" or "__linux__".
    Additionally this part is just plain wrong. Assuming "linux" is defined you would execute code outside of any function which isn't possible in C. Furthermore printf() and exit() wouldn't be declared properly because you didn't include the headers for them.

    Quote Originally Posted by BatchProgrammer View Post
    1 : Why do the threads I start require a void * param. When I think of a void pointer, usually I think of something that can hold any value, but if that is true, is it just a value you can pass locally to a thread?
    First, a pointer to void (like any other pointer) can just have an address as its value and not "any value". Furthermore, a pointer to void just points to a raw memory address without any type information.
    In your case this allows you to pass a pointer to an object of any type to the thread starting function.

    Quote Originally Posted by BatchProgrammer View Post
    2 : I still would like it to be able to get input in the first thread without pressing the RETURN key( ENTER key, whatever name you like to call it ). Yes, I know there is documentation for it in the FAQ, but the win32 API one is made for C++, not C.
    You should ask in the Windows forum for a solution if you are not able to convert the code to C.

    Bye, Andreas

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Use this to figure out what #defines to use to detect your OS/Compiler.
    Pre-defined Compiler Macros / Wiki / Home
    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.

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    Quote Originally Posted by AndiPersti View Post
    Code:
    #ifdef _WIN32
    #define SYSTEM WINDOWS
    Why do you want to define a new macro when "_WIN32" already does what you need (conditional compilation)?

    Code:
    #ifdef linux
    #define SYSTEM LINUX
    printf("Linux is not supported in this program!");
    exit(EXIT_FAILURE);
    #endif // linux
    The macro "linux" for a Linux system is outdated and not conforming to the C standard. You should rather use "__linux" or "__linux__".
    Additionally this part is just plain wrong. Assuming "linux" is defined you would execute code outside of any function which isn't possible in C. Furthermore printf() and exit() wouldn't be declared properly because you didn't include the headers for them.
    I know that in my later replies I fixed it, I'll just post it again I guess ( this time hopefully correctly) :

    Code:
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int IsWindows = 1;
    
    
    #ifdef _WIN32
    #include <process.h>
    #include <windows.h>
    #else
    IsWindows = 0;
    #endif // _WIN32
    
    
    void cls( HANDLE hConsole );
    void clearstdinbffr(void);
    
    
    void GetInput(void *param)
    {
        char UserCommand;
    
    
        do
        {
            scanf("%1c", &UserCommand);
            clearstdinbffr();
    
    
        } while (tolower(UserCommand) != 'q');
    
    
        exit(EXIT_SUCCESS);
    
    
        _endthread();
    }
    
    
    void PrintOutput(void *param)
    {
        int o;
    
    
        HANDLE hStdout;
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    
    
        for ( o = 0; o<INFINITE; o++ )
        {
            printf("Woohoo!");
            Sleep(1000);
            cls(hStdout);
        }
    
    
        _endthread();
    }
    
    
    int main() // <------------------ Main entry point is here
    {
        if (!IsWindows) {return 1;}
    
    
        HANDLE loop_thread[2]; // Declares an array for 2 processes
    
    
        loop_thread[0] = (HANDLE) _beginthread( GetInput, 0, NULL ); // Begins thread 1
        if ( loop_thread[0] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Exits with a failure if thread
                                                                        // was not created properly
        loop_thread[1] = (HANDLE) _beginthread( PrintOutput, 0, NULL ); // Begins thread 2
        if ( loop_thread[1] == INVALID_HANDLE_VALUE ) exit( EXIT_FAILURE ); // Same error as bfore
    
    
        WaitForMultipleObjects(2, loop_thread, TRUE, INFINITE); // Wait for the threads to complete before exiting with 0
    
    
        return 0;
    }
    
    
    void cls( HANDLE hConsole ) // Credit for this function goes to Microsoft's website's help section here :
    {                           // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682022%28v=vs.85%29.aspx
    
    
    
    
       COORD coordScreen = { 0, 0 };    // home for the cursor
       DWORD cCharsWritten;
       CONSOLE_SCREEN_BUFFER_INFO csbi;
       DWORD dwConSize;
    
    
    // Get the number of character cells in the current buffer.
    
    
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
    
    
       dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
    
    
       // Fill the entire screen with blanks.
    
    
       if( !FillConsoleOutputCharacter( hConsole,        // Handle to console screen buffer
                                        (TCHAR) ' ',     // Character to write to the buffer
                                        dwConSize,       // Number of cells to write
                                        coordScreen,     // Coordinates of first cell
                                        &cCharsWritten ))// Receive number of characters written
       {
          return;
       }
    
    
       // Get the current text attribute.
    
    
       if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
       {
          return;
       }
    
    
       // Set the buffer's attributes accordingly.
    
    
       if( !FillConsoleOutputAttribute( hConsole,         // Handle to console screen buffer
                                        csbi.wAttributes, // Character attributes to use
                                        dwConSize,        // Number of cells to set attribute
                                        coordScreen,      // Coordinates of first cell
                                        &cCharsWritten )) // Receive number of characters written
       {
          return;
       }
    
    
       // Put the cursor at its home coordinates.
    
    
       SetConsoleCursorPosition( hConsole, coordScreen );
    
    
    }
    
    
    void clearstdinbffr(void) { int c = ' '; while((c = getchar()) != '\n' && c != EOF); }

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    I also decided to make it a windows only program.
    You said you will only be using Windows, then why even worry about some other operating system? Just get rid of all the conditionals.

    Also look at this snippet:

    Code:
    void GetInput(void *param)
    {
        char UserCommand;
     
        do
        {
            scanf("%1c", &UserCommand);
            clearstdinbffr();
        } while (tolower(UserCommand) != 'q');
     
     
        exit(EXIT_SUCCESS);
      
        _endthread();
    }
    Do you realize that that last line will never be executed?

    Jim

  11. #11
    Registered User
    Join Date
    Jan 2013
    Posts
    55
    Removed the #ifdef _WIN32 and the other macros, since I kept messsing it up, and I guess I'll just keep it simple for now.


    Code:
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <process.h>
    #include <windows.h>
    
    
    void cls( HANDLE hConsole );
    void clearstdinbffr(void);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. block program from seeing process tree
    By klmdb in forum C# Programming
    Replies: 6
    Last Post: 12-08-2011, 05:00 AM
  2. Executing java program as a separate process from C
    By arka.sharma in forum C Programming
    Replies: 5
    Last Post: 09-09-2011, 04:05 AM
  3. C program for Inter Process communication ( Tx and RX)
    By hiharsh in forum C Programming
    Replies: 3
    Last Post: 05-03-2007, 10:23 AM
  4. have to program to get process ID?
    By George2 in forum Tech Board
    Replies: 12
    Last Post: 08-23-2006, 10:13 AM
  5. How to make a program that runs in the process
    By Makoy in forum Windows Programming
    Replies: 12
    Last Post: 12-20-2004, 10:19 AM

Tags for this Thread