sas if then else statement - if-statement

I have this code below, I need it to set elig_factor[2] to 1 when status is =1 and hudadmin is in 1 or 2 or 3 else set elgi_factor[2] =0. But it sets elig_factor[2] = 0 anyway. Can someone please help?
if ("&r_start" eq 1) then
do;
if ( 2011<=built <= 2014) then elig_factor[1] = '1';
else elig_factor[1] = '0';
if (status eq '1' and hudadmin eq '1') then elig_factor[2] = '1';
else elig_factor[2] = '0';
if (status eq '1' and hudadmin eq '2') then elig_factor[2] = '1';
else elig_factor[2] = '0';
if (status eq '1' and hudadmin eq '3') then elig_factor[2] = '1';
else elig_factor[2] = '0';
if (np_all gt 0) then elig_factor[3] = '1';
else elig_factor[3] = '0';
if (np_black gt 0) then elig_factor[4] = '1';
else elig_factor[4] = '0';
if (np_age65 gt 0) then elig_factor[5] = '1';
else elig_factor[5] = '0';
if (np_hisp gt 0) then elig_factor[6] = '1';
else elig_factor[6] = '0';
elig_factor[7] = occ;
elig_factor[8] =vac;
end;

You almost answered the question yourself when you said:
when status is =1 and hudadmin is in 1 or 2 or 3
I'm not sure why you haven't used the in operator here.
Anyway, to explain what your code is actually doing:
if (status eq '1' and hudadmin eq '1') then elig_factor[2] = '1';
else elig_factor[2] = '0';
if (status eq '1' and hudadmin eq '2') then elig_factor[2] = '1';
else elig_factor[2] = '0';
if (status eq '1' and hudadmin eq '3') then elig_factor[2] = '1';
else elig_factor[2] = '0';
Each if statement is evaluated in turn, ignoring the results of the past if statements. So, if you have a situation where hudadmin = 1 then the first if statement is triggered, setting elig_factor[2] to '1', the subsequent else is ignored.
When the second if statement is reached, it is checked and found to be FALSE, so the else statement is run, setting elig_factor[2] to '0', despite having previously set it to '1'.
So you have two options:
Amend your code so it does what you want
if (status eq '1' and hudadmin eq '1') then elig_factor[2] = '1';
else if (status eq '1' and hudadmin eq '2') then elig_factor[2] = '1';
else if (status eq '1' and hudadmin eq '3') then elig_factor[2] = '1';
else elig_factor[2] = '0';
This checks if hudadmin = '1', if not then it checks if hudadmin='2', if not then '3', only once it has checked hudadmin is not '1','2' or '3' then it will set elig_factor[2] = '0'.
The code is sound, but a little over engineered, I would go with the following approach
Use the in operator
if (status eq '1' and hudadmin in ('1','2','3')) then elig_factor[2] = '1';
else elig_factor[2] = '0';
This checks the condition in one statement, is easier to read, and is arguably more efficient.

This is actually even easier if you use the boolean results. The only difference below is that it returns numeric results - if you must have '1' then put each of these to a character or wrap each of them in cats.
if ("&r_start" eq 1) then
do;
elig_factor[1] = ( 2011<=built <= 2014) ;
elig_factor[2] = (status eq '1' and hudadmin in ('1','2','3'));
elig_factor[3] = (np_all gt 0) ;
elig_factor[4] = (np_black gt 0);
elig_factor[5] = (np_age65 gt 0);
elig_factor[6] = (np_hisp gt 0);
elig_factor[7] = occ;
elig_factor[8] = vac;
end;

Related

How can I switch what points on an array equal in c++?

