I have this function "path" that takes 3 arguments:
path::String->String->String->IO()
path place1 dir place2 =
if place1 == "bedroom" && d == 'n' && place2 == "den"
then do
putStrLn "You are in a bedroom with a large, comfortable bed. It has been a long, tiresome day, and you would like nothing better than to go to sleep."
else
if place1 == "bedroom" && d == 'd' && place2 == "bed"
then describe "bed"
else
if place1 == "den" && d == 's' && place2 == "bedroom"
then describe "bedroom"
else
if place1 == "bed" && d == 'u' && place2 == "bedroom"
then describe "bedroom"
else putStrLn "Cannot go there!"
I want to know how if this is the correct way of having multiple conditions and multiple if statements?
It's not incorrect, but it is not idiomatic (i.e. customary style). Usually we prefer guards to if-then-else, like in #user5402's answer. However in your case you are also just comparing to constant literals with ==, which means the best way is to take it one step further and use pattern matching (I formatted it a bit prettier too):
path :: String -> String -> String -> IO ()
path "bedroom" "n" "den" = putStrLn "You are in a bedroom with a large, comfortable bed. It has been a long, tiresome day, and you would like nothing better than to go to sleep."
path "bedroom" "d" "bed" = describe "bed"
path "den" "s" "bedroom" = describe "bedroom"
path "bed" "u" "bedroom" = describe "bedroom"
path _ _ _ = putStrLn "Cannot go there!"
Consider using guards, e.g.:
path :: String -> String -> String -> IO ()
path place1 d place2
| place1 == "bedroom" && d == "n" && place2 == "den"
= putStrLn "You are in a bedroom ..."
| place1 == "bedroom" && d == "d" && place2 == "bed"
= describe "bed"
| place1 == "den" && d == "s" && place2 == "bedroom"
= describe "bedroom"
| place1 == "bed" && d == "u" && place2 == "bedroom"
= describe "bedroom"
| otherwise = putStrLn "Cannot go there!"
Note that String literals an enclosed in double quotes.
Related
This is the prompt for my script:
Script that asks the user “Are you OK?”
If user replies y or Y, then say “glad to hear it” else if the user enters n or N then print “sorry that you are not feeling good”. If the user enters some other character, then print in-correct choice and ask the question again.
Here's what I have:
#! /bin/csh
echo "Are you OK? "
set n = $<
set loop = 1
if (("$n" == "y") || ("$n" == "Y")) then
echo "glad to hear it"
else if (("$n" == "n") || ("$n" == "N")) then
echo "sorry that you are not feeling good"
else
echo "in-correct choice"
while ( $loop == 1 )
echo "Are you OK? "
set n = $<
if (("$n" == "y") || ("$n" == "Y")) then
echo "glad to hear it"
set loop = 0
else if (("$n" == "n") || ("$n" == "N")) then
echo "sorry that you are not feeling good"
set loop = 0
else
echo "in-correct choice"
endif
end
endif
I keep receiving the error "else: endif not found." Also the echo line "glad to hear it" runs every time regardless if the user input is right or not. Please help. Thank you
Just add new line after Your last endif statement:
...
end
endif
#new line
Or I recommend always end csh scripts with exit status and You should be good to go:
...
end
endif
exit (0)
Anyway here is also little rewrite of Your script:
#!/bin/env csh
while (1)
echo "Are you OK?"
set n = "$<"
if (("$n" == "y") || ("$n" == "Y")) then
echo "glad to hear it"
break
else if (("$n" == "n") || ("$n" == "N")) then
echo "sorry that you are not feeling good"
break
else
echo "in-correct choice"
endif
end
exit (0)
set n = $< here is danger better set n = "$<" in order not to handle e.g. string y abc as yes
i'm extremely rusty with C and when trying to compile this i keep getting the error: "lvalue required as left operand of assignment" in each of the three nested ifs.
i'm pretty sure i'm doing some really dumb and basic mistake but i can't manage to fix it!
also the code is extremely naive, is there a better way to check the various strings in argv (they must be 6 charachters long, the first 2 charachters must be either IC, FR or RG and then the other 4 should be a numeric code) and print the correct strings?
int main(int argc, char *argv[]){
int i=1;
while(i < argc){
if(strlen(argv[i]) == 6){
if(argv[i][0] == 'I' && argv[i][1] = 'C' && argv[i][2] >= '0' && argv[i][2] <= '9' && argv[i][3] >= '0' && argv[i][3] <= '9' && argv[i][4] >= '0' && argv[i][4] <= '9' && argv[i][5] >= '0' && argv[i][5] <= '9'){
printf("%s", argv[i]);
}
if(argv[i][0] == 'F' && argv[i][1] = 'R' && argv[i][2] >= 0 && argv[i][2] <= 9 && argv[i][3] >= 0 && argv[i][3] <= 9 && argv[i][4] >= 0 && argv[i][4] <= 9 && argv[i][5] >= 0 && argv[i][5] <= 9){
printf("%s", argv[i]);
}
if(argv[i][0] == 'R' && argv[i][1] = 'G' && argv[i][2] >= 0 && argv[i][2] <= 9 && argv[i][3] >= 0 && argv[i][3] <= 9 && argv[i][4] >= 0 && argv[i][4] <= 9 && argv[i][5] >= 0 && argv[i][5] <= 9){
printf("%s", argv[i]);
}
}
i++;
}
return(0);
}
EDIT: Damn this was a pretty dumb question, wrote = instead of == in the second assignment. thanks for the help!
It's because you have a typo in your second tests in each if, having written = (assignment of a value) instead of == (test for equality).
The error message is correct but not intuitive. The compiler interprets your code as follows (note the extra parentheses I inserted):
if ((arg[0] == 'C' && arg[1]) = 'I') {}
This is because && binds more tightly than =. Replace the = with ==, and you're fine.
You should write a helper function:
static bool parse_number(const char *arg, char ch1, char ch2, int *pnum) {
if (arg[0] == ch1 && arg[1] == ch2 && '0' <= arg[2] && arg[2] <= '9') {
char *end;
unsigned long num = strtoul(arg + 2, &end, 10);
if (*end == '\0' && end - arg == 6) {
*pnum = (int)num;
return true;
}
}
return false;
}
Then you can use it like this:
int num;
if (parse_number(argv[i], 'I', 'C', &num)) {
printf("IC number %d\n", num);
}
My old code was:
let comps = split(str, { $0 == "-" || $0 == " " }, maxSplit: Int.max, allowEmptySlices: false)
after update of Swift 2 my XCode 7 fix it to:
let comps = split(str.characters, { $0 == "-" || $0 == " " }, maxSplit: Int.max, allowEmptySlices: false).map { String($0) }
but now I have an error: Cannot invoke 'map' with an argument list of type '((_) -> _)'
How to fix it.
Link to old answer on Swift
The order of arguments for split() function messed up for some reason. It should be:
let comps = split(str.characters, maxSplit: Int.max, allowEmptySlices: false) {
$0 == "-" || $0 == " "
}.map {
String($0)
}
I have a shell script that is doing something.I want to print the Unknown string where there is blank space in the output.
I want to do check if (f[1] == "") or (f[2] == "") or (f[3] == ""), it should be replaced by a unknown string and should be written in a single file
if(f[1] == "") printf(fmt, id, f[1], f[2], f[3]) > file
where f[1],f[2],f[3] if empty should be replaced by unknown string
where f[1] is the first index, fmt is the format specifier I have defined in the code.How to replace these empty spaces with a string in Linux.
Any lead is appreciated.
Thanks
Use the conditional operator:
ec2-describe-instances | awk -F'\t' -v of="$out" -v mof="$file" '
function pr() { # Print accumulated data
if(id != "") { # Skip if we do not have any unprinted data.
printf(fmt, id, f[1], f[2], f[3]) > of
if (f[1] == "" || f[2] == "" || f[3] == "") {
printf(fmt, id, f[1]==""?"Unknown":f[1], f[2]==""?"Unknown":f[2], f[3]==""?"Unknown":f[3]) > mof
}
}
# Clear accumulated data.
id = f[1] = f[2] = f[3] = ""
}
BEGIN { # Set the printf() format string for the header and the data lines.
fmt = "%-20s %-40s %-33s %s\n"
# Print the header
headerText="Instance Details"
headerMaxLen=100
padding=(length(headerText) - headerMaxLen) / 2
printf("%" padding "s" "%s" "%" padding "s" "\n\n\n", "", headerText, "") > of
printf(fmt, "Instance id", "Name", "Owner", "Cost.centre") > of
printf("%" padding "s" "%s" "%" padding "s" "\n\n\n", "", headerText, "") > mof
printf(fmt, "Instance id", "Name", "Owner", "Cost.centre") > mof
}
$1 == "TAG" {
# Save the Instance ID.
id = $3
if($4 ~ /[Nn]ame/) fs = 1 # Name found
else if($4 ~ /[Oo]wner/) fs = 2 # Owner found
else if($4 ~ /[Cc]ost.[Cc]ent[er][er]/) fs = 3 # Cost center found
else next # Ignore other TAGs
f[fs] = $5 # Save data for this field.
}
$1 == "RESERVATION" {
# First line of new entry found; print results from previous entry.
pr()
}
END { # EOF found, print results from last entry.
pr()
}'
I have a sign function, which can return an error.
signe :: Int -> Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = '+'
| chiffre == 0 = '0'
| chiffre >= -9 && chiffre <= (-1) = '-'
| otherwise = error "Erreur in the sign"
I'd like to make a simple one to return the corresponding code of the sign, but with error handling.
signes liste = [ signe x | x<-liste ]
I give you an example : For now, if I call
signes [1,3,0,-10]
it gives me
++0*** Exception: Error in sign.
I'd like to have nothing instead of Exception: ++0.
You can, and should, use Maybe in such cases:
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Just '+'
....
| otherwise = Nothing -- parbleu!!
signes = mapMaybe signe
You may need to import Data.Maybe for the mapMaybe function.
A better way would be to actually use the Maybe type which lets you literally return Nothing or Just aValue. You could rewrite your function as
signe :: Int -> Maybe Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Just '+'
| chiffre == 0 = Just '0'
| chiffre >= (-9) && chiffre <= (-1) = Just '-'
| otherwise = Nothing
The problem already seems to be answered by Ingo, but I wanted to point out that since you had an error message in the original question, perhaps "Either" would be a better choice here
signe :: Int -> Either String Char
signe chiffre
| chiffre >= 1 && chiffre <= 9 = Right'+'
| chiffre == 0 = Right '0'
| chiffre >= -9 && chiffre <= (-1) = Right '-'
| otherwise = Left "Erreur in the sign"
where you can get the filtered list with
signes liste = [ x | Right x<-map signe liste ]
Both Maybe and Either are used for error checking, Either gives you the ability to pass an "Exception" up the call chain.