Skip input buffer in c? - c

I am making a small console game and want to allow instant input and output for the player so that they don't have to hit enter after each move. I understand there are already a few solutions that can be found online, most prominently ncurses (I'm on linux), but I have not been able to get anything to work. When I input the code below, I get the message:
main.cpp:(.text+0x39c): undefined reference to `initscr'
main.cpp:(.text+0x3a3): undefined reference to `stdscr'
main.cpp:(.text+0x3ac): undefined reference to `wgetch'
main.cpp:(.text+0x3b4): undefined reference to `endwin'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I understand skipping the input buffer is not standard in C, but any ways around this would be greatly appreciated. I can make the code work by just using key = getchar(); but as aforementioned, I want to skip the necessary enter key.
void move(int key){
initscr();
key = getch();
switch(key){
case 'w': if (playery > 1){y--;}
break;
case 's': if (playery < height - 1){y++;}
break;
case 'a': if(playerx > 1){x--;}
break;
case 'd': if(playerx < width - 1){x++;}
break;
default: grid[x][y] = 'x';
break;
}
endwin();
}

You need to link with ncurses to make it work. When you include curses.h or ncurses.h, it includes just the definitions. The actual code is separated, so you have to tell your compiler to add the code to your program.
Compiling with clang
Use this when compiling C++:
clang++ main.cpp -lncurses
Use this when compiling C:
clang main.c -lncurses
Never use clang with C++ or clang++ with C. It creates a huge mess.
Compiling with GNU/gcc
Use this when compiling C++:
g++ main.cpp -lncurses
Use this when compiling C:
gcc main.c -lncurses
Again, do not interchange those.
You say you use C, but you have main.cpp, which implies you are using C++. Rename your file to main.c or edit your question.
As noted in comments, ncurses already has a function named move. You should rename your function.

Related

How to write a "Makefile" for a “Guess the Right Number!” game in C?