These change the array that I print to the screen. direc is an input before this. However, when array[1][2] == '#', it still moves '#' to array[1][0].
if (array[1][1] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '_';
array[1][0] = '#';
}
else {
if (array[1][1] == '#' && direc == 'D' || direc == 'd' ) {
array[1][1] = '_';
array[1][2] = '#';
}
else {
if (array[1][2] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '#';
array[1][2] = '_';
}
}
}
You can either add parentheses, as already noted in the comments, like this
if (array[1][1] == '#' && (direc == 'A' || direc == 'a' )) {
Alternatively you could use std::tolower in which case you no longer nee
if (array[1][1] == '#' && std::tolower(direc) == 'a') {
You could still add extra parentheses if you are not comfortable that operator && is lower precedence than operator ==
(the full table of operator precedences can be seen here)

how do you change arrays?

help! im trying to replace 'a' and 'e' with ' ' in my array but it keeps replacing all of the array instead.
for(int x = 0; x < array_length); x++)
{
if(city_name[x] == 'a' || 'e')
city_name[x] = " ";
}
if(city_name[x] == 'a' || 'e')
should be
if(city_name[x] == 'a' || city_name[x] == 'e')
Your code is equivalent to
if( ( city_name[x] == 'a' ) || 'e')
which does city_name[x] == 'a' and then checks the result of that statement || 'e'
First of all the loop is wrong. it contains a typo
for(int x = 0; x < array_length); x++)
^^^
Remove the redundant parenthesis.
Also this condition
city_name[x] == 'a' || 'e'
is always equal to true because it is equivalent to
( city_name[x] == 'a' ) || 'e'
And instead of string literal " " you have to use character literal ' '
The correct loop can look like
for ( int i = 0; i < array_length; i++ )
{
if ( city_name[i] == 'a' || city_name[i] == 'e' ) city_name[i] = ' ';
}
Take into account that there is standard algorithm std::replace_if declared in header <algorithm> that can be used instead of the loop. For example
std::replace_if( city_name, city_name + array_length,
[]( char c ) { return c == 'a' || c == 'e'; },
' ' );

Program to count evens odds vowels and consonants in a string

