Stopwatch program in standard C - c

I'm trying to create a program of a stopwatch using this Standard C-Free 5.0. Here's what I've got so far:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
char button;
int minutes=0, seconds=0, millisec=0;
int main(void)
{
while(1)
{
reset:
button = '\0';
int minutes=0, seconds=0, millisec=0;
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 'a')
{
while(1)
{
cont:
button = '\0';
Sleep(10);
millisec++;
if(millisec == 100)
{
millisec = 0;
seconds++;
if(seconds == 60)
{
seconds = 0;
minutes++;
}
}
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 's')
{
while(1)
{
button = '\0';
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 'a')
{
goto cont;
}
if(button == 'd')
{
goto reset;
}
}
}
}
}
}
}
I'm trying to start the stopwatch with a pressed of button 'a' but it wouldn't work. Using scanf() will pause the whole program. Is there a way to detect a button being pressed and continue the stopwatch program? I mean without pausing the program especially the pressing 's' to stop and pressing 'a' again to continue, while displaying the timer at all times.

This should help _kbhit and it's important to use _getch() after it.
#include <conio.h>
//...
int key;
while (1)
{
if (_kbhit())
{
key = _getch();
if (key == 'a')
printf("You pressed 'a'\n");
else if (key == 'd')
printf("You pressed 'd'\n");
}
}

Since you use system("cls");, this is probably on dos / Windows command prompt. You can try to see if conio.h is supported by your compiler.
If it is, kbhit() or _kbhit() (link to MSDN, you should check docs of your compiler's libraries for most accurate reference) seems to be what you need to use.

This is a system problem not C. In general, your hosting system provide buffering to inputs, so when you press a key, it is not delivered at that time to your program, it is buffered until some condition occurs (basically, an end-of-line is pressed).
Under Windows there is different calls you should make to get a keypress.
Under Unix, you should put your tty in non-canonical mode (there is a set of magic calls to tcgetattr and tcsetattr).
See that one for example

#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>
#include<windows.h>
main()
{
int choice, h,m,s; h=0; m=0; s=0; //--variable declaration--//
char p= 'p';
printf("Press 1 to start the timer\nPress 2 to exit\n");
printf("\nEnter your choice\n");
scanf("%d",&choice);
switch(choice) //--switch case --//
{
case 1:
{
while(1) //--while condition is true//
{
if(s>59) //--if seconds(s) is > 59--//
{
m=m+1; //--increment minute by 1--//
s=0;
}
if(m>59) //--if minutes(s) is > 59--//
{
h=h+1; //--increment hour by 1--//
m=0;
}
if(h>11) //--if hour(h) is > 11--//
{
h=0; //-Hour to 0--//
m=0;
s=0;
}
Sleep(1000); //--inbuilt function for 1sec delay--//
s=s+1;
system("cls"); //--Clear screen--//
printf("DIGITAL CLOCK");
printf("\n\nHOUR:MINUTE:SECOND");
printf("\n\n%d:%d:%d",h,m,s); //--Print time--//
printf("\n\nTo pause : press P\n");
if(kbhit()) //--Check if any button is pressed on keyboard--//
{
if(p==getch()) //--Check if P is pressed--//
{
system("pause"); //--Inbuilt function for pause and resume--//
}
}
}
break;
}
case 2:
exit(0); //--Exit --//
default:
{
printf("Wrong Choice");
}
}
getch(); //--Holding the screen--//
return 0;
}

Related

press q for quit and enter for continue

I have a do-while loop, and I want if I press ENTER key, the progress will continue, but q will finish the program. It is not working as the program will end straight away and does not wait for the user to enter the key.
Code below is my main code.
void displayGrid() {
bool progress = true;
printf("%s", "input round for round mode, moves for move mode");
scanf("%s", input);
toLowerCase(input);
if (strcmp(input, "round") == 0) {
do {
printf("Enter key ENTER to continue,Q for quit \n");
bool qoc = quitOrContinue();
if (qoc) {
} else if (!qoc) {
progress = false;
}
} while (progress);
}
}
This is my code for checking enter and q key:
bool quitOrContinue() {
if (kbhit()) {
char click = fgetc(stdin);
while (getchar() != '\n');
if (click == 0x0A) {
return true;
} else if (click == 'q') {
return false;
}
}
}
You do not need three functions to read a char from stdin.
Here's some psuedo-code to illustrate how to read one char. (I couldn't test it, so there may be some bugs in it).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
static bool quitOrContinue(void)
{
int click = fgetc(stdin);
if (click == 0x0A) {
return true;
} else if (click == 'q') {
return false;
}
/* Returns false in case of any other character */
return false;
}
int main(void)
{
bool condition = false;
do {
printf("Hello World\n");
printf("Enter q to quit or ENTER to continue.\n");
condition = quitOrContinue();
} while (condition);
return EXIT_SUCCESS;
}
You do not need the progress variable.
while (getchar() != '\n');
serves no purpose in your code, unless you're trying to flush stdin.
regarding:
printf("%s", "input round for round mode, moves for move mode");
You could use:
printf("input round for round mode, moves for move mode");
regarding:
scanf("%s", input);
What happens when one inputs more than size characters?
Limit length:
scanf("%6s", input);

