PDA

View Full Version : just a quick "hello world!" before I start asking questions.



PaulS
09-22-2014, 12:17 AM
I used to write some C code back in the 1980s but I haven't done much of anything with C since windoze took over my computers.

I am fairly new to Linux (Ubuntu) and have the bug to start programming in ANSI C. It is a new challenge but I like it. I am set up with the header files and I got a new list of the keywords and am beginning my second career by recoding an old program that I wrote using Turbo C from Borland. I am using the Geany IDEand am faily comfortable with it but it seems I have forgotton just about everything I thought I knew.

I used to use Getch() to get keystroke input but I guess it is gone from the "new" ANSI C. Is their an easy way around it without going beyond the ANSI coding?

If not I will deal with the extra <enter> keystroke.

I am having fun with it at 64 years old but it is going to be a rough learning curve.

So, hello world, and I'll be back.

Paul

Salem
09-22-2014, 01:41 AM
Welcome to the forum!.

All input in ANSI C is line buffered by default, so it's hard to get away from the need to press enter.

FAQ - Cprogramming.com (http://faq.cprogramming.com/cgi-bin/smartfaq.cgi) has some methods for simulating getch() in a Linux environment, which would allow your program to be 'mostly' ANSI-C rather than 'purely' ANSI-C.

grumpy
09-22-2014, 03:10 AM
I used to use Getch() to get keystroke input but I guess it is gone from the "new" ANSI C. Is their an easy way around it without going beyond the ANSI coding?


getch() was never part of the "old" (as in pre-ANSI) C either. It was supported by some vendors as an extension, either in the library supplied by compiler vendors or as a third-party library function.

If you were writing programs that relied on directly receiving keyboard input, you were already going beyond ANSI coding. That has not changed.

ANSI C is also old. The original 1989 ANSI C standard was adopted by ISO in 1990 without modification of content (except for some editorial topping/tailing/formatting). So you will see "ANSI C" referred to as "ISO C", with the shorthand of either C89 or C90. Things haven't stood still though .... ISO ratified an update of the C standard in 1999 (fixing flaws in C89/C90 and adding features) - shorthand C99 - and another update in 2011, which you might see referred to C11.


C99 is backward compatible to the earlier standard, but has more useful features and is more strictly specified (so a C99 compiler will pick up coding problems that will float merrily past a C89 compiler without complaint). If you are going to be relearning C anyway, I would suggest going for C99 or later.

And, please, find a more recent compiler than Turbo C. Turbo C was a good product for its day, but is woefully obsolete now. And more modern compilers are freely available.

PaulS
09-22-2014, 12:43 PM
getch() was never part of the "old" (as in pre-ANSI) C either. It was supported by some vendors as an extension, either in the library supplied by compiler vendors or as a third-party library function.

If you were writing programs that relied on directly receiving keyboard input, you were already going beyond ANSI coding. That has not changed.

ANSI C is also old. The original 1989 ANSI C standard was adopted by ISO in 1990 without modification of content (except for some editorial topping/tailing/formatting). So you will see "ANSI C" referred to as "ISO C", with the shorthand of either C89 or C90. Things haven't stood still though .... ISO ratified an update of the C standard in 1999 (fixing flaws in C89/C90 and adding features) - shorthand C99 - and another update in 2011, which you might see referred to C11.


C99 is backward compatible to the earlier standard, but has more useful features and is more strictly specified (so a C99 compiler will pick up coding problems that will float merrily past a C89 compiler without complaint). If you are going to be relearning C anyway, I would suggest going for C99 or later.

And, please, find a more recent compiler than Turbo C. Turbo C was a good product for its day, but is woefully obsolete now. And more modern compilers are freely available.

Grumpy,
I haven't touched Turbo C for about 30 years and I wasn't writing ANSI code back then. I was writing for DOS and using all the platform specific coding I could. I am using Geany as my IDE. and have gotten warnings about C99 code - like it is not supported?? I am sure that I was using syntax that it didn't like but that was corrected. I tend to behave like a terrier once I get ahold on something.
It was not hard to find the list of ANSI header files with the functuions listed and syntax provided - if I change to C11 or C99 where do I find the changes / additions? As popular as C was / is, one would expect to be able to find decent documentation on the latest version.

PaulS
09-22-2014, 12:53 PM
Salem,
Thanks for the welcome and your confirmation.
I don't want to write code that can't be ported to different OS's and platforms. That is why I am limiting my coding to ANSI standards. I have solved the easy problem of clearing the screen with a simple "for" loop.
The software I am rewriting used mode changes, graphics and special fonts. If I decide to attempt to dress up the software I may have to use some "extensions" and work them out for each platform as "#define" code but I would like to stay away from that as much as possible.
This is a labor intensive process - converting an old Turbo C code to ANSI standard - and I think it is going to be more cumbersome for the user but with the improvements I want to add it will be a much better product when I am done.

c99tutorial
09-22-2014, 02:34 PM
I am using Geany as my IDE. and have gotten warnings about C99 code - like it is not supported??

Probably you may need to add some switch to the compiler (probably gcc) to get it to recognize the flavour you are using, e.g. -std=gnu99 or -std=c99. Also it's good to turn on warnings with -Wall to get the full diagnostics.

PaulS
09-25-2014, 12:15 AM
C99tutorial,
I am a bit new to Ubuntu and old and forgetful. Just how would I go about "adding a switch" to Geany? How can I set the IED (Geany) to turn on all warnings and errors?
You see I seem to have already run into a problem with this as I added a second struct to set up a new menu and get new input but even though it compiled withourt errors or warnings when I try to get to the second struct it locks up the terminal window. It was bad enough that after an hour I gave up and powered down to get out.

Paul

PaulS
09-25-2014, 04:22 PM
I looked over all the check boxes and settings in Geany to find that "-wall" is on and as near as I can tell it is set up for ANSI C. Now I need some help with this code:



// ExtBal6.c
// the <ESC> key exits the program until I get the ender func complete

// Preprossesor comands ***********************************************
#include <stdio.h>
// #include <math.h> I will need this later but not for now
// #include <stdlib.h> I will need this later but not for now


// Prototypes ************************************************** *******
int mainmenu(void);
int ballistics (void);
//int openfile(void); not done
//int newrecord(void); not done
//int lprint(int); not done
//int ender(void; not done

// Global variables ************************************************** *
int chois; //used to return values from functions


// structures defined *************************************************

// program code begins ************************************************
int main(void)
{
do
{ // do - while loop begins
switch(mainmenu()) //put up main menu and return
{ // switch begins
case 49: // 1
case 66: // B
case 98: // b
ballistics(); // ballistic struct
break;
case 50: // 2
case 79: // O (as in Oscar)
case 111: // o (as in oscar)
//openfile(); // open existing record
break;
case 51: // 3
case 78: // N
case 110: // n
//newrecord(); // enter new record
break;
case 52: // 4
case 80: // P
case 112: // p
//lprint(); // print current record
break;
case 53: // 5
case 70: // F
case 102: // f
//lprint(); // print a range form (blank record form)
break;
case 54: // 6
case 81: // Q
case 113: // q
//ender(); // prepare to end program (clean up and clear screen)
// chois made to equal 27
break;
default:
printf("\a"); // sound alert and continue the switch
} // switch ends

} // do - while loop ends
while (chois != 27); // while <ESC> is not used continue loop

return(0);
} // Main ends


// Functions ************************************************** ********

// Main menu ************************************************** ********
int mainmenu(void)
{
int i;
for (i = 0; i < 100; i++) // clear screen with 100 blank lines
{
printf(" \n");
} // screen is now cleared
// put up the menu
printf("\n\n\n\n\t\t\t\t Main Menu \n\n");
printf("\t\t\t 1. run Ballistics \n");
printf("\t\t\t 2. Open existing record \n");
printf("\t\t\t 3. enter New record \n");
printf("\t\t\t 4. Print record \n");
printf("\t\t\t 5. print range Form \n");
printf("\t\t\t 6. Quit \n");
printf("\n\t\t Enter your NUMBER or LETTER choice: ");
chois = getchar(); // get the letter or number from user
return(chois); // return value to main in the global "chois"
}

// Main Menu ends ************************************************** ***


// Balistics computations and output begins****************************
int ballistics(void)
{
int i; // used in clear screen for loop
int select; // selection from menu
chois = 0; // reset the value of global chois to zero
for (i = 0; i < 100; i++); // clear screen
{
printf(" \n");
} // screen is cleared
printf("\n\n\n\n\t\t\t\t Ballistics Menu \n\n"); // write menu
printf("\t\t\t 1. use record data \n");
printf("\t\t\t 2. enter fresh data \n");
printf("\t\t\t 3. return to Main Menu \n");
printf("\t\t\t 4. quit \n\n");
printf("\t\t enter your NUMBER choice: ");
select = getchar(); // get number selection
do
{
switch(select) // switch begins - use selection in switch
{
case 49:
case 50:
case 51: // if value is 1, 2, or 3
printf(" success on 1 - 3 selection\n");
chois = 1; // assign global chois to previous value
break;
case 52: // if the value is 4
chois = 27; // assign global chois to <ESC>
break;
default:
printf("\a"); // sound the alert and continue the switch
} // switch ends
}
while(select != 27);
return(chois); // send chois back to main switch
}

// ballitics function ends ********************************************



I comment out the "ballistic" dummy function and the declarations and calls and the first menu seems to work fine (right now the only way to exit is with the <ESC> key) . The problem occurs when I compile and run the program with the ballistics fuction enabled. The program compiles with no errors or warnings but when I run it choosing to go to ballistics causes the system to lock up. It doesn't clear the screen or print the second menu, so I think the problem is in the calling routine but I can't see it. There is no way to get out unless you can shut down the terminal window. If you waste a lot of time hitting keys it seems to take all the power of my quad processor and I can't even move the mouse. After doing that I waited about an hour for things to "normalize" and then resorted to the BIG RED SWITCH and powered down to get out of the (what appeared to be) an endless loop.

I must have a mistake in the code but it is one that the compiler thinks is alright.
What did I do wrong?

Thank you for your help,
Paul

PaulS
09-25-2014, 05:51 PM
I am wondering if this should go into the "C Programming" forum instead of here.
Although I am programming for Linux this might be better served in the other forum??

If so would one of the good moderators move it for me? (I don't want to start my time here with a double post)

gemera
09-25-2014, 10:25 PM
Yeah it's nothing to worry about too much - essentially the logic of the code takes it into an endless loop in which the "bell" is sounded and while the bell is sounding it cannot be interrupted.

The main problem with your code is that when you use getchar() to get your menu choice, the input buffer also receives the end of line character '\n' when you press the Enter key, so when you go to the ballistics menu the program does not wait for you to input your choice there, instead getchar() just grabs that new line character from the buffer and ,if you follow the logic, the program enters an infinite loop as described above.

The way to avoid this is to flush the input buffer after you use getchar() to read in your menu choice, and that is generally done like this:




int ch;

while((ch = getchar()) != '\n' && ch != EOF)
{
continue;
}



An additional tip, from looking at your code, is that its better not to use "magic numbers" and you can save yourself the need to add comments by directly doing:




case '1':
case 'B':
case 'b':

PaulS
09-26-2014, 12:24 AM
Yeah it's nothing to worry about too much - essentially the logic of the code takes it into an endless loop in which the "bell" is sounded and while the bell is sounding it cannot be interrupted.

The main problem with your code is that when you use getchar() to get your menu choice, the input buffer also receives the end of line character '\n' when you press the Enter key, so when you go to the ballistics menu the program does not wait for you to input your choice there, instead getchar() just grabs that new line character from the buffer and ,if you follow the logic, the program enters an infinite loop as described above.

The way to avoid this is to flush the input buffer after you use getchar() to read in your menu choice, and that is generally done like this:




int ch;

while((ch = getchar()) != '\n' && ch != EOF)
{
continue;
}



An additional tip, from looking at your code, is that its better not to use "magic numbers" and you can save yourself the need to add comments by directly doing:




case '1':
case 'B':
case 'b':



Thank you for pointing the way out.

I will try the steps you point out to clear potential problems but the screen should clear and the menu should print because that happens before the getchar(). None of that happens once "ballistics" is called. It seems to be stuck in the first loop not the second. It is my bedtime so I will get back to you in the morning or after my work is done at the latest.

PaulS
09-27-2014, 09:22 AM
Gemera,
I took your advice to clear the buffer and then rearranged the code a bit to get what I wanted but it still seems to ignore my screen clearing routine. Is this due to the Vterm window or are there more things wrong?



// ExtBal6.c
// the <ESC> key exits the program until I get the ender func complete

// Preprossesor comands ***********************************************
#include <stdio.h>
// #include <math.h> I will need this later but not for now
// #include <stdlib.h> I will need this later but not for now


// Prototypes ************************************************** *******
int mainmenu(void);
int ballistics (void);
//int openfile(void); not done
//int newrecord(void); not done
//int lprint(int); not done
//int ender(void; not done

// Global variables ************************************************** *
int chois; //used to return values from functions


// structures defined *************************************************

// program code begins ************************************************
int main(void)
{
// int ch;
do
{ // do - while loop begins

switch(mainmenu()) //put up main menu and return
{ // switch begins
case 49: // 1
case 66: // B
case 98: // b
ballistics(); // ballistic struct
break;
case 50: // 2
case 79: // O (as in Oscar)
case 111: // o (as in oscar)
//openfile(); // open existing record
break;
case 51: // 3
case 78: // N
case 110: // n
//newrecord(); // enter new record
break;
case 52: // 4
case 80: // P
case 112: // p
//lprint(); // print current record
break;
case 53: // 5
case 70: // F
case 102: // f
//lprint(); // print a range form (blank record form)
break;
case 54: // 6
case 81: // Q
case 113: // q
chois = 27;
//ender(); // prepare to end program (clean up and clear screen)
// chois made to equal 27
break;


} // switch ends

} // do - while loop ends
while (chois != 27); // while <ESC> is not used continue loop

return(0);
} // Main ends


// Functions ************************************************** ********

// Main menu ************************************************** ********
int mainmenu(void)
{
int i;
int ch;

for (i = 0; i < 100; i++) // clear screen with 100 blank lines
{
printf(" \n");
} // screen is now cleared
// put up the menu
printf("\n\n\n\n\t\t\t\t Main Menu \n\n");
printf("\t\t\t 1. run Ballistics \n");
printf("\t\t\t 2. Open existing record \n");
printf("\t\t\t 3. enter New record \n");
printf("\t\t\t 4. Print record \n");
printf("\t\t\t 5. print range Form \n");
printf("\t\t\t 6. Quit \n");
printf("\n\t\t Enter your NUMBER or LETTER choice: ");

chois = getchar(); // get the letter or number from user
while ((ch = getchar()) != '\n' &&ch != EOF)
{
continue;
}
return(chois); // return value to main in the global "chois"
}

// Main Menu ends ************************************************** ***


// Balistics computations and output begins****************************
int ballistics(void)
{
int i; // used in clear screen for loop
int select; // selection from menu
int ch;
chois = 0; // reset the value of global chois to zero


do
{
for (i = 0; i < 100; i++); // clear screen
{
printf(" \n");
} // screen is cleared
printf("\n\n\n\n\t\t\t\t Ballistics Menu \n\n"); // write menu
printf("\t\t\t 1. use record data \n");
printf("\t\t\t 2. enter fresh data \n");
printf("\t\t\t 3. return to Main Menu \n");
printf("\t\t\t 4. quit \n\n");
printf("\t\t enter your NUMBER choice: ");
select = getchar(); // get number selection
while((ch = getchar()) != '\n' && ch != EOF)
{
continue;
}
switch(select) // switch begins - use selection in switch
{
case 49:
case 50:
case 51: // if value is 1, 2, or 3
printf(" success on 1 - 3 selection\n");
chois = 1; // assign global chois to previous value
break;
case 52: // if the value is 4
chois = 27; // assign global chois to <ESC>
break;

} // switch ends

}
while(select !=27 && select !=49 && select !=50 && select !=51 && select !=52);
return(chois); // send chois back to main switch
}


// ballitics function ends ********************************************



Thank you so much for your help.
Is there a more "elegant" way to handle the input from the keyboard?

Paul

gemera
09-27-2014, 12:51 PM
There's a "programming FAQ" link on the menu of the site's home page which should help you.

This is the page for "Clearing the Screen" (http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1031963460&id=1043284385).

Edit: The technique you are using for input is certainly the only one I've seen/used in Standard C for these menu type programs.

Salem
09-27-2014, 11:28 PM
> case 49: // 1
Having been previously shown that you can do
case '1':

Your response of putting // 1 as the comment to the case is frankly bizarre.

> int chois; //used to return values from functions
NO!
The return statement in a function returns the value.
The variable inside the function that is returned can be local to the function.

> for (i = 0; i < 100; i++); // clear screen
Rather than copy/pasting the code, make it a separate function.
So that when you do find a better way (as gemera has hinted the FAQ), it becomes a very simple drop-in replacement.

PaulS
09-28-2014, 02:33 PM
Salem,
I may or may not change the way the different case statements are made - it is an old habit that will take time to change. (I am a little bizaare)

"chois" is a global variable and not local. It makes the code easier for me to follow. I suppose I could return the value of chois but as long as the global is available why not use it?

Gemera,
I changed the "clear screen" to a while loop and it is functioning as it should. I don't understand why the for loop did not clear the screen but it is working now. I will probably convert it to a separate fuction and I might do the same for the input process too.

Thanks for your help and the advice. I might not take the advice right away but if it eats at me long enough I may decide to take the advice.

Thanks,
Paul