Hi everyone I am trying to add multiple conditions to a do while statement with the code shown as followed
do
( switch case menu)
while(choice!='X' && (NetworkPacket= 50; printf("No more network packets can be added")));
Basically, the (some code) part is a menu system which asks the user to add packets of data, then the choice!='x' allows the user to exit the program by pressing x. But as the menu allows them to loop through, I want the program to also restrict the user from adding more than 50 packets hence the network packet int = 50 then it says no more packets can be added but this doesn't seem to work.
Stylistically, your code will be easier to read if the while statement only has logic, and actions like printf are outside. You can separate out the parts like this:
#define PACKET_LIMIT 50
do {
(switch case menu)
//presumably NetworkPackets is being updated in here too
} while ((choice != 'X') && (NetworkPackets < PACKET_LIMIT));
//now check why we exited
if (NetworkPackets >= PACKET_LIMIT) {
printf("No more network packets can be added");
}
Using < PACKET_LIMIT in the loop logic allows for the case where multiple packets might be added by the loop body.
Try this
do
{
(switch case menu)
NetworkPacket++;
}
while(choice!='X' && (NetworkPacket >= 50? printf("No more network packets can be added" ),0 : 1));
Related
I am having issues making this nested while loop to work in this terminal application.I am trying to build a system with Clients and an Admin with certain
capabilities for each.
scanf("%s",sign_in_choice);
int admin_result, client_result, number_of_clients, x, c;
admin_result = strcmp(sign_in_choice,"Admin");
client_result = strcmp(sign_in_choice,"Client");
char client_choice[10];
int client_username;
int client_password;
int client_choice_log_in, client_choice_register;
while(x == 0)
{
if(admin_result == 0 )
{
printf("Welcome to Admin Page\n");
}
else if(client_result == 0)
{
printf("Testing");
while(c == 0)
{
//START OF CLIENT PAGE
printf("Welcome to Client Page\n");
printf("Register or Log in?\n");
scanf("%s",client_choice);
client_choice_log_in = strcmp(client_choice,"Login");
client_choice_register = strcmp(client_choice,"Register");
if(client_choice_register == 0)
{
// REGISTER
reg(client_number);
// END OF REGISTER
}
else if(client_choice_log_in == 0)
{
//LOG IN
printf("Please enter your credentials\n");
printf("Enter your afm:\n");
scanf("%d", &client_username);
printf("Enter your year of birth:\n");
scanf("%d", &client_password);
login(client_username, client_password, client_number, client_verify);
//END OF LOG IN
// PERSONAL CLIENT PAGE
i = client_number;
printf("Welcome to your Personal Client Page: %s \n", client_array[i].client_name);
printf("Verify : %d\n",client_verify);
// END OF PERSONAL CLIENT PAGE
}
else
{
printf("Invalid input.Please try again.\n");
scanf("%s",client_choice);
client_choice_log_in = strcmp(sign_in_choice,"Login");
client_choice_register = strcmp(sign_in_choice,"Register");
}
// END OF CLIENT PAGE
}
}
else
{
printf("Invalid input.Please try again.\n");
scanf("%s",sign_in_choice);
admin_result = strcmp(sign_in_choice,"Admin");
client_result = strcmp(sign_in_choice,"Client");
}
}
If I remove the while( c == 0) loop the code works.It allows me to select either Login or Register and continue.If I leave the loop as is when I input 'Client' the program goes into an infinite loop printing 'testing'.In addition if I enter 'Admin' the program again goes into infinite loop printing 'welcome to admin page' although the while loop appears later in the program.At least in my understanding the while(c == 0) loop should only affect what is contained within it not outside it,at least in this particular case.I am using Devc 5.11.Also I tried compiling and running through vs code and codeblocks and in those cases the program doesn't even go beyond the 'Admin Client' choice in the beginning.As you can see I have some functions and and structs not shown here but they should not affect my problem since everything works fine until I try to make this nested while loop work.
c is uninitialized, so it has an undefined behavior, which depends on your compiler. You will need to initialize your variables. And to make sure you do not have infinite loops, you must handle the case when you have a client and c is not 0. You can set it to 0, or something, just don't leave there an else which will always be entered, will not change c and will have a loop inside it, which depends on the value of c.
Maybe I missed it, but I do not see how you set the value of c inside the while (c == 0) loop, so if c happens to be 0, that inner loop seems to be infinite as well.
Update my code
So i am working on a 2d game in c, now i am using threads to do different stuff in the same time, to move the player, cars etc.
But somehow i don't get it how can i move my player just one step, i know that the problem lays in my global variable movement. But can figure it how to do it the right way. So i hope someone can help me.
The code is huge so i will not passt all of it but the parts that are interesting for the player movement.
void moveFroggy() {
// froggy.y = SCREEN_HEIGHT - OUTER_BORDER;
if((movement == 'a') && (froggy.x > OUTER_BORDER))
froggy.x--;
if((movement == 'd') && (froggy.x < (SCREEN_WIDTH - OUTER_BORDER)))
froggy.x++;
if ((movement == 'w') && (froggy.y >= (SCREEN_HEIGHT - NUM_LANES - OUTER_BORDER - GRASS_BORDER)))
froggy.y--;
if ((movement == 's') && (froggy.y < (SCREEN_HEIGHT - OUTER_BORDER)))
froggy.y++;
if(movement == 'q')
quit = 1;
if(froggy.y <= (SCREEN_HEIGHT - NUM_LANES - OUTER_BORDER - GRASS_BORDER))
player_won = 1;
movement = '0';
}
Now inside the main we have a while loop that runs all the time, till the player complete the game or quit it.
pthread_create(&input_t, NULL, input_runner, NULL);
while(!quit && !error && !player_lost && !player_won) {
moveFroggy();
moveCarsOnMotorway();
startCar((SCREEN_WIDTH - OUTER_BORDER));
drawScreen();
usleep(GAME_SPEED);
}
pthread_join(input_t, NULL);
So my input_t thread is calling the input_runner function inside that function i get the user input.
void *input_runner(void* arg) {
char input;
if(!player_lost || !player_won){
while((input = getchar()) != EOF){
movement = input;
}
}
pthread_exit(0);
}
Just to know movement is a global variable so i can use it for moveFroggy function. but that is the problem to because it stores "w" and it just repeat itself till the user hit any other command. But it should move the player just one step ahead, so how can i reset the value and how to do proper clean up for threads if one is needed.
I am new in using thread,
Well, it seems the simple way to only move one step would be, at the bottom of moveFroggy() to clear movement value.
As an aside, it looks like you're creating an input-processing thread on every iteration of your game loop; is that really what you intend? If you want an input-processing thread, why not have it run its own loop to constantly read input until the game is over?
I'm also not sure of this overall multithreading strategy, but perhaps it will work for you...
This is not a good use of threads, and will be prone to synchronization errors.
Variables that are accessed by multiple threads must be protected by a mutex or accessed using atomic methods. Failing to do so will result in unpredictable behavior.
In any case, you don't need threads for this. If you want to read from the keyboard without blocking, there are a number of ways of doing that, including:
If on Linux, use the ncurses library, which natively provides non-blocking keyboard input through getch().
If on Windows, use kbhit().
Use fcntl() with F_SETFL to set standard input as non-blocking.
Use select() or poll() to check for input before trying to read.
Avoid the console entirely, and use a graphics library such as SDL.
I'm attempting to write a function that will pull text from different sources (Ethernet client/Serial/etc.) into a single line, then compare them and run other functions based on them. Simple..
And while this works, I am having issues when trying to call a simple Serial.println() from a function OTHER than loop().
So far, I have around 140 lines of code, but here's a trimmed down version of the portion that's causing me problems:
boolean fileTerm;
setup() {
fileTerm = false;
}
loop() {
char character;
String content="";
while (Serial.available()) {
character = Serial.read();
content.concat(character);
delay(1);
}
if (content != "") {
Serial.println("> " + content);
/** Error from Serial command string.
* 0 = No error
* 1 = Invalid command
*/
int err = testInput(content);
}
int testInput(String content) {
if (content == "term") {
fileTerm = true;
Serial.println("Starting Terminal Mode");
return 0;
}
if (content == "exit" && fileTerm == true) {
fileTerm = false;
Serial.println("Exiting Terminal Mode");
return 0;
}
return 1;
}
(full source at http://pastebin.com/prEuBaRJ)
So the point is to catch the "term" command and enter some sort of filesystem terminal mode (eventually to access and manipulate files on the SD card). The "exit" command will leave the terminal mode.
However, whenever I actually compile and type these commands with others into the Serial monitor, I see:
> hello
> term
> test for index.html
> exit
> test
> foo
> etc...
I figure the function is catching those reserved terms and actually processing them properly, but for whatever reason, is not sending the desired responses over the Serial bus.
Just for the sake of proper syntax, I am also declaring the testInput() function in a separate header, though I would doubt this has any bearing on whether or not this particular error would occur.
Any explainable reason for this?
Thanks.
Model: Arduino Uno R3, IDE version: 1.0.4, though this behavior also happened on v1.0.5 in some instances..
It is kinda guessable how you ended up putting delay(1) in your code, that was a workaround for a bug in your code. But you didn't solve it properly. What you probably saw was that your code was too eager to process the command, before you were done typing it. So you slowed it down.
But that wasn't the right fix, what you really want to do is wait for the entire command to be typed. Until you press the Enter key on your keyboard.
Which is the bug in your code right now, the content variable doesn't just contain "term", it also contains the character that was generated by your terminal's Enter key. Which is why you don't get a match.
So fix your code, add a test to check that you got the Enter key character. And then process the command.
First this gets triggered:
if ((temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) | (temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit))
activateAlarm(channelID);
Activate alarm is triggered, then from there:
void activateAlarm(int channelID);
{ while (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit || temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit)
{
logSubsystem(temperatureChannel[channelID].currentTemperature);
}
}
Then alarm screen is triggered with following case:
int logSubsystem(int currentTemperature)
case 'F': //if user input is 'F'
case 'f': //if user input is 'f'
currentTemperature--;
printf("your current exceeded temp is %i\n \n", currentTemperature);
if (currentTemperature <= 100 || currentTemperature >= 50);
compareLimit();
break; //exits loop
How do I set up this function so that if the user decrements with F and gets the current temperature to below the limit (<100, or >50), then it will return back to the compareLimit function and the requirement for the high limit/low limit triggered state will be FALSE, returning the program to its original pre-alarm state?
I think you would benefit considerably from thinking a lot about how your program flows. Right now, what I can deduce of your program flow is:
You have an outer loop that checks the temperature, on at least one channel ID. Inside that loop, you have the if statement you first showed us.
Then activate alarm does some other stuff, but loops until the temperature goes down, calling logSubsystem.
logSubsystem then presumably gets some kind of user input, and from there, you want it to call to your initial function, presumably called prepare limit.
The problem with this is that none of these functions ever complete. They all call each other, and you'll eventually get a stack overflow. Nice, since that's the name of this site, but not something you want to aspire to.
What you basically need is a state machine. You need something that keeps track of values, looks at those values, and calls functions that return that operate on those values. There should only be one loop, and it should do all the control of what happens based on what those values are. The good news is, you have all of this in place already. temperatureChannel is keeping track of the values for you, and you have while loops a-plenty.
Let me give you my suggestion of the way I suggest your program should flow:
bool checkTemperatureValuesOutOfRange(int channelID) {
// this is just a convenience, to make the state machine flow easier.
return (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) || // note the || not just one |
(temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit);
}
void actOnUserInput() {
char input = // ... something that gets a user input. It should check if any is available, otherwise return.
switch (input) {
case 'F':
case 'f':
temperatureChannel[channelID].currentTemperature--;
break; // This doesn't exit the loop - it gets you out of the switch statement
}
void activateAlarm(int channelID) {
// presumably this does something other than call logSubsystem?
// if that's all it does, just call it directly
// note - no loop here
logSubsystem(channelID);
}
void logSubsystem(int channelID) { // Not the current temperature - that's a local value, and you want to set the observed value
// I really think actOnUserInput should be (an early) part of the while loop below.
// It's just another input for the state machine, but I'll leave it here per your design
// Presumably actually logs things, too, otherwise it's an unnecessary function
actOnUserInput();
}
while (TRUE) { // this is the main loop of your function, and shouldn't exit unless the program does
// do anything else you need to - check other stuff
// maybe have a for loop going through different channelIDs?
if (checkTemperatureValuesOutOfRange(channelID)) {
activateAlarm(channelId);
// do anything else you need to
}
I'm sure you can see lots of differences between your code and mine. Here are some key things to consider:
All the functions now return. The master while loop calls functions that check status, and calls function that change status.
I would highly suggest acting on the user input as part of the master while loop. It's just another input to the state machine. Get it, act on it, and then check your statuses. You presumably need to have some input from the user, otherwise you'll never get in a bad state in the first place.
Right now, activate alarm happens every time. With the code you showed, that's fine - because logSubsystem was all that was being called. If you only want the alarm to ring once, keep a boolean tracker inside temperatureChannel[channelId] that says if the alarm rang, set it true within activateAlarm, and then reset it to false based on the return value of checkTemperatureValuesOutOfRange.
Rather than leaving yourself in the activateAlarm/logSubsystem area, you return each time, and check your values each time to see if you're still there. This is the key point - your functions should be fast, and not monopolize your processor. Make each function do just one sort of thing, and have all the control come from within the master loop.
I made a lot of changes to your code, and I don't know if you're allowed to make all of them, but you'll need something similar to this. It's much more robust, and gives you room to grow all around.
Hey all I've asked this question a few times in the past few days but I just don't get it...I basically want to have the while loop for the Beep command executed in the background while the user can interact with the available case statements (only one shown..there are others)....i keep getting blocked and everytime i want the beep to make a sound constantly i block the rest of my program...I have to use Beep so please don't suggest any other functionality..
here's a sample code...
while( keypress != 'q' || keypress != 'Q')
{
x = Beep(x);
while (x == 1)
Beep(350,300);
alarm_t current;
keypress = _getch();
switch(keypress){
case 'h':
sprintf_s(current.message,"high alarm");
current.timeOfEvent = time(NULL);
recordEvent(current);
break;
Now...my issue is with the while loop and the Beep command....here is what i call to Beep(x)
int Beep(int y)
{
return y;
}
So basically i am trying to call a function outside of my current cpp file to just compare x and y, and return y as being equivalent to x...i thought this might avoid blocking but it doesn't...
Your while loop around beep just won't work and _getch is blocking. So it will just block until there's a character.
Depending what platform you are on, you need something like kbhit (and if you google that you will find alternatives for other platforms). ie it's not standard C functionality and platform specific.
kbhit will return true or false depending if there is a character or not.
So you can do:
while(!key_is_quit(ch))
{
Beep();
if(kbhit())
{
ch = getch();
// switch....
}
}