allow user to start program again in c? - c

I have written a program in c. However once the program is finished it stops (duh). Is there a simple script that allows me to let the user start the program over again?

Why not use loop (for, while) in the main itself: ( if the program is simple!)
main()
{
while( Exit condition)
{
//logic
}
}

char cont_prog = 'n';
do {
/* main program in here */
printf("Do you want to start again? (y/n): ");
cont_prog = getchar();
} while (cont_prog == 'y' || cont_prog == 'Y');
Essentially, you want to put you main prog in a loop, asking the user if they want to continue. You have to deal with the user entering in too much data (they type, 'yes', for example) and your buffer being full next time through the loop.

If you really want to re-launch the program without exiting (though I can't see why):
Save argv (and I'll assume that argv[0] actually points to your executable, even though that is not guaranteed) if you want the same command line arguments.
Consider saving the environment, if you might change it, and also want it to be repeated.
man execv or execle. Just replace the currently running image with a new one that has the same command line
Frankly, looping would be easier, and can have the same semantics if you avoid global state, or arrange to be able to re-set it.

Sure, but how would you get the user to run that script? Wouldn't it be simpler to have the user simply re-run the program?

#include <stdlib.h>
#ifdef WIN32
#define EXECUTABLE ".exe"
#else
#define EXECUTABLE
#endif
int main(void) {
for (;;) system("executable_in_c" EXECUTABLE);
return 0;
}
Compile this program, rename your old executable to "executable_in_c[.exe]"; rename this one to the name of your old executable ... voila!

Related

Application files made using CodeBlocks won't run outside the IDE

I've been learning programming with C and have made some starter programs using CodeBlocks. The problem is that I can't run the application files that are saved in bin\debug by double right clicking on them. Instead, I have to open the project file and hit "Run" or "Build and Run" to do so. Is there a way to fix this?
Firstly, "double click" means "double (left) click" and not "double (right) click".
Even if your machine does support "double right click" to open a file, the following could be a problem.
Consider a small program like this:
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
You can see its results when you run it inside the IDE because it waits for you to "press any key" before terminating it.
But when you run it outside the IDE, the program is terminated immediately at the end of main. The program will open, execute, and terminate before even you realizing it. It happens very quickly. In case of programs dealing with user inputs, you can see the intermediate results though.
Solution:
An easy fix is to add getchar() to the end of main. It will wait for you to press the enter key in order to quit the console application.
#include <stdio.h>
int main()
{
printf("Hello World");
getchar(); // <-- add this line of code
return 0;
}
You can also have a more controlled termination by making your own exit function.
For example, if your program leaves a newline in the buffer before calling the getchar, it would consume the '\n' and not wait for you to press the enter key. In that case, you should clear the input buffer:
// clear the input buffer
char ch;
while ((ch = getchar()) != '\n' && ch != EOF);
// then call getchar
getchar();

When modularising C code, within a function is there a way to loop to another function (i.e. to my main() c file)?

I'm in my first semester at university studying C programming. We've gained an introduction to modularising our code, and the basic gist of my problem is that I've created a function which prompts the user to continue or exit the program. Obviously I have a few other functions before this and I call these in main(). Bear in mind the functions are in separate C files. I wish to loop back to main() if the user inputs 'Y' (i.e. to start the program from the beginning), but given my beginner knowledge I've had a hard time figuring out how to go about this. Any help/guidance would be appreciated!
int continueOrExit() {
char response;
char upperResponse;
printf("Do you wish to continue the program? Y/N");
scanf("%c", &response);
upperResponse = toupper(response);
while(upperResponse == 'Y')
main(); // this is the bit which I struggle with
.....
}
You should not run your main() again from inside a function already called from main(). Well, you could; recursive calls are possible, but you definitely don't want to do it in this case.
What you want to do is for your continueOrExit() to return true when user chooses to continue, and put a selected large part of your main() body in a loop:
do
{
/* your code here */
} while (continueOrExit());
Going from one function directly to another is against the rules of structured programming. It may be used for handling of errors (longjmp), but such a mechanism should be used sparingly - only when you really have an error which you cannot handle in any other way.
To implement the "start over" functionality, you have to structure your code with that in mind. For example:
int exitByUserRequest()
{
char upperResponse;
...
return (upperResponse != 'Y');
}
int main()
{
do
{
...
} while (!exitByUserRequest());
}
Here, the main function calls exitByUserRequest and interprets its exit code.
If you have several layers of functions between main and "ask user whether to continue", all of them should pass the information "exit or continue" to the caller, using return codes. Therefore, you should avoid this situation - your "exit or continue" should be called directly from main.

Trying to execute and compile C programs in notepad++

I referred this article to setup compiler and execution tool.
http://codingfox.com/1-9-how-to-configure-gcc-in-notepad-for-c11/
The problem I am facing is that when I try to compile the program I have made, compiler shows up for milliseconds and disappears.Thus, I am not able to see what's wrong in that program. I want compiler to stop by and wait for my response.
Code is as follows
header files used are stdio.h and conio.h
int main()
{
printf("Hello World");
return 0;
getch();
}
In case, there are more ways of what I am trying to do, please let me know.
Help will be appreciated.
Post your code. This is need to understand if it closes because of the progam is ended, or if compiler stops on errors. In any case the article gives you instruiction to run your code, but you can also compile it, as #Sourav suggested you. If the program simply ends, as #Igor wrote, you can add a getch() before the end of main and the execution stops and wait for an input.
Another way is to launch the compiled program into cmd shell: it will not close the shell at the end of the program.
The issue is that your output window disappears before you ever get a chance to look at it.
You took it a bit too literally to use getch at the end of your program.
We mean, "at the end of the program, before the return statement"
What you wrote
int main()
{
printf("Hello World"); // This does exactly what you expect
return 0; // Your program ends here.
getch(); // This line is NEVER run.
}
What you should write
int main()
{
printf("Hello World"); // This does exactly what you expect
getch(); // Pause the program for input.
return 0; // Your program ends here.
}

Breaking up from while loop in lex

so I have using lex tool in linux and fell into an embarrassing position position , I couldn't break from a while loop.
e.g : I wrote ;
while(1)
{
int x = yylex();
switch(x):
case(ID):printf("ID");
case(NUM):printf("NUM");
}
Now I am reading from a file using yyin ; the problem is that the while loop does not fail after reading the whole file and keeps asking for more inputs at the terminal . Therefore I could not invoke other functions after calling the while loop . I know I am missing something basic , it will be great if somebody can provide an insight into this problem .
P.S# Thanks all for your answers ; tension and lack of sleep before homework submission date ; btw - I figured my answer already .
I see some issues with the C code, independent of what's going on inside the yylex() function. You quote the code as:
while(1)
{
int x = yylex();
switch(x):
case(ID):printf("ID");
case(NUM):printf("NUM");
}
This clearly isn't the source you compiled because it is not acceptable as C. You need to replace the first colon (after switch(x)) with an open brace {, and you need another close brace } at the end, to yield:
while(1)
{
int x = yylex();
switch(x)
{
case(ID):printf("ID");
case(NUM):printf("NUM");
}
}
This is syntactically valid C code, but there are still problems:
There should probably be a break; after each case.
There should probably be a default: clause, which might be used to terminate the loop (but you can't use break to do that inside the scope of a switch).
The printf() statements should print a newline so that the data appears.
Since yylex() returns 0 when it reaches the end, you should probably revise the code so it is more like:
void function(void)
{
int x;
while ((x = yylex()) != 0)
{
switch (x)
{
case ID:
printf("ID\n");
break;
case NUM:
printf("NUM\n");
break;
default:
printf("Other: %d\n", x);
break;
}
}
}
This will at least show you what's going on, and does not have an infinite loop unless you've written your lex analyzer such that it does not terminate properly. I opted not to have the default case terminate the loop since the loop is bounded by yylex() returning 0 instead.
When you write while (1), you are writing an infinite loop. It is incumbent on you to consider whether the loop is really infinite or not. If it is not, then you should aim to be able to make a test at the top of the loop that controls whether there is another cycle to the loop or not.
yylex() returns 0 at the logical end of input. Try this:
int x = -1;
while(!(x == 0))
{
x = yylex();
switch(x):
{
case(0): printf("that's all, folks!"); break;
case(ID): printf("ID"); break;
case(NUM): printf("NUM"); break;
}
}
Well, while I'll admit I'm not familiar with what lex is, I do know quite a bit about the linux environment and the terminal, so...
Try typing 'Ctrl' and 'c' at the same time while in the terminal. If that doesn't work, use 'Ctrl' + 'z'. If you don't mind having the process stopped in the background until the computer turns off and it goes away entirely, after Ctrl + Z you don't need to do anything else. If Ctrl + C worked, then the program's ended and you're fine.
If, for whatever reason, neither work, if you know the name of the program you wrote, you can type into the terminal:
pkill -9 [insert name of program here]
...which will send an unignorable kill signal to the process, and return all its memory (RAM- it won't undo changes made to disk) to the parent process.
If you DON'T know the name of the program, but you think you'll probably be able to recognize it, you can try:
top
which will bring up all the currently running processes in the terminal. Once you locate the name of your still-running program, press q to exit top, and then type in the kill command above with the name you recognized in top. If you don't know the program's name, and Ctrl + Z worked, but you don't want the stopped job to keep hogging its memory until you've turned off the computer, you can type:
ps -a
while in the terminal session from which you ran (and stopped) the program, and the job which shows up labeled 'stopped' is, in all likelihood, yours. Again, using the pkill command above will kill it. If, for whatever reason, you know the process ID but not the name (I don't know why you would, but there you go...), you could use the command 'kill' instead of 'pkill' (instructions for how to use these commands are all over the internet so I won't mention them here. They also have helpful help manual pages which can be accessed via:
man [the name of the program you want help with; 'pkill' or 'kill', in this case.]
To add to David's answer, here's a different version:
do
{
int x = yylex();
if (!x)
break;
switch(x):
{
case(ID): printf("ID"); break;
case(NUM): printf("NUM"); break;
}
} while(1);
This was only to show that you can break out of a while(1). You keep the x in local scope, and you don't evaluate the first pass or switch unnecessarily. Of course someone will most likely pull out the trump card of "it isn't as readable"...

GNU Readline (libreadline): Displaying output message asynchronously

While using readline (blocking) for user input, I would like to output lines of text to the console asynchronously from another thread. Further, I would like that the readline prompt and current partial input line be removed from the console, the output line written, then the readline prompt and the partial user line restored - so as to give the appearance that the output was written "above" the prompt.
By what combination of readline redisplay functions (or otherwise) can this be achieved?
(Redisplay function documentation: http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC35)
problem demo:
#include <readline/readline.h>
#include <readline/history.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
bool run = true;
void* log_thread(void*)
{
while (run)
{
sleep(1);
// WHAT TO DO HERE?
write(1, "tick\n", 5);
}
}
int main()
{
pthread_t t;
pthread_create(&t, 0, log_thread, 0);
while (true)
{
char* p = readline("? ");
free(p);
if (!p)
break;
}
run = false;
pthread_join(t,0);
}
build:
$ g++ -pthread -lreadline test.cpp
$ ./a.out
observed output: (input "foo\nbar\n" typed slowly)
? tick
ftick
otick
otick
? tick
tick
bartick
tick
? tick
^C
desired output: (input "foo\nbar\n" typed slowly)
tick
tick
tick
tick
tick
? foo
tick
tick
tick
tick
tick
? bar
tick
? ^C
I'm doing this in the console version of my program omphalos (https://github.com/dankamongmen/omphalos). This particular code comes from https://github.com/dankamongmen/omphalos/blob/master/src/ui/tty/tty.c.
I have:
// Call whenever we generate output, so that the prompt is updated
static inline void
wake_input_thread(void){
if(input_tid){
pthread_kill(*input_tid,SIGWINCH);
rl_redisplay(); // FIXME probably need call from readline contex
}
pthread_mutex_unlock(&promptlock);
}
and
static inline void
clear_for_output(FILE *fp){
fputc('\r',fp);
}
Whenever something wants to print, it takes the lock and calls clear_for_output(), moving the cursor to the beginning of the current line. It can change the prompt at this time if necessary, by calling rl_set_prompt(). When done, it calls wake_input_thread(), releasing the lock and causing a redisplay.
I'm not sure if this works in the case where you've typed more than a line of text in, and doubt it, and don't care to formally discover what's likely a new and depressing bug right this moment, so you can experiment with that yourself.
The functions that should be used:
rl_clear_visible_line(). Printing \r won't do it well, because it just moves the cursor to the start of the line without deleting the line content, plus it fails to work properly when there's more than one input line.
rl_on_new_line(); rl_redisplay(); (or rl_forced_update_display();): After printing.
It appears that it's okay to call these two functions from any thread; however it may introduce race conditions (the documentation says nothing be whether it's safe to use readline functions from multiple threads), therefore it's better to use rl_event_hook and rl_getc_function (because rl_event_hook is not called when a key is held) to call the function for the main thread. Also remember to handle the says when there's no running readline function.

Resources