Hello i don't know how to fix my program to find how many evens, odds, vowels and consonants are in my string.
The program compiles and runs but i never get any vowels or consonants and everything else is added in either evens or odds (even characters).
Edit 1: By evens and odds i mean like if the user types in the string John123 i want to find how many characters are vowels in this case 1 the 'o' how many are consonants in this case 3 the 'J', 'h', 'n' how many are evens in this case 1 the '2' and how many are odds in this case 2 the '1' and the '3'.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s1;
int evens = 0; //
int odds = 0; //
int vowels = 0; //
int consonants = 0; //
cout << "Please type in Something: ";
getline(cin, s1);
cout << "You typed: " << s1 << endl;
for(int i = 0; i < s1.size(); ++i)
{
if((s1[i] % 2) == 0 )
{
++evens;
}
else if((s1[i] % 2 ) != 0) // What would an algorithm (formula) be to find when a number is odd without the not-equals != ?
{
++odds;
}
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
{
++vowels;
}
else if(s1[i] == 'Q' || 'W' || 'R' || 'T' || 'Y' || 'P' || 'S' || 'D' || 'F' || 'G' || 'H' || 'J' || 'K' || 'L' || 'Z' || 'X' || 'C' || 'V' || 'B' || 'N' || 'M'||
'q' || 'w' || 'r' || 't' || 'y' || 'p' || 's' || 'd' || 'f' || 'g' || 'h' || 'j' || 'k' || 'l' || 'z' || 'x' || 'c' || 'v' || 'b' || 'n' || 'm')
// I specify every letter so that it dosn't pick whitespaces, symbols etc.
{
++consonants;
}
}
cout << "Evens in string are: " << evens << "\nOdds in string are: " << odds << "\nVowels in string are: " << vowels << "\nConsonants in string are: " << consonants;
return 0;
}
if((s1[i] % 2) == 0 )
This code is not correct. You are modulating the character, which isn't what you want. You want to first convert the character to an integer using atoi or something like that, I can't remember the function. (Just look up string to int c++). Then, once you've converted the character to an integer, then you can modulate it correctly.
Also, your || syntax is totally wrong, as Jongware mentioned. You need to have an == comparison for each character.
Should look like this (very long):
(s1[i] == 'A' || s1[i] == 'a' || s1[i] == 'E' || s1[i] == 'e' || s1[i] == 'O' || s1[i] == 'o' || s1[i] == 'I' || s1[i] == 'i' || s1[i] == 'U' || s1[i] == 'u')
You might want to store s1[i] in a char beforehand so it's more concise.
And you should place your character testing BEFORE the odd/even testing, so that you don't accidentally try and convert h or another non-numeric character to an integer.
A char is a number. For example, a is (on most computers) the ASCII code 97. So either your even test or your odd test will always match. You need to rearrange your if blocks.
Also, your character tests don't do what you intended. s1[i] == 'A' || 'a' tests as true whenever s1[i] is equal to 'A' or whenever 'a' as a number is not zero. But 97 is never zero, so that test will always result in true. You need code more like s1[i] == 'A' || s1[i] == 'a', testing the s1[i] value each time.
(One way to make things simpler: Once you know the character is not a vowel, you can test for an ASCII consonant with ((s1[i] >= 'a' && s1[i] <= 'z') || (s1[i] >= 'A' && s1[i] <= 'Z')).)
You have basically two problems:
Characters are interpreted as numbers, taking into account the character code. When you are checking whether the character is even or odd, you are checking its character code which will always be either event of odd, this is why your code will always enter into the first or second case. You must check whether your character is digit and if so, you must check whether it is even
Your OR is incorrect, see Ruby van Soelen's answer
Suggested, untested code:
for(int i = 0; i < s1.size(); ++i)
{
if (isdigit(s1[i])) {
if ((s1[i] == '0') || (s1[i] == '2') || (s1[i] == '4') || (s1[i] == '6') || (s1[i] == '8'))
{
++evens;
}
else // What would an algorithm (formula) be to find when a number is odd without the not-equals != ?
{
++odds;
}
}
else
{
if(s1[i]=='A' || s1[i]=='a' || s1[i]=='E' || s1[i]=='e' || s1[i]=='O' || s1[i]=='o' || s1[i]=='I' || s1[i]=='i' || s1[i]=='U' || s1[i]=='u')
{
++vowels;
}
else if(s1[i]=='B' || s1[i]=='b' || s1[i]=='C' || s1[i]=='c' || s1[i]=='D' || s1[i]=='d' || s1[i]=='F' || s1[i]=='f' || s1[i]=='G' || s1[i]=='g' || s1[i]=='H' || s1[i]=='h' || s1[i]=='J' || s1[i]=='j' || s1[i]=='K' || s1[i]=='k' || s1[i]=='L' || s1[i]=='l' || s1[i]=='M' || s1[i]=='m' || s1[i]=='N' || s1[i]=='n' || s1[i]=='P' || s1[i]=='p' || s1[i]=='Q' || s1[i]=='q' || s1[i]=='R' || s1[i]=='r' || s1[i]=='S' || s1[i]=='s' || s1[i]=='T' || s1[i]=='t' || s1[i]=='V' || s1[i]=='v' || s1[i]=='X' || s1[i]=='x' || s1[i]=='Y' || s1[i]=='y' || s1[i]=='Z' || s1[i]=='z')
// I specify every letter so that it dosn't pick whitespaces, symbols etc.
{
++consonants;
}
}
}
Your || syntax is making no sence, what you currently have is something like this
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
while it should be like this:
else if(s1[i]=='A' || s1[i]=='a' || s1[i]=='E' || s1[i]=='e' || s1[i]=='O' || s1[i]=='o' || s1[i]=='I' || s1[i]=='i' || s1[i]=='U' || s1[i]=='u')
Expression in the else-if statement will be always equal to true
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
becuase it is equivalent to
( s1[i] == 'A' ) || 'a' || 'B' /*...*/
where 'a' as it is not equal to zero evaluates to true.
So you have to write at least like
s1[i] == 'A' || s1[i] == 'a' || s1[i] == 'B' /*...*/
Also take into account that for example character 'B' though is not a digit but its code is even. So you will get a wrong result if will start checks from statement
if((s1[i] % 2) == 0 )
You should check at first whether the character is a digit. Also you could define an array of vowels and consonants and use standard function strchr that to check whether a character is a vowel or consonant.
For example
#include <iostream>
#include <string>
#include <cctype>
//...
const char *alpha_vowels = "AEIOU";
const char &alpha_consonants = "BCD...";
//...
if ( std::isdigit( s[i] ) )
{
s[i] % 2 == 0 ? ++evens : ++odds;
}
else if ( std::strchr( alpha_vowels, std::toupper( ( unsigned char )s[i] ) ) != nullptr )
{
++vowels;
}
else if ( std::strchr( alpha_consonants, std::toupper( ( unsigned char )s[i] ) ) != nullptr )
{
++consonants;
}
In addition to the other answers, here's a simpler way to accomplish the same thing.
std::set<char> vs{'a', 'o', 'u', 'e', 'i'};
for (auto&& c : s1) {
if (std::isdigit(c))
if ((c - '0') % 2 == 0) // Trick to convert numeric char -> int.
++evens;
else
++odds;
else if (std::isalpha(c))
if (vs.count(std::tolower(c)))
++vowels;
else
++consonants;
}