Using function if, if condition is true, not working?

I want so that when the user enters e it will run my function called enter and scan in values but all I get is VECRQ?:, why is this? Did I call upon the function wrong?
I tried having the while loop to 1 also instead of menuoption != 'q' didn't work. I was thinking that with the menuoption is not equal to 'q' it will keep the loop running until the user actually enters 'q' to shut the program off.
#include <stdio.h>
int enter(int measurments[], int nrOfmeasurments)
{
while(nrOfmeasurments<10)
{
printf("Enter measurment #%d (or q to quit): ",nrOfmeasurments+1);
int oneMeasurment;
int readInteger = scanf("%d",&oneMeasurment);
if(readInteger)
{
measurments[nrOfmeasurments] = oneMeasurment;
nrOfmeasurments ++;
//return nrOfmeasurments;
}
else
{
char tmp;
scanf(" %c",&tmp);
break;
}
}
if(nrOfmeasurments==10)
{
printf("Array is full\n");
}
return nrOfmeasurments;
}
int main(void)
{
int measurments[10];
int nrOfmeasurments;
char menuoption;
printf("Measurment tool 2.0\n");
while (menuoption != 'q')
{
printf("VECRQ?:\n");
scanf(" %c",&menuoption);
if (menuoption == 'e')
{
//int MeasurmentData[10];
//int nrOfmeasurments;
//enter(measurments, nrOfmeasurments);
nrOfmeasurments = enter(measurments, nrOfmeasurments);
}
else if(menuoption == 'v')
{
}
else if(menuoption == 'c')
{
}
else if(menuoption == 'q')
{
printf("Exiting Measurment tool 2.0\n");
break;
}
}
}
Don't forget to init your variables with default values. Your problem is that nrOfmeasurments is not initialized and have some trash value. Also, set a default value to menuoption for some non q char to be sure, that your loop will be executed at least one time

Is there a way to replace the kbhit() and getch() functions in Standard C?

