SAS DATA Step, Why is this simple IF statement not working? - sas

im not getting it,
I have this if statement determine which value to store en tmp variable
%let csvfil= L:\work\sij\ss.csv;
filename ss "L:\work\sij\ss.txt";
data tester;
if a = 1 then
tmp = "infile '" || strip("&csvfil") || "'";
else if a = 2 then
tmp = "infile '" || strip("&csvfil") || "'" || "encoding='windows'";
put tmp;
run;
So When a = 1 it
should put "infile '" || strip("&csvfil") || "'"; in tmp variable
When a is not 1 it should put
tmp = "infile '" || strip("&csvfil") || "'" || "encoding='windows'";
It doesn't happen ?
Then i tried a simple test
this works ok so really i dont get it.
data simse;
a=2;
if a = 1 then
tmp = 'simse';
else
tmp = 'frede';
run;

Your DATA Step does not contain a SET statement, so the data step compiler does not know abouit a variable named a at the if statement. The compiler will 'add' the variable a to the PDV as uninitialized (which means it's value will be the missing value .).
Your log should show
NOTE: Variable a is uninitialized.
Since a missing value does not match the if or the else if clause the tmp variable is never assigned a value.
The compiler does not know about a tmp variable at the point of it's first assignment, so the compiler 'adds' tmp to the PDV with a type and length derived from the type and length of the first expression it is assigned from.
data tester;
if a = 1 then
tmp = "infile '" || strip("&csvfil") || "'";
else if a = 2 then
tmp = "infile '" || strip("&csvfil") || "'" || "encoding='windows'";
put tmp;
run;

Related

How can the symbols be bigger than each other? Or do I not understand something? Could you explain what this code does?

Is it ok to compare symbols with each other?
#include <iostream>
using namespace std;// For Example, Why if "k = 4" it outputs "r o" ? //
int main() {
char word[] = "programming";
int k;
cin >> k;
for (int i = 0; i < k; i++)
if (word[i] > word[i + 1]) {
cout << word[i] << endl;
}
}
The char data type is an integral type, meaning the underlying value is stored as an integer. Moreover, the integer stored by a char variable is intepreted as an ASCII character.
ASCII specifies a way to map english characters(and some other few symbols) to numbers between 0 and 127. That is, each english character(and some other few symbols) has a corresponding number between 0 and 127. This number is formally called a code point.
For example, the code point for the english character a is 97. Similarly, the code point for the english character H is 72. You can find the list of code points for all the characters here.
The important thing to note here is that the underlying value of a char variable is stored as an integer. Lets take some examples to clarify this,
char var1 = 'a'; //here var1 is stored as the integer 97
char var2 = 'H'; //here var2 is stored as the integer 72
In the above snippet, var1 is stored as the integer 97 because the code point for the english character a is 97. Similarly, var2 is stored as the integer 72 because the english character H corresponds to the code point 72.
Now lets come back to your original question. In particular what happens when k =4.
For k = 4, the for loop will be executed 4 times.
Iteration 0: Here i = 0
The if block basically translates to:
if (word[0] > word[0 + 1]) {
cout << word[0] << endl;
}
which is:
if ('p' > 'r') {
cout << 'p' << endl;
}
which is(using the ascii table):
if (112 > 114) {
cout << 'p' << endl;
}
since the condition inside if is false, the body of the if block will not be executed and you'll get no output.
Iteration 1: Here i = 1
The if block basically translates to:
if (word[1] > word[1 + 1]) {
cout << word[1] << endl;
}
which is:
if ('r' > 'o') {
cout << 'r' << endl;
}
which is(using the ascii table):
if (114 > 111) {
cout << 'r' << endl;
}
since the condition inside if is true, the body of the if block will be executed and you'll get r as output(which is followed by a newline).
Iteration 2: Here i = 2
The if block basically translates to:
if (word[2] > word[2 + 1]) {
cout << word[2] << endl;
}
which is:
if ('o' > 'g') {
cout << 'o' << endl;
}
which is(using the ascii table):
if (111 > 103) {
cout << 'o' << endl;
}
since the condition inside if is true, the body of the if block will be executed and you'll get o as output(which is followed by a newline).
Iteration 3: Here i = 3
The if block basically translates to:
if (word[3] > word[3 + 1]) {
cout << word[3] << endl;
}
which is:
if ('g' > 'r') {
cout << 'g' << endl;
}
which is(using the ascii table):
if (103 > 114) {
cout << 'g' << endl;
}
since the condition inside if is false, the body of the if block will not be executed and you'll get no output.
Hence you get the output:
r
o
Is it ok to compare symbols with each other?
Yes, it is OK.
Why if "k = 4" it outputs "r o" ?
Character types are integers. Each integer value of the character type is mapped to a symbol1. This mapping is called a character set or character encoding.
In the character encoding of the system where you ran the program, the value of the character that maps to the symbol 'r' has a greater value than the character that maps to the symbol 'o', while that 'o' character has smaller value than the character that maps to 'g'.
1 This is a simplification. There are special non-printable charcters such as null terminator which aren't symbols as such. Furthermore, the mapping isn't so simple in case of variable length encodings (Unicode).

Why do i keep getting this error when comparing string tokens to another string?

This simple function is meant to check if the string tokens passed are operators or not, if they are return true.
bool isOp(std::string tokens){
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
return true;
}
}
}
However it won't compile and i get an unexpected error that says "ISO C++ forbids comparison between pointer and integer [-fpermissive]", what i don't understand is that i'm not comparing a pointer to an integer, i'm comparing a string to a string? So why do i get this error and how can i fix it?
You're trying to compare single characters, not strings. Replace all your " with ' to make them character constants instead of string literals.

Entering If Statement Despite Not Meeting Condition

This is a specific problem, but I can't seem to figure out what is wrong.
else if (X == 2)
//move left
{
if (Level[X-1][Y] == 0);
{
cout << Level[X-1][Y] << "\n";
cout << "\n MOVING LEFT from RIGHT\n"; //PROBLEM IS HERE
Level[X][Y] = 1; // block it
X = X - 1;
moved = 1;
}
}
What I am doing is I am checking if Level[X-1][Y] is 1, indicating a column, so I can not move my player there. However for some reason, despite it being 1 and not 0 (as indicated by the output), the IF statement is still accessed. Any help will be appreciated.
Your problem is here:
if (Level[X-1][Y] == 0);
^
the ; ends the if statement. What follows the if statement is just a compound statement like this:
{
//Code
}
and are completely valid on their own and have many uses, one use of which is creating a block scope.
For completeness sake if we go to the draft C++ standard section 6.2 Expression Statements we see that the ; just terminates a null statement. The grammar is as follows:
expression-statement:
expressionopt ;
^
and it also says:
[...]An expression statement with the expression missing is called a null statement.[...]
Semi-colon!!!
if (Level[X-1][Y] == 0);
if (Level[X-1][Y] == 0);
// ^
Get rid of this semicolon.
It would make the logic like this: if Level[X-1][Y] is zero, do nothing, then run the following code(the compound statement you thought was belong to the if). It's equivalent to:
if (Level[X-1][Y] == 0)
{
;
}
{
cout << Level[X-1][Y] << "\n";
cout << "\n MOVING LEFT from RIGHT\n";
Level[X][Y] = 1;
X = X - 1;
moved = 1;
}

C++ Assigns Value to Two Strings At Once

unsigned short n = 0;
while (!in.eof())
{
in >> opString; //Read in string from file
//Read the string from file character by character
for (int i = 0; i < opString.size(); i++)
{
if (!op1b) //If we do not yet know our first operand (op1b = false, b stands for bool, clever naming eh?)
{ //Check if our next item is an operator. If it is...
if (!(opString[i] == '+' || opString[i] == '-' || opString[i] == '*' || opString[i] == '/' || opString[i] == '$'))
op1[i] = opString[i];
else //We finally know it since when we hit an symbol, our first number is known; do not repeat this if block
op1b = true;
n++;
}
if (op1b && !operb) //If we know our first operand but not our operator...
{
oper = opString[i]; //Find out what our operator is. Now we know it (operb = true)
operb = true;
i++; //We increment i because if we did not we'd double dip on the if statement below and wind up
} // with an operator tacked onto the beginning of the second operand
if (op1b && operb) //If we know our first operand and the operation, let's find operand #2
{
if (opString[i] == '=')
break;
else
{
op2[i-n] = opString[i];
j++;
}
}
}
cout << "Op 1: " << op1.c_str() << endl << "Oper: " << oper.c_str() << endl << "Op 2: " << op2.c_str() << endl;
}
return 0;
}
What I have here is (the beginning of) a program that is meant to read in strings from a text file to add hexadecimal operands together. The strings have the form of "op1OperatorOp2=" (minus the quotation marks). I am just starting. I am trying to take out op1, op2, and the operator (all strings) out of that by reading the string from the file (opString) character by character (as indicated by i in the for loop). The while loop just checks that it's not end of file for the fstream variable. op1b and operb are bool values that help determine when we 'know' what our first operand and operator are (and then when we can figure out operator number 2).
However, when I extract op2 from the string, my op1 gets replaced with the value of op2, even when I only say op2[whatever] = opString[i] where i is long past where op1 would even be.
Example: if the string coming in from the file is "3+2=", op1 should get 3, oper should get +, and op2 should get 2. However, op2 always ends up being the same as op1 at the end of the loop. Thus, instead of op1 = 3, oper = +, op2 = 2, I end up with op1 = 2, oper = +, op2 = 2.
Is there some undocumented C++ feature I am missing? I cannot figure out why this occurs. Is it because I am in a loop? Should I break up my loop? I do not see why that should make a difference, however. Thanks.
Next time post complete code (with all declration). op1 and op2 are std::string? You try to write characters in op1 and op2 but you haven't allocated any space, i.e. you should either op1.resize(SOME_SIZE) before the loop or use std::string::push_back to append chars to the operands.

Am I incorrectly using atoi?

I was having some trouble with my parsing function so I put some cout statements to tell me the value of certain variables during runtime, and I believe that atoi is incorrectly converting characters.
heres a short snippet of my code thats acting strangely:
c = data_file.get();
if (data_index == 50)
cout << "50 digit 0 = '" << c << "' number = " << atoi(&c) << endl;
the output for this statement is:
50 digit 0 = '5' number = 52
I'm calling this code within a loop, and whats strange is that it correctly converts the first 47 characters, then on the 48th character it adds a 0 after the integer, on the 49th character it adds a 1, on the 50th (Seen here) it adds a two, all the way up to the 57th character where it adds a 9, then it continues to convert correctly all the way down to the 239th character.
Is this strange or what?
Just to clarify a little more i'll post the whole function. This function gets passed a pointer to an empty double array (ping_data):
int parse_ping_data(double* ping_data)
{
ifstream data_file(DATA_FILE);
int pulled_digits [4];
int add_data;
int loop_count;
int data_index = 0;
for (char c = data_file.get(); !data_file.eof(); c = data_file.get())
{
if (c == 't' && data_file.get() == 'i' && data_file.get() == 'm' && data_file.get() == 'e' && data_file.get() == '=')
{
loop_count = 0;
c = data_file.get();
if (data_index == 50)
cout << "50 digit 0 = '" << c << "' number = " << atoi(&c) << endl;
pulled_digits[loop_count] = atoi(&c);
while ((c = data_file.get()) != 'm')
{
loop_count++;
if (data_index == 50)
cout << "50 digit " << loop_count << " = '" << c << "' number = " << atoi(&c) << endl;
pulled_digits[loop_count] = atoi(&c);
}
add_data = 0;
for (int i = 0; i <= loop_count; i++)
add_data += pulled_digits[loop_count - i] * (int)pow(10.0,i);
if (data_index == 50)
cout << "50 index = " << add_data << endl;
ping_data[data_index] = add_data;
data_index++;
if (data_index >= MAX_PING_DATA)
{
cout << "Error parsing data. Exceeded maximum allocated memory for ping data." << endl;
return MAX_PING_DATA;
}
}
}
data_file.close();
return data_index;
}
atoi takes a string, i.e. a null terminated array of chars, not a pointer to a single char so this is incorrect and will get you unpredictable results.
char c;
//...
/* ... */ atoi(&c) /* ... */
Also, atoi doesn't provide any way to detect errors, so prefer strtol and similar functions.
E.g.
char *endptr;
char c[2] = {0}; // initalize c to all zero
c[0] = data.file.get(); // c[1] is the null terminator
long l = strtol(c, &endptr, 10);
if (endptr == c)
// an error occured
atoi expects a null-terminated string as an input. What you are supplying is not a null-terminated string.
Having said that, it is always worth adding that it is very difficult (if at all possible) to use atoi properly. atoi is a function that offers no error control and no overflow control. The only proper way to perform string-representation-to-number conversion in C standard library is functions from strto... group.
Actually, if you need to convert just a single character digit, using atoi or any other string conversion function is a weird overkill. As it has already been suggested, all you need is to subtract the value of 0 from your character digit value to get the corresponding numerical value. The language specification guarantees that this is a portable solution.
Nevermind, it was simply that I needed to convert the character into a string terminated by \0. I changed it to this code:
char buffer [2];
buffer[1] = '\0';
buffer[0] = data_file.get();
if (data_index == 50)
cout << "50 digit 0 = '" << buffer[0] << "' number = " << atoi(buffer) << endl;
and it worked.