Why does my program only change some of the letters

So, I am trying to make a ROT13decoder, and this is what I have so far. Only some of the letters change though and I am not sure why. I'm very new to programming. I am just trying to figure out how to read in files, and write to files. So far that part works, but yeah it doesn't change all the letters in the original file, just some of them. I would really appreciate any feedback.
#include <iostream>
#include <fstream>
//the letters in the secretMessage file are "Lbh unir gb fgnl va funcr. Zl tenaqzbgure, fur fgnegrq jnyxvat svir zvyrf n qnl jura fur jnf 60. Fur’f 97 gbqnl naq jr qba’g xabj jurer gur uryy fur vf
//
//
//and this is what it outputs to the decodedMessage file "Lbh haie gb fgal ia fhace. Ml geaadmbghee, fhe fgaeged jalkiag fiie milef a dal jhea fhe jaf 60. Fhe’f 97 gbdal aad je dba’g kabj jheee ghe hell fhe if.
using namespace std;
int main(){
ofstream fout;
ifstream fin;
fin.open("secretMessage.txt");
fout.open("decodedMessage.txt");
char c = 0;
while (!fin.eof()){
c = fin.get();
if (c == 'a')c = 'n';
if (c == 'b')c = 'o';
if (c == 'c')c = 'p';
if (c == 'd')c = 'q';
if (c == 'e')c = 'r';
if (c == 'f')c = 's';
if (c == 'g')c = 't';
if (c == 'h')c = 'u';
if (c == 'i')c = 'v';
if (c == 'j')c = 'w';
if (c == 'k')c = 'x';
if (c == 'l')c = 'y';
if (c == 'm')c = 'z';
if (c == 'n')c = 'a';
if (c == 'o')c = 'b';
if (c == 'p')c = 'c';
if (c == 'q')c = 'd';
if (c == 'r')c = 'e';
if (c == 's')c = 'f';
if (c == 't')c = 'g';
if (c == 'u')c = 'h';
if (c == 'v')c = 'i';
if (c == 'w')c = 'j';
if (c == 'x')c = 'k';
if (c == 'y')c = 'l';
if (c == 'z')c = 'm';
if (c == 'A')c = 'N';
if (c == 'B')c = 'O';
if (c == 'C')c = 'P';
if (c == 'D')c = 'Q';
if (c == 'E')c = 'R';
if (c == 'F')c = 'S';
if (c == 'G')c = 'T';
if (c == 'H')c = 'U';
if (c == 'I')c = 'V';
if (c == 'J')c = 'W';
if (c == 'K')c = 'X';
if (c == 'L')c = 'Y';
if (c == 'M')c = 'Z';
if (c == 'N')c = 'A';
if (c == 'O')c = 'B';
if (c == 'P')c = 'C';
if (c == 'Q')c = 'D';
if (c == 'R')c = 'E';
if (c == 'S')c = 'F';
if (c == 'T')c = 'G';
if (c == 'U')c = 'H';
if (c == 'V')c = 'I';
if (c == 'W')c = 'J';
if (c == 'X')c = 'K';
if (c == 'Y')c = 'L';
if (c == 'Z')c = 'M';
cout << c;
if (!fin.eof())fout << c;
}
fin.close();
fout.close();
return 0;
}
Most letters in your example will be flipped twice. You either need to add a whole lot of 'else' commands or use a switch statement.
if (c == 'a')c = 'n';
else if (c == 'b')c = 'o';
There is a better, mathematical method; but I'll leave that as an exercise to the reader.
You have a logic error. If you start with "a" the first IF turns it into "n" and a later IF turns it back into "a".
Have a look at the switch statement.
you should not use if conditions everywhere as each of them will be checked as you have a new row. Suppose your character is l then your if statement changes the letter to y but the condition for y is also checked so the character is changed back to l. So in fact your code is not not changing some of the letters, it is changing them twice.
You should be able to cure this using else if for the subsequent entries so that when one is true the other ones don't get checked, or you could use a switch case.
Take a single letter encoded in ROT13. If you encode it twice, you end up with the original letter again, which makes encoding and decoding ROT13 practically the same.
Now take for example the letter 'a'. What you are doing above in your code is
if (c == 'a') c = 'n';
...
if (c == 'n') c = 'a';
So for the first half of the letters above (a to m), you're encoding twice, getting the same letter again. Only for the lower half of the letters the encoding is only done once.
One solution to this would be to change your statements to something like
if (c == 'a') { c = 'n'; continue; }
This would skip the rest of the code in case of a match and continue with the next loop iteration.