I'm trying to get a quick time event type of interaction with the console and I managed to obtain it using the conio library. Sadly the project I'm working on requires the code to be compilable on both Windows and Linux and I can't figure out a way to change it.
Is there anything I can do to get the desired effect or should I give up on this notion? Below is the code for the function I created.
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
void battle(int x) {
srand(time(0));
printf("Use Q to dodge projectile attacks, E to block melee attacks and W to attack when the boss is stunned. Button mashing will not work! Press any key to start the battle.\n\nYou face Brutus, Lord Incarcerator!\n\n");
getchar();
bool ok;
int dealt = 0 ,recieved = 0 , state, prev = 0;
time_t start, end;
double elapsed;
while(dealt < 5 && recieved < 3)
{
do
{
state = rand() % 3 + 1;
}
while(prev == state);
prev = state;
time(&start);
switch(state)
{
case(1):
ok = 1;
printf("Brutus uses Hook Attack!\n\n");
do
{
time(&end);
elapsed = difftime(end, start);
if(kbhit())
{
if( getchar() == 'q')
{
printf("Dodged!\n\n");
ok = 0;
break;
}
else
{
break;
}
}
}
while(elapsed < 3);
if(ok)
{
printf("You took damage!\n\n");
recieved++;
break;
}
break;
case(2):
ok = 1;
printf("Brutus is stunned!\n\n");
do
{
time(&end);
elapsed = difftime(end, start);
if(kbhit())
{
if( getchar() == 'w')
{
printf("You dealt damage!\n\n");
dealt++;
ok = 0;
break;
}
else
{
break;
}
}
}
while(elapsed < 3);
if(ok)
{
printf("Too slow!\n\n");
break;
}
break;
case(3):
ok = 1;
printf("Brutus uses Blood Slam!\n\n");
do
{
time(&end);
elapsed = difftime(end, start);
if(kbhit())
{
if( getchar() == 'e')
{
printf("Blocked!\n\n");
ok = 0;
break;
}
else
{
break;
}
}
}
while(elapsed < 3);
if(ok)
{
printf("You took damage!\n\n");
recieved++;
break;
}
break;
}
}
if(recieved >= 3)
{
printf("Battle lost; you will now respawn in town.");
getchar();
}
else
{
printf("Battle won!");
getchar();
}
}
int main()
{
battle(2);
}
You could write your own getch().
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
/* reads from keypress, doesn't echo */
int getch(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}
Not really, since they can't be implemented on some
implementations, and can only be implemented at great cost on
others.
While not standard, there are portable libraries like
ncurses which support these sort of operations.
There are two choices
Find some cross-platform library that abstracts the details away for you (SDL might be good for this.)
Do the abstracting yourself.
To do 2. you will have to define your own version of the input functions. You then create different implementation for each platform. This means your core code remains common across the various platforms.
I think you need to use ncurses library.
here is similar question:Create a function to check for key press in unix using ncurses

C program switch statement

