I need to use boolen expressions instead of using terms such as: c: b? A, switch, else ... if. and using for / while-do / while as if is also not allowed.
My question is when receiving a name, based on its value we decide what to print. For example, if the name is shorter than 6 letters we print "player A is sent", if the letters sum (in ascii values) is more than 20 we send player B and stuff like that. In addition, if we can send more than one player, we will choose to send the largest lexicographic player (playerC < playerB < playerA.)
what I tried to do is something like this
bool sum = AsciiSum(name)>=20;
bool len = NameLength(name)<6;
...
so the rest should be that
if(sum)
printf("%c\n" ,'playerA');
else if (len)
printf("%c\n" ,'playerB');
else
printf("%c\n" ,'no player was sent');
But as I said , I cant use if and else or similar conditions. Will be grateful for any help in that last part.
One way of doing this would be to reroute your input through a custom print function which return a boolean value. That was, you could then just use the AND (&&) operator to call it.
Example code:
bool printMessage(char* string)
{
printf("%s", string);
return true;
}
bool sum = AsciiSum(name)>=20 && printMessage("playerA");
bool len = NameLength(name)<6 && printMessage("playerB");
// ... etc
Why does this work? The AND operator will only allow the next condition to be checked if the first one was true. Since your condition is that sum must be true in order to print the message, this is a way to call the method to print without directly using any if/else statements
Edit: An even better way, as suggested by Johnny Mopp is to use stdio puts(), which returns an integer (that's what a boolean is functionally).
bool sum = AsciiSum(name)>=20 && puts("playerA");
bool len = NameLength(name)<6 && puts("playerB");
With this, you don't even have to create a printMessage function, though you should stay with whichever feels more comfortable to work with.
Given an output function that always returns true :
bool print( const char* msg )
{
puts( msg ) ;
return true ;
}
You can then exploit short-circuit evaluation thus:
bool sum = AsciiSum(name)>=20;
bool len = NameLength(name)<6;
(sum && print("playerA")) ||
(len && print("playerB")) ||
print("no player was sent") ;
Testing all combinations thus:
bool sum = false, len = false ;
(sum && print("playerA")) || (len && print("playerB")) || print("no player was sent") ;
sum = false, len = true ;
(sum && print("playerA")) || (len && print("playerB")) || print("no player was sent") ;
sum = true, len = false ;
(sum && print("playerA")) || (len && print("playerB")) || print("no player was sent") ;
sum = true, len = true ;
(sum && print("playerA")) || (len && print("playerB")) || print("no player was sent") ;
correctly outputs:
no player was sent
playerB
playerA
playerA
Your compiler may issue a diagnostic regarding the result of the expression being unused; that can be supressed by a dummy assignment:
bool dummy = (sum && print("playerA")) ||
(len && print("playerB")) ||
print("no player was sent") ;
or by casting the whole expression to void:
(void)((sum && print("playerA")) ||
(len && print("playerB")) ||
print("no player was sent")) ;
The only requirement of the output function is that it returns a non-zero value to short-circuit the ||, to that end printf() will work if the message is not an empty string, and avoid the need to define a specific output function.:
(void)((sum && printf("playerA\n")) ||
(len && printf("playerB\n")) ||
printf("no player was sent\n")) ;
puts() however only guarantees to return a non-negative value on success, which includes zero, so should not be used.
Related
I wanted to ask if its possible to have 1 array with two conditions for it to meet?
lets just say the arrays are
//gi.move2[10] = 1,1,1,1,1,1,1,0,1,1
//gi.move3[10] = 1,1,1,1,1,1,1,0,1,1
//pi.move1 [10] = 2,3,4,5,6,7,0,8,1,8
scanf("%d",&pi.move1[k]); // user will input 8 thus resulting a &pi.move[7] = 8
for (i = 0; i <= 10; i++)
{
if (pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
{
printf("x");
}
else
{
printf("-");
}
}
I tied the code above, but
I have the structure of gi.move2, gi. move3 and pi.move 1// I have no problems with those.
I am not sure how to show that this statement is true
(pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
I tried this also didnt work.
if (pi.move1[7] = (gi.move2[7] == 0 || gi.move3[7] == 0))
it gave me xxxx-xxxxx-xx
**
The outcome I'm looking for is
--------X--
and also once 8 has been input it cant be used again.
**
the outcome i get is ----------
Thank you
if (pi.move1[7] = (gi.move2[7] == '0' || gi.move3[7] == '0'))
the single '=' is the first problem i see
try fixing the if logic
I am trying to have the user type in a number between 1 and 8 to print out stuff on screen (height), if the number is lower than 1 or higher than 8 I would like for the program to prompt again for an input instead of it quitting out and say "invalid". I know I have to set it up with do on top and when on the bottom in C, my question is how would I go about it when I have 2 possible outcomes, i.e. too low or too high?
do {
int height = get_int(Height: ");
if (height < 1)
~ ~printf("invalid");
else if (height > 8)
~ ~printf("invalid");
} when(???????)
printf("valid")
The key is Logical OR operator (||) in logical operator.
A logical operator would :
treats its operands as boolean values
treats a non-zero value operand as true
treats a zero value operand as false
operates the boolean algebra on its operands
returns the boolean algebra result
returns 1 for true boolean result
returns 0 for false boolean result
The Logical OR operator (||) :
lhs || rhs
Here, lhs and rhs are the 2 operands of OR(||) operator
The OR operator returns 1 if any of the following conditions is true:
only lhs is true
only rhs is true
both lhs and rhs are true
In other words, the boolean algebra OR result is true if either lhs or rhs is true.
In your example, there are 2 conditions :
height is less than 1
height is larger than 8
if either of them is true, then the result is true (the loop will continue), so the expression in this example would be :
int height; /* move height outside the loop so it can be used in do-while condition */
do {
height = get_int();
if (height < 1)
printf("invalid\n");
else if (height > 8)
printf("invalid\n");
} while(height < 1 || height > 8);
printf("valid\n");
Furthermore, since we have already done the logical condition in the loop, we can just add a flag variable instead:
int flag; /* record the boolean result */
do {
int height = get_int();
if (height < 1) {
printf("invalid\n");
flag = 1;
} else if (height > 8) {
printf("invalid\n");
flag = 1;
} else {
flag = 0; /* !(height < 1 || height > 8) */
}
} while(flag);
printf("valid\n");
Try this to see if it works for you.
If not, leave a comment to tell me what you really want.
#include <stdio.h>
int main()
{
int height = 0;
while (height < 1 || height > 8) {
scanf("%d", &height);
if (height >= 1 && height <= 8) {
break;
} else {
printf("Invalid, please try again.\n");
}
}
printf("Valid.\n");
return 0;
}
A simple way of checking if the user has made an invalid choice would be to use a simple Boolean variable and set it to "false" when an invalid choice is made.
I have modified your own example code to include what I mean here:
bool valid = true;
do {
valid = true; //reset valid to true at the beginning of the loop, otherwise it will remain false when the loop runs again
int height = get_int("Height: ");
if (height < 1)
valid = false; //set valid to false when an invalid choice is made
else if (height > 8)
valid = false; //set valid to false when an invalid choice is made
} while (!valid) //if valid is not true ( or ==false), repeat. If valid is true or not equal to false, don't repeat and continue to the print statement below.
print("valid");
Please note that I used the same get_int function you provided in your post. I am not aware of this function. For ways of reading integers (for example scanf) see other answers in this thread.
I hope this helps you.
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
do {
printf("Enter 0 to quit\n");
printf("Print Enter number between 1 and 8\n");
scanf("%d",&num);
if (num > 8) {
printf("Number to high\n");
} else if (num < 0) {
printf("Number to low\n");
}
if (num == 0) {
printf("You quit the program goodby\n");
} else {
printf("Number within range\n");
}
} while(num != -0);
return 0;
}
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
_Bool check_domain(char *domain) {
int str_count = 0, x = strlen(domain), y = 0;
if (domain[x-1] == '.' || domain[0] == '.'){
return false; //if there is a period at start or end
}
else{
while (domain[y]){
if (str_count==2){
return false; //if 2 consecutive periods
}
if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){ //if character is period or alphanumeric
if (domain[y] == '.'){
str_count += 1;
}
else{
str_count = 0;
}
}
else{ // if character is non period non alphanumeric
return false;
}
y += 1;
}
}
return true;
}
int main(void){
char domain[] = "nus#edu.sg";
printf("%d",check_domain(domain));
}
EDIT:
Thank you for your responses, have a little more clarity on the subject now.
In addition to not having a period at the end or beginning, nor two consecutive periods, there should be no non-period, non-alphanumeric character inside the string.
For reasons I can't figure out, this code fails to return false for cases wherein there are non-period, non-alphanumeric characters inside the string.
Start here
if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
C can't handle statement like n <= X <= m in the way you expect.
C treats this as:
(65<=domain[y]) <= 90
^^^^^^^^^^^^^^^ ^^
bool <= number
So first C will calculate a bool result from 65<=domain[y] and then it will compare that bool to a number. The bool is converted to either 0 or 1 so when comparing with 90, the result is always true.
If you had checked the compiler warnings, you would have seen something like:
main.cpp:18:49: warning: comparison of constant '90' with boolean expression is always true [-Wbool-compare]
18 | if (domain[y] == 46 || 65<=domain[y]<=90 || 97<=domain[y]<=122){
| ^~
which tells you that something is wrong.
You need to write
if (domain[y] == 46 || (65<=domain[y] && domain[y]<=90) || (97<=domain[y] && domain[y]<=122)){
BTW:
Don't use magic numbers like 65, 90 and so on. Use the character instead. Like:
(65<=domain[y] && domain[y]<=90) --> ('A' <= domain[y] && domain[y] <= 'Z')
It makes the code much easier to understand.
Further - consider using the function isalpha(domain[y]) for such checks.
Finally - Your text (and function name) says that that you want to check for a domain name. However, your input is more like an e-mail address.
I have the following code that accepts a string that resembles hours.. I want to check if the string format is actually xx-yy where xx resembles an hour as does yy.. The code worked fine but when I input "02-13-" it returns true but I want it to return false cause it's not correct (cause it has - at the end)
bool hourIsValid(char * hours) {
int openH = 0;
int closeH = 0;
if ((sscanf(hours, "%d-%d", & openH, & closeH) == 2) && openH >= 0 && openH <= 24 && closeH >= 0 && closeH <= 24) {
if (openH >= closeH) {
return false;
}
return true;
} else {
return false;
}
}
The solution depends on how "pedantic" your code has to be when deciding if an input is valid or not. For example, you might expect "2-14", "02 - 15", " 2-14 " as valid, or you might not. It depends.
If you want to get a pedantic version that accepts only the exact format "dd-dd" with no leading or trailing characters or white spaces and with exactly a two-digit format for each hour value, you could check the string as follows before reading in the values with your sscanf-code:
if (strlen(hours) != 5)
return 0;
if (hours[2] != '-')
return 0;
if ( !isdigit(hours[0])
|| !isdigit(hours[1])
|| !isdigit(hours[3])
|| !isdigit(hours[4])
)
return 0;
Another way:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool hourIsValid(
char *I__hours
)
{
long openH, closeH;
openH=strtol(I__hours, &I__hours, 10);
if( '-' != *I__hours // Ensure that there is a dash between the two numbers in the string.
|| 0 >= openH // Ensure that the 1st number in the string is non-negative.
|| 24 <= openH // Ensure that the 1st number in the string is 24 or less.
)
return(false);
++I__hours; // Skip over the dash between the two numbers.
closeH=strtol(I__hours, &I__hours, 10);
if( *I__hours // Ensure that there are no additional characters beyond the 2nd number.
|| 0 >= closeH // Ensure that the 2nd number in the string is non-negative.
|| 24 <= closeH // Ensure that the 2nd number in the string is 24 or less.
|| openH >= closeH // Ensure that the 1st number is less or equal to the 2nd number.
)
return(false);
return(true);
}
I want the loop to exit when both strncmp() and check() return 0, meaning they both found a match. The problem is, when check() returns 0 and strncmp() does not return 0 the loop is exiting.
while (strncmp(buf, match, 3) != 0 && check(buf[3]) != 0)
{
}
I have checked the values in buf and match and they do not match when it exits. buf[3] does match when it exits.
You are using && so you're saying both strncmp(buf, match, 3) and check(buf[3]) != 0 must be met in order for the loop to continue. To get the result you specified you should use ||
This loop runs as long as
buf and match differ somewhere in the first 3 characters, AND
check(buf[3]) is nonzero
Is that what you want? In other words, the loop exits when either
buf and match share the same three initial characters OR
check(buf[3]) is zero
I want the loop to exit when both strncmp() and check() return 0
Then you can rewrite the loop to be very easy to verify against your requirement:
for(;;) {
...
if (strncmp(buf, match, 3) == 0 && check(buf[3]) == 0)
break;
...
}
Now place the negated condition in the controlling expression of the loop:
while (! (strncmp(buf, match, 3) == 0 && check(buf[3]) == 0) ) {
...
}
If you are somewhat into computer science, you realize that not(A and B) is--per de Morgan's Laws--equivalent to (not A) or (not B). This finally yields:
while (strncmp(buf, match, 3) != 0 || check(buf[3]) != 0) {
}
So your error was using && instead of || for the logical operator.
u can try this ...
int c,d;
while ((c=strncmp(buf, match, 3) != 0) && (d=check(buf[3]) != 0))
{}
Description:
strncmp() will return a value that have to store in a var..if u don't do then how it will compare with 0..same as also check().