Why isn't my or statement working, C++?

I'm trying to create a function that will replace 0's, 1's, or 2's with spaces in a string. I'm going about it by iterating through the string and comparing each individual character.
My function will work if I compare str_in[i] == '0', but if I add the or statement it returns nothing.
Snippet:
string omit_num( string ) {
int i ;
str_len = str_in.length();
str_out = "" ;
for( i = 0 ; i < str_len ; i ++ ){
cout << str_in[i] << endl;
if ( str_in[i] == '0' || '1' || '2')
app = " " ;
else
app = str_in[i];
str_out.append(app) ;
}
return str_out;
}
You need
if ( str_in[i] == '0' || str_in[i] =='1' || str_in[i] =='2')
You will have to repeat the test each time, '1', '2' on their own are basically small ints and evaluate to true. It should look like the following:
if (str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2')
The expression str_in[i] == '0' || '1' || '2' contains three separate expressions:
str_in[i] == '0'
'1'
'2'
According to any ASCII chart, '0' has a value of 48, '1' is 49, '2' is 50. So the last two expressions are always non-zero (and therefore always true).
You probably wanted str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2'
if (str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2')
or alternatively
switch (str_in[i]) {
case '0':
case '1':
case '2': app = " " ;
break;
default: app = str_in[i];
}
Your if statement reads as follows: If the character at i is equal to '0', or '1' is true, or '2' is true. As '1' and '2' both evaluate to a non zero integer, it will always be true.
What you want is: str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2'
'1' is '1' therefore '1' evaluates to true. You must make new, complete, statements with every operator.
try this:
if ( str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2' )
Not sure about the logic overall, but the logic here specifically is wrong. Replace
if ( str_in[i] == '0' || '1' || '2')
with
if ( str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2')
Change your if statement to:
if ( str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2') {
...
}
string omit_num( string ) {
int i ;
str_len = str_in.length();
str_out = "" ;
for( i = 0 ; i < str_len ; i ++ ){
cout << str_in[i] << endl;
if ( str_in[i] == '0' || '1' || '2')
app = " " ;
else
app = str_in[i];
str_out.append(app) ;
}
return str_out;
}
this would work as the following:
string omit_num( string ) {
int i ;
str_len = str_in.length();
str_out = "" ;
for( i = 0 ; i < str_len ; i ++ ){
cout << str_in[i] << endl;
if ( (str_in[i] == '0') || (str_in[i] == '1') || (str_in[i] == '2'))
app = " " ;
else
app = str_in[i];
str_out.append(app) ;
}
return str_out;
}
You need to apply the equality operator in each || expression:
if (str_in[i] == '0' || str_in[i] == '1' || str_in[i] == '2')
If you're using c++, use the standard library already:
std::replace_if( s.begin(), s.end(), [](char a){return a=='0'||a=='1'||a=='2';}, ' ');