I have completed the code to run the box inside of game. It is called Guess the right number! which means you can select a number from between 0 to 10, if it is not right number it will show message to try again, otherwise to appears a message you are winner with choices quit or restart. When I try to use gcc to compile it but it looks like I need to create a makefile as I was told but I have never done to make makefile for a single file or a second file would be called answer?
I have been doing C programming for 4 months so far. My program name is game.c to create Game (./Game) to start a program (game). How can I write a makefile for this?
I have no idea what is "curses" so I wanted to learn how to use with curses (<ncurses.h>) for myself when I did a lot of research so far I don't see the different betweens curses and ncurses. I have created the compile error after I use gcc in the below.
Snippet:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <time.h>
// PREDEFINED VALUES FOR DEFINING NON CHANGING VALUES IN CODE THIS CASE
#define WINDOWHEIGHT 20
#define WINDOWWIDTH 60
#define WINDOWSTARTX 0
#define WINDOWSTARTY 0
#define CORRECT 1
#define INCORRECT 0
#define START 2
#define WRONGFORMAT 3
#define MAXVALUE 10//You may change MAXVALUE to any num, i.e. `100` = (0-100).
#define MINVALUE 0
// PREDEFINED VALUES FOR DEFINING NON CHANGING VALUES IN THIS CASE
// initialising global structure for saving amount of right and wrong guesses and number to compare with.
struct game {
int rightGuesses;
int wrongGuesses;
int rightNumber;
} myGame;
void initializeGame()
{
// Returns a pseudo-random integer between 0 and MAXVALUE.
int randomNumber = rand() % MAXVALUE;
myGame.rightGuesses=0;
myGame.rightNumber=randomNumber;
}
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win, 0, 0);
wrefresh(local_win);
return local_win;
}
int getGuess()
{
int guess=0;
char guessString[32];
scanf("%s", guessString);
// Read number as string by using scanf, but convert to int for comparison with atoi()
guess= atoi(guessString);
size_t allowedEntries = strspn(guessString, "0123456789");
// Some checking if guess was between allowed range + its a number + checking if answer is correct or not
if(guess>=MINVALUE && guess<=MAXVALUE && guessString[allowedEntries] == '\0')
{
if(guess==myGame.rightNumber)
return CORRECT;
else
return INCORRECT;
}
else
return WRONGFORMAT;
}
/**
Function for updating views regarding the input values...
**/
void updateWindowTexts(WINDOW* window, int state)
{
char* greetingsString = "Guess the correct number!";
char* instructionsString = "Enter number 0-10 and press enter";
char* correctGuess = "That was correct! Lets play again";
char* incorrectGuess = "Sorry that was not right";
char* wrongFormat = "incorrect number, please enter number between 0-10";
char* correctAnswersString = "Correct answers:";
char correctAnswers[32];
char wrongAnswers[32];
const char rightAnswersBase[] = "Right numbers so far: ";
sprintf(correctAnswers, "%s%d", rightAnswersBase, myGame.rightGuesses);
const char wrongAnswersBase[] = "Wrong numbers so far: ";
sprintf(wrongAnswers, "%s%d", wrongAnswersBase, myGame.wrongGuesses);
wclear(window);
box (window, 0, 0);
mvwprintw (window, 1, (WINDOWWIDTH/2)-(strlen(greetingsString)/2), greetingsString);
mvwprintw (window, (WINDOWHEIGHT-3), (WINDOWWIDTH/2)-(strlen(correctAnswers)/2), correctAnswers);
mvwprintw (window, (WINDOWHEIGHT-2), (WINDOWWIDTH/2)-(strlen(wrongAnswers)/2), wrongAnswers);
mvwprintw (window, (WINDOWHEIGHT/2), (WINDOWWIDTH/2)-(strlen(instructionsString)/2), instructionsString);
switch (state) {
case START:
break;
case CORRECT:
mvwprintw (window, WINDOWHEIGHT-5, (WINDOWWIDTH/2)-(strlen(correctGuess)/2), correctGuess);
myGame.rightGuesses++;
break;
case INCORRECT:
mvwprintw (window, (WINDOWHEIGHT-5), (WINDOWWIDTH/2)-(strlen(incorrectGuess)/2), incorrectGuess);
myGame.wrongGuesses++;
break;
case WRONGFORMAT:
mvwprintw (window, (WINDOWHEIGHT-5), (WINDOWWIDTH/2)-(strlen(wrongFormat)/2), wrongFormat);
break;
}
wrefresh (window);
}
int main (int argc, char **argv)
{
WINDOW *my_win;
initscr();
// Here we call crea_newwin to make new window, paremeters are static and defined at the top of file
// You can try to play with these numbers
my_win = create_newwin(WINDOWHEIGHT, WINDOWWIDTH, WINDOWSTARTY, WINDOWSTARTX);
// Initialization of random generator, should only be called once.
srand(time(NULL));
initializeGame();
// Update window once before enteringing loop
updateWindowTexts(my_win,START);
while(1)
{
updateWindowTexts(my_win,getGuess());
}
return 0;
}
gcc version:
/u1/stuff/C/projectFinal> gcc game.c
/usr/bin/ld: /tmp/ccOy8YhK.o: in function `create_newwin':
game.c:(.text+0x73): undefined reference to `newwin'
/usr/bin/ld: game.c:(.text+0xa8): undefined reference to `wborder'
/usr/bin/ld: game.c:(.text+0xb8): undefined reference to `wrefresh'
/usr/bin/ld: /tmp/ccOy8YhK.o: in function `updateWindowTexts':
game.c:(.text+0x251): undefined reference to `wclear'
/usr/bin/ld: game.c:(.text+0x285): undefined reference to `wborder'
/usr/bin/ld: game.c:(.text+0x2c5): undefined reference to `mvwprintw'
/usr/bin/ld: game.c:(.text+0x301): undefined reference to `mvwprintw'
/usr/bin/ld: game.c:(.text+0x33d): undefined reference to `mvwprintw'
/usr/bin/ld: game.c:(.text+0x379): undefined reference to `mvwprintw'
/usr/bin/ld: game.c:(.text+0x3f4): undefined reference to `mvwprintw'
/usr/bin/ld: /tmp/ccOy8YhK.o:game.c:(.text+0x444): more undefined references to `mvwprintw' follow
/usr/bin/ld: /tmp/ccOy8YhK.o: in function `updateWindowTexts':
game.c:(.text+0x4a3): undefined reference to `wrefresh'
/usr/bin/ld: /tmp/ccOy8YhK.o: in function `main':
game.c:(.text+0x4ba): undefined reference to `initscr'
collect2: error: ld returned 1 exit status
First of all you cannot create a Makefile for something if you do not know how to make it manually. So let's first fix your compilation and linking problems. In order to compile your program type:
gcc -c game.c
The -c option tells gcc that you just want to compile, not link. This command produces an object file named game.o. To automate this with make you don't need anything: make knows already how to do this. Without any Makefile, just type:
make game.o CC=gcc
and make will do the job. Note that we tell make which compiler to use by passing it on the command line a value for its standard make variable CC.
Next we want to link all object files of our project (only game.o in our case, but we could have several, corresponding to several different source files) and generate the executable. The important thing to understand here is that you are using a library of already existing functions (ncurses) that is not linked by default with any executable, because most programs do not use it. You must tell gcc to link your object file(s) with this library using the -lncurses option:
gcc game.o -o game -lncurses
Note that in a very simple example like this you can
compile and link in one single call to gcc:
gcc game.c -o game -lncurses
And there again, make knows already how to do all this. It just needs to be passed the -lncurses linking option thanks to the other standard make variable LDLIBS:
make game CC=gcc LDLIBS=-lncurses
And that's it, you should be able to play your game. If you want to handle all the details yourself in a real Makefile the following should be OK:
game: game.c
gcc game.c -o game -lncurses
But a much more make-ish solution would rather be:
CC := gcc
LDLIBS := -lncurses
game: game.c
$(CC) $^ -o $# $(LDLIBS)
In order to understand this you will have to spend some time with the GNU make manual but here is a short and minimal explanation. In both versions:
<target>: <prerequisite>
<recipe>
tells make that to build <target> it needs to have <prerequisite> and run <recipe>. It also tells make that if <target> is newer than <prerequisite> there is no need to re-build <target>. In the first version above, with:
game: game.c
gcc game.c -o game -lncurses
make knows that:
if game.c does not exist it cannot build game; if it as asked to do so, it will raise an error
if game exists and is newer than game.c there is nothing to do to build game
if game does not exists or if it is older than game.c, it must run:
gcc game.c -o game -lncurses
In the second version:
VARNAME := <value>
is the make syntax for setting a make variable named VARNAME to value <value>, while $(VARNAME) is the make syntax to get the value of make variable VARNAME. $# and $^ are two automatic variables which values are, respectively, the target and the list of all prerequisites of the rule in the recipe of which they appear.

Turbo C++ GCC Compiler

I'm currently developing a gui application in turbo c++ (mandatory) for a project using C language, and i need to invoke turbo c++'s compiler(gcc), my question is HOW DO I CALL IT? i can't find any sources in the internet regarding this.
here's a snippet of my code
int program(){
int opt=-1,j;
char menu[4][20]={"Open File","Compile", "Run","Quit"};
close=1;
dropmenu(menu,10,33,131,105,opt);
do{
showmouse();
getmousepos(&buttonm,&xm,&ym);
if(xm>=10+10&&xm<=131-10&&ym>=33+8&&ym<=105-8&&buttonm==1){
for(j=0;j<(105-33-8)/14;j++)
if((ym-33-8)/14==j){
opt=j;
break;
}
dropmenu(menu,10,33,131,105,opt);
switch(opt){
case 0: openFile(); break;
case 1: compile(); break;
case 2: run(); break;
case 3: delay(100);cleardevice();closegraph();exit(0);
}
}else if(xm>=10&&xm<=34&&ym>=18&&ym<=32&&buttonm==1){
dropmenu(menu,10,33,131,105,opt);
continue;
}else if(buttonm==1){
break;
}
}while(close);
return 0;
}
void openFile() {
}
void compile() {
//i would like to put that invoking here
}
void run() {
}
Firstly gcc is not equivalent to turbo-c. turbo uses tc for compiling the codes. You can probably find that from the documentations of turbo c. To compile a file you can use system function. This function helps to execute command on the turbo c shell. I am not sure gcc would be accessible from the turbo shell. Since turbo elevates(mount) the directories giving it restricted permissions only. Also if you want to use the system it would be like following:
system("tc source.c -o destination");
or
system("gcc source.c -o destination");
remember the above code also shows error if any in the text mode only therefore you might want to redirect them to some file. You can find out about redirecting of output of command line from google. There are many resources about it.

How to do an explicit fall-through in C

The newer versions of gcc offer the Wimplicit-fallthrough, which is great to have for most switch statements. However, I have one switch statement where I want to allow fall throughs from all case-statements.
Is there a way to do an explicit fall through? I'd prefer to avoid having to compile with Wno-implicit-fallthrough for this file.
EDIT: I'm looking for a way to make the fall through explicit (if it's possible), not to turn off the warning via a compiler switch or pragma.
Use __attribute__ ((fallthrough))
switch (condition) {
case 1:
printf("1 ");
__attribute__ ((fallthrough));
case 2:
printf("2 ");
__attribute__ ((fallthrough));
case 3:
printf("3\n");
break;
}
GCC fallghrough magic comments
You should not use this if you can help it, it is insane, but good to know about:
int main(int argc, char **argv) {
(void)argv;
switch (argc) {
case 0:
argc = 1;
// fall through
case 1:
argc = 2;
};
}
prevents the warning on GCC 7.4.0 with:
gcc -Wall -Wextra main.c
man gcc describes how different comments may or not be recognized depending on the value of:
-Wimplicit-fallthrough=n
C++17 [[fallthrough]] attribute
C++17 got a standardized syntax for this: GCC 7, -Wimplicit-fallthrough warnings, and portable way to clear them?
You should be able to use GCC diagnostic pragmas to disable that particular warning for your source file or some portion of a source file. Try putting this at the top of your file:
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"

How do I get GCC to work?

I am using Vim as my editor and GCC as my compiler, but it’s not working quite right. Let‘s say I am making a basic program to determine if a number is odd or even. Here is my code:
#include <stdio.h>
int main(int argc, char argv[])
{
int i;
printf("Enter a number: ");
scanf("%d\n", &i);
printf("%d\n", i);
if(i % 2 == 0)
{
printf("Your number is even.\n");
}
else if(i % 2 != 0)
{
printf("Your number is odd.\n");
}
else
{
printf("Invalid input.\n");
}
getchar();
return 0;
}
I'm not sure if I am programming this wrong, or gcc is just not a good compiler, or whatever. I am running linux, which I dual boot with windows. Now I press ctrl-d to stop the process, and only then does it print me back my number, and tell if it is odd or even. It isn't just this one, a lot of other programs with similar formats seem to do this to.
~ $ ./test
Enter a number: 45
45 //I press enter, nothing happends. Ctrl-d
Your number is even. //ctrl-d again
~ $
So what I'm asking is, is there a way to program it so that I don't have to quit the program in order for it to work, or is there another compiler that wouldn't have this problem? I am running on Ubuntu 14.04 dual booted with Windows 8.1.
\n in the format for scanf means "read until hit into non-whitespace character and then ignore them". Remove it and make the format for reading "%d".
to get gcc to work from vim,
goto the vim command prompt
shell gcc <and all needed parameters>
Or open another command window
set it to the same directory as the program being edited
gcc <and all needed parameters>
in general, try to make the compile step separate from the link step. I.E. to compile:
gcc -c <mySource.c> -Wall -Wextra -pedantic -std=c99 -o mySource.o
if any header files, other than those in the default 'include' path then add
-I<pathToHeaderFile>
which is often in the same directory so would be:
-I.
then link with:
gcc mySource.o -o mySource
You can add the -ggdb parameter to both lines if you plan on doing any debugging.
to add any library directories then on the link step append
-L<pathToLibrary>
to add any libraries then on the link step append, after any library parameters:
-l<shortLibName>
The initialization file for vim can contain the necessary info to invoke gcc by some keystroke combination, but I'm not totally familiar with the details.

Linux terminal - error: label at end of compound statement

I'm using x64 Ubuntu Linux via VMware Player as a virtual machine. As a part of my project, I need to install some library (fec-3.0.1). I'm new to Linux and not good at coding.
Here is the error I encounter in terminal after successful configuration:
farhat#ubuntu:~/project/fatcaps_v0.5/fec-3.0.1$ make
gcc -g -O2 -I. -Wall -c -o dotprod.o dotprod.c
dotprod.c: In function ‘freedp’:
dotprod.c:56:3: error: label at end of compound statement
default:
^
make: *** [dotprod.o] Error 1
Here is function 'freedp' content (the start line is 55):
/* Free a dot product descriptor created earlier */
void freedp(void *p){
switch(Cpu_mode){
case PORT:
default:
#ifdef __i386__
case MMX:
case SSE:
return freedp_mmx(p);
case SSE2:
return freedp_sse2(p);
#endif
#ifdef __VEC__
case ALTIVEC:
return freedp_av(p);
#endif
}
}
What should I do?
The reason why you meet the error label at end of compound statement is because the default case can not be empty, it means you must provide a break or ; empty statement.
Edited: I find some material on that topic, and I got that: https://mail.gnome.org/archives/evolution-patches/2004-April/msg00235.html, It is the problem about the compiler gcc3.4, which reports an error on default without statements, and it is warning on gcc3.3, but now, I test on gcc4.8.2, it is all right....

Resources