I'm new to programming in C. I have a quick question about Switch Statements.
I have a menu that presents a list of options like so:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct Video {
char name[1024]; // Yvideo name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct Video Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void savequit();
void load();
void branching(char);
void menu();
int main()
{
char ch;
load(); // load save data from file
printf("\n\nWelcome\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
savequit();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
so far entering 'i' (for inserting a new entry) and q (for save and quit) work perfectly. However every time I enter 'p' I get the default case. (Error: Invalid Input. Please try again...). What is it that I am doing wrong? I believe the syntax for the switch is correct? I've tried changing the 'p' to a different letter and I still got the the default case. Here is my printall() method if that helps...
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nName: %s", Collection[i].name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
What about something like:
char b[5];
do {
menu();
if(fgets(b,5,stdin)==NULL)
return -1;
ch = tolower(b[0]); // read a char, convert to lower case
while(strlen(b)>=4&&b[3]!='\n'){
check=fgets(b,5,stdin);
if(check==NULL)
return -1;
}
branching(ch);
} while (ch != 'q');
You can output the invalid char in your default case. That may help you understand how your input are handled.
default:
printf("\nError: Invalid Input ('%c'). Please try again...", option);
break;
fflush(stdin) is undefined as fflush is define only for output streams. To clear the newline char, you can simply use another getchar().
Try this for the loop part:
do {
menu();
ch = tolower((unsigned char)getchar());
getchar();
branching(ch);
} while (ch != 'q');

My code is looping once more than I want it to, I suspect something is wrong with my getchar statement

Firstly, I would like to thank everyone here in advance. I look very forward to advancing in the realm of computer science, and helping others as I become more proficient.
Now here is my code:
#include <stdio.h>
#include <stdlib.h>
#define RECORDS 30
/*Questions
Formatting display() - can we use spaces to format?
Is the patient structure supposed to be global or local in enter()?
*/
void enter();
void display();
void update();
void loadDisk();
void writeDisk();
void emptyDisk();
void sort();
void clear();
struct patient
{
char * name;
int age;
double highBP, lowBP, riskFactor;
};
struct patient * db[RECORDS];
int counter = 0;
main()
{
int flag = 1;
while (flag == 1)
{
printf("---------------------------------------------------------\n");
printf("|\t(N)ew record\t(D)isplay db\t(U)pdate record |\n");
printf("|\t(L)oad disk\t(W)rite disk\t(E)mpty disk |\n");
printf("|\t(S)ort db\t(C)lear db\t(Q)uit |\n");
printf("---------------------------------------------------------\n");
printf("choose one: ");
char selection = getchar();
printf("selection %c\n", selection);
if ((selection == 'n') || (selection == 'N'))
{
//New record
enter();
}
else if ((selection == 'd') || (selection == 'D'))
{
//Display db
//printf("display %d\n", flag);
display();
}
else if ((selection == 'u') || (selection == 'U'))
{
//Update db
update();
}
else if ((selection == 'l') || (selection == 'L'))
{
//Load disk
loadDisk();
}
else if ((selection == 'w') || (selection == 'W'))
{
//Write disk
writeDisk();
}
else if ((selection == 'e') || (selection == 'E'))
{
//Empty disk
emptyDisk();
}
else if ((selection == 's') || (selection == 'S'))
{
//Sort db
sort();
}
else if ((selection == 'c') || (selection == 'C'))
{
//Clear db
clear();
}
else if ((selection == 'q') || (selection == 'Q'))
{
//Quit
flag = 0;
}
else
{
printf("not a vaild input\n");
}
}
}
void enter()
{
/*struct patient temp;
printf("name: "); sscanf("%s", temp.name);
printf("age: "); scanf("%d", temp.age);
printf("high bp: "); scanf("%f", temp.highBP);
printf("low bp: "); scanf("%f", temp.lowBP);
db[counter] = (struct patient *) calloc(1, sizeof(temp));
*db[counter] = temp;
//printf("%s, %d, %f, %f", db[counter]->name, db[counter]->age, db[counter]->highBP, db[counter]->lowBP);
counter++;*/
}
void display()
{
}
void update()
{
}
void loadDisk()
{
}
void writeDisk()
{
}
void emptyDisk()
{
}
void sort()
{
}
void clear()
{
}
The issue I am having when running it is that the menu displays twice after I enter an option. I am having trouble understanding what is going wrong, but I suspect it has something to do with getchar which storing the selection and the new line character, hence running it twice. This would also mean the final else statement would run, which it does.
I think I have triangulated the problem, just unsure how to fix it. Thank you in advance!
If the problem is with getchar, which it does look to be, why not use a different function?
Try replacing:
char selection = getchar();
With this:
char selection;
scanf("%c",&selection);
If you're worried about overflow in the single character, then do a scanf() for a string and only use the first character in your checks:
char selection, selectionstr[20];
scanf("%s",selectionstr);
selection = selectionstr[0];
getchar also returns '\n' character.
Yeah, the problem is that your input is always a string, at least one character followed by a newline. I would either change your loop so that it terminates if selection is 'q' or use a function other than getchar and prune your input.
I think you can do this using curses! Here is a a website which you may find useful. Curses is a cursor control library for c.
From the manual:
Initially the terminal may or may not be in cbreak mode, as the mode is
inherited; therefore, a program should call cbreak or nocbreak explic-
itly. Most interactive programs using curses set the cbreak mode.
Note that cbreak overrides raw.

Resources