This following code is supposed to encrypt a sentence using the ceasers cipher, it is still WIP i haven't accounted for spaces, lower case letters etc etc.
int main(int argc,string argv[])
{
int k = atoi(argv[1]);
string value = GetString();
int n = strlen(value);
for(int i = 0;i<n; i++);
{
char temp = value[i];
int conv = temp - (int)'A';
int cipher = (conv + k)%26;
char final = cipher + (int)'A';
printf("%c\n",final);
}
}
I get
caeser.c:15:23 use of undeclared identifier i.
which is on the line char temp = value[i];
Remove the semicolon at the end of the for line:
for(int i = 0;i<n; i++);
Declaring int i there makes it local to the for block, but because of the semicolon that is an empty block.
So in the following code block (between the { }) i is not declared because it does not belong to the for.
This will also fix the program not executing the body of the for more than once (which it would, if it compiled). If this had compiled the for loop would have looped until n but not execute anything. Then after that the code between the curly braces would have been executed with i == n (assumed that i is then visible to that code block). So your code would always execute with temp == '\0' (the terminating null in value) and always print the same cipher value.
ENCORE: (as explained in the comments, but here for completeness' sake)
The casts of character-literals to ints (int conv = temp - (int)'A';) are unnecessary for two reasons:
Contrary to what may seem intuitive character-literals are ints, not chars (this is different in C++, I believe)
But even if 1. weren't the case, a char is always smaller than an int and will thus always fit inside an int so it can safely be promoted.
Your problem is here:
for(int i = 0;i<n; i++);
^
The ; ends your for loop, it runs n times but performs no operation since the ; just ends a null statement. So the {} afterward is just a compound statement with it's own scope which does not include the declaration of i:
{
char temp = value[i]; // i does not exist here since it declared in for loop
// and it's scope ends with the for loop
//...
}
The C99 draft standard tells us that what you have after the for is a statement expression, section 6.8.3 Expression and null statements has the following grammar for expression statements:
expression-statement:
expressionopt ;
and in paragraph 3 tells us that the empty statment is just a null statement:
A null statement (consisting of just a semicolon) performs no operations.
Related
Not sure what I've done here (pretty new to C, have done some Python, Arduino and Java before).
int main(void){
unsigned long int sum = 0;
unsigned int count = 0;
for(unsigned long int i = 1; i <= 100; i++)
if(i%3 != 0 && i%5 != 0)
printf("cond%d\n", i);
count++;
sum += i; // $$here$$
return 0;
When I compile the code, I get 'error undefined identifier: i' on line 10 (indicated with $$here$$
C does not use indentation to structure program control (such as to indicate that more-indented statements are controlled by a less-indented statement above them). To group statements under the control of an if or other statement, you must use braces:
if(i%3 != 0 && i%5 != 0)
{
printf("cond%d\n", i);
count++;
sum += i;
}
The compiler error occurs because, due to the lack of braces, the scope of the for statements ends after the printf statement. So no declaration for i is visible at the sum += i; line, and the compiler complains.
The compiler will ignore most indentation and white space. When authors use indentation in C source code, it is to aid humans, not the compiler.
(C grammar does not require any braces around the if statement to keep it within the for statement’s control, because the if statement and the following lines form a single statement, once braces are added as shown above. However, many people would add braces just around the if statement to illustrate explicitly that it forms the body of the for statement. I treat this contextually, judging what is clearer in each situation.)
I want to know exactly, what is a null statement in C programming language? And explain a typical use of it.
I found the following segment of code.
for (j=6; j>0; j++)
;
And
for (j=6; j>0; j++)
From the msdn page:
The "null statement" is an expression statement with the expression missing. It is useful when the syntax of the language calls for a statement but no expression evaluation. It consists of a semicolon.
Null statements are commonly used as placeholders in iteration statements or as statements on which to place labels at the end of compound statements or functions.
know more: https://msdn.microsoft.com/en-us/library/1zea45ac.aspx
And explain a typical use of it.
When you want to find the index of first occurrence of a certain character in a string
int a[50] = "lord of the rings";
int i;
for(i = 0; a[i] != 't'; i++)
;//null statement
//as no operation is required
A null statement is a statement that doesn't do anything, but exists for syntactical reasons.
while ((*s++ = *t++))
; /* null statement */
In this case the null statement provides the body of the while loop.
or (disclaimer: bad code)
if (condition1)
if (condition2)
dosomething();
else
; /* null statement */
else
dosomethingelse();
In this case the inner else and null statement keeps the outer else from binding to the inner if.
From C11, §6.8.4.1, 6.8.3 Expression and null statements:
A null statement (consisting of just a semicolon) performs no
operations.
The standard also provides a couple of common uses of it:
EXAMPLE 2 In the program fragment
char *s;
/* ... */
while (*s++ != '\0')
;
a null statement is used to supply an empty loop body to the iteration
statement.
6 EXAMPLE 3 A null statement may also be used to carry a label just
before the closing } of a compound statement.
while (loop1) {
/* ... */
while (loop2) {
/* ... */
if (want_out)
goto end_loop1;
/* ... */
}
/* ... */
end_loop1: ;
}
A null statement doesn't DO anything, hence the solo ';'
so....this code block will do nothing 10x in C/C++
for(int i = 0; i < 10; i++){//execute the following 10 times
;//nothing aka "null statement"
}//end for
Sometimes the null statement serves. In the "old days" the math hardware might not return an integer value when you needed one, such as returning 0.999... as sin(pi / 2), (that is sin(90 degrees)).
int i, j, k;
i = something;
for(j = 1; (2 * j) <= i; j *= 2);
Computes in j the largest integer power of 2 less than i. Not very efficient for large i but useful if you could not trust Log functions to return an exact integer value.
My C++ compiler does not accept the null statement as a function body, but does accept the "empty statement" which I think is just an empty statement block "{}".
Whether C or java, null has a special significance.
Whenever there is a need of re-intializing of values to variavle, null serves the purpose.
If there is a String i, and we want it to add a char value through a loop, then first we have to intialize i with null.
#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");
else
printf("Get out World");;;;;;
}
Can anybody tell me why line number 8 still works, with multiple semicolons?
An empty statement is legal in C. Since ; is the statement terminator, multiple ; are syntactically valid. Sometimes this is even useful: such as the for (;;) {/*code here*/} idiom.
(Although some compilers will warn you in appropriate instances).
Do note that, conceptually at least, the excess ; in that line are not part of the if block.
Your program just has a sequence of empty statements at the end of the main function. It is parsed as this:
#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");
else
printf("Get out World");
;
;
;
;
;
}
Note that int main() should be written int main(void) and it should return an int value, for example 0. C99 makes this return 0; implicit, but it is considered bad style and it is indeed less portable to omit it.
Extra semicolons in general are not "OK".
For example, changing your code slightly:
#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");;;;;;
else
printf("Get out World");
}
That won't even compile.
Another example, and this one does compile:
...
int done = 0;
...
while ( !done );
{
...
done = 1;
}
...
;;;;; are empty statements. They are allowed in C.
It's a null statement which you have after the printf() statment. Having more than one semi-colons is allowed.
C11, §6.8.3, 4
A null statement (consisting of just a semicolon) performs no
operations
Well, the ; semicolon in C is a statement terminator, which means that you cannot put it where you like, only at the end of a statement.
The null statement (one that does nothing) is valid in C, which allow you to write things as the one you post, and things like:
while((data = do_read(...)) != NULL); /* skip input until EOF */
that should be more visible written as (a single semicolon is too small to be skipped in a quick read):
while((data = do_read(...)) != NULL) continue;
which looks better as you'll never think that the next line is inside the loop.
By the way, if you write something like:
if (a > b); /* <====== LOOK at this semicolon */
printf("Hello World");;;;;;
else
printf("Get out World");
it will not compile, as that means if a greater than b just do nothing and that's a good valid sentence in C. By contrast you'll get an error several lines later, when the compiler gets to the else token and cannot match it to an if statement (remember, when you used the ;, you finished the ifstatement)
That also happens to occur with the group of semicolons you put after the printf("Hello World"); statement (the first semicolon terminates it, and also as the next token is not an else but a ;, also terminates the if statement).
The statements in the example above are:
if (a > b); /* if a greater than b do nothing */
; /* do nothing */
; /* ... */
; /* ... */
; /* ... */
; /* do nothing */
else /* ERROR, else cannot begin a statement */
....
Here, as you got a syntax error from the compiler, you cannot have a good C program so you'll not get further analysing (the compiler tries to recover and continue parsing past that point, but you can have new errors originating of the new condition, or fake errors)
As we know, semicolon (;) works as a statement terminator. In the Line no.8 the first semicolon terminates the statement under else and the next semicolon terminates the empty statement, and so on.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
I am solving a problem that reads a set of text lines and prints the longest.
The problem is from K&R "The C programming language" section 1.9. The book provides a solution but I tried to solve it in my own way. The code below works but before I get it to work, I was getting a problem due to the line longestStr[i++] = tmpStr[j++] as I have previously used longestStr[i++] = tmpStr[i++] thinking that i would be incremented once the assignment was done. But that was not the case. Is this how postfix operator normally works?
#include <stdio.h>
#define MAXLINE 100
main()
{
int lineLength = 0, longestLine = 0;
int c, i, j;
char longestStr[MAXLINE];
char tmpStr[MAXLINE];
while((c = getchar()) != EOF)
{
tmpStr[lineLength++] = c;
if(c == '\n')
{
if( lineLength > longestLine)
{
longestLine = lineLength;
i = 0, j = 0;
while(i < lineLength)
{
longestStr[i++] = tmpStr[j++]; // I tried longestStr[i++] = tmpStr[i++] but it gives wrong result
}
}
lineLength = 0;
}
}
printf("Longest line is - %d long\n", longestLine-1);
for(i = 0; i < longestLine-1; i++)
printf("%c", longestStr[i]);
putchar('\n');
}
The postfix increments or decrements are operators that perform the increment or decrement after the use of the variable, such that if you wish to use a integer value to print out and add it at the same time you would use postfix.
int i = 0;
printf("%d",i++);
//prints out 0
Prefix increment/decrement however works in the opposite manner such that it performs the increment/decrement prior to the use of the variable, such that if you wish to increment/decrement a variable before printing it out, you would use prefix
int i = 0;
printf("%d",++i);
//prints out 1
The problem you have is not related to how the postfix operator works, but rather to what you intend to do in the code line which gives you a problem.
As asked in the comments, what is the meaning of the line as you wrote it initially?
longestStr[i++] = tmpStr[i++];
Because the C standard does not specify it, this line can be interpreted in several ways:
longestStr[i] = tmpStr[i+1];
i += 2;
or
longestStr[i+1] = tmpStr[i];
i += 2;
or
longestStr[i] = tmpStr[i];
i += 2;
In every case, you end up with a counter incremented twice, which will mess up your algorithm.
The correct way is to increment the counter in a separate line, or use the working solution (you are providing), which should be compiled down to the same code with any decent compiler.
Note that you should probably check for the counter not going beyond the maximum allowed line size MAXLINE (unless the problem states that this cannot happen with the input, but even in that case, it would be helpful for situations like yours, where the code wrongly increment the counter twice).
try to understand how post fix increment works.
f(i++) is equivalent to the operation 'call f on the current value of i, then increment i'
For example, when you use i++ twice, and initial value of i = 1, a(i++) = b(i++) means, a(1)=b(2) and the value of i after the operation is i=3.
If you want to eliminate one variable in what you are trying to do, you have to make sure you use increment only once. Do it like, a(i)=(b(i); i++
Whereas the postfix increment operator evaluates the original value, it is understandable to think the actual incrementating doesn't happen until sometime down the road. However this is not the case. You should conceptualize postfix as if the incrementing is happening while the original value is being returned.
The bigger issue though is that your statement increments i twice. This means i will increase by two with each iteration of your loop. Futhermore your index values will be off by one from each other, That's because if a variable changes during one part of statement evaluation, those changes become instantly visible to parts of the statement which have not yet evaluated.
I'm trying to write a program that evaluates a postfix arithmetic expression. The program sends a character string to my function evaluatePostfix, which proceeds to identify operands and operators and come up with an integer solution. I am manipulating stacks in this program by pushing the scanned character as it is identified and of course doing the appropriate pop functions when needing to evaluate. Right now though, I'm having a problem with the program hanging in what appears to be an infinite loop. I guess I'm not really sure how to tell the function to proceed to the next character in the string after it has evaluated the first character. Another thing to note is that the user puts a space in-between each operand and operator. Here is my function:
int evaluatePostfix(char *postfixStr)
{
stack * s;
int x, y;
stackInit(&s);
do {
if(isOperand(postfixStr) == 1) {
stackPush(&s, postfixStr);
}
if(isOperator(postfixStr) == 1) {
y = atoi(stackPop(s));
x = atoi(stackPop(s));
char *str = malloc(10 * sizeof(char));
sprintf(str, "%d", applyOperator(x, y, postfixStr));
stackPush(&s, str);
}
} while (postfixStr != NULL);
return stackPop(s);
}
I know the functions that manipulate the stack are correct as they were provided by my instructor. Could someone perhaps give me a clue as to what I'm missing?
You could change the while condition to while (++postfixStr != NULL) to increment the pointer to the next character in postfixStr.
This increment is done using the prefix notation (++var vs var++) so that the next character is compared to NULL. I'm not familiar with the behavior of the stack functions you're using, but I would recommend changing the do { ... } while (++postfixStr != NULL); loop to a while (postfixStr != NULL) { ... } loop, and increment postfixStr at the end of that while loop's block.
The safest thing to do is add a string length parameter to your function:
int evaluatePostfix(char *postfixStr, int strLength)
You would then use a loop that explicitly steps from the beginning of the string at index 0 to index strLength - 1, which would safely handle empty and non-NULL-terminated strings.