0

Today while doing K&R question 1-19, a strange error (which I resolved) occurred in my for loop. The reason I am posting is to ask why this is the case.

K&R 1-19: Write a function reverse(s) that reverses the character string s . Use it to write a program that reverses its input a line at a time. My Solution:

#include <stdio.h>

int function1 (char []);
void reverse (char [], char[], int);

int main() {

    char a[1000];
    char b[1000];
    int i;

    i = function1(a);
    reverse (b,a,i);

    printf("%s",b);
    putchar('\n');

    return 0;
}

int function1 (char a[]) {
    int i;
    int p;

    for (i=0; (i<1000-1) && (p=getchar())!=EOF && (p !='\n'); ++i) {
        a[i]=p;
    }

    if (p == '\n') {
        a[i]=p;
        ++i;    
    }

    a[i]='\0';
    return i;
}

 void reverse (char a[], char b[], int c) {
    int i;
    int x;
    i=0;    


    /*It appears that in the for declaration you must use , instead of && */    

    for (x=c-1; x>=0; (++i) && (x=x-1)) {
        a[i] = b[x]; 
    }
    a[i+1]='\0';
}

My code successfully accomplishes the task (there are some garbage characters at the end but I will figure that out). However, I noticed that in the increment part of the for loop something strange happens:

Let's say I type:

hi my name is john

I will get:

nhoj si eman ym ih

Which is the correct response. However, if I reverse the increment portion:

for (x=c-1; x>=0; (x=x-1) && (++i)) {

Strangely, enough my output becomes:

nhoj si eman ym h

The second character (i) becomes missing. Why is this the case?

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
John Doe
  • 55
  • 1
  • 8
  • How does your program magically change case? – Kerrek SB Feb 23 '17 at 10:42
  • 3
    Because in the second version you made the increment conditional. [See this](http://stackoverflow.com/questions/628526/is-short-circuiting-boolean-operators-mandated-in-c-c-and-evaluation-order). – Lundin Feb 23 '17 at 10:42
  • Sorry I mistyped the case. I will correct it. @KerrekSB – John Doe Feb 23 '17 at 10:47
  • Thank you for the link. @Lundin – John Doe Feb 23 '17 at 10:47
  • 1
    Please don't type. You should *copy-paste* code and data from your local test setup that you created in preparation for this question. – Kerrek SB Feb 23 '17 at 10:52
  • I copy-pasted the code from 'gedit', but for some reason my copy paste does not work when I attempt to copy the output from the terminal. – John Doe Feb 23 '17 at 10:57

2 Answers2

2

The logical operators in C (&& and ||) preform what is known as short circuiting. It means that they will not evaluate their second operand if they can determine the result from the first.

I.e , if the first operand of && is logically false, then the second will not be evaluated, since the entire expression will be logically false regardless.

In your case ++i is always non-zero, so if you place it as the first operand to &&, then (x=x-1) must be evaluated.

If you place (x=x-1) first, then when x becomes zero, there will be no evaluation of ++i.

Regardless, the usual idiom of preforming multiple operations in the third part of the for statement, is by using the comma operator:

for (x=c-1; x>=0; (x=x-1), (++i))

Which ensures that each operand will be evaluated in the order specified, from left to right.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I will be sure to use the comma separator. However, I am confused about the evaluation. The reason is because I believe that x=x-1 is suppose to set x equal to x-1, whereas if I were attempting to evaluate, I would write x==x-1 (or !=). In this situation I can see that there would be an evaluation scenario. However, I was simply setting x to an integer, so I am confused as to why the short circuiting concept applies. @StoryTeller – John Doe Feb 23 '17 at 10:55
  • 1
    @JohnDoe - Evaluation is what the program does to determine the value of an expression, and not what one would colloquially assume evaluation means. So to determine the value of the expression `++i`, the program will need to increment `i` and retrieve its new value. That new value is the value of the expression. `x = x - 1` is also an expression, and has a value to be evaluated. That value is what was assigned to `x`. – StoryTeller - Unslander Monica Feb 23 '17 at 10:57
  • Does the programming term evaluation also include the == and the != then? Or does it only solely refer to the single =? (Nevermind, I believe that it does include those other operands from reading other examples.) – John Doe Feb 23 '17 at 11:00
  • 1
    @JohnDoe - It includes everything that is an expression. And yes, `a == b` is also an expression, that has two sub-expressions `a` and `b`. – StoryTeller - Unslander Monica Feb 23 '17 at 11:06
2

Operator && and || short cicuit the operation. (Do not evaluate the second operand if the result is known after evaluating the first)

When you reverse the arguments of expression (Instead of assignment, increment is conditional) flow of program changes and change the result.

Related C-faq: Is it safe to assume that the right-hand side of the && and || operators won't be evaluated if the left-hand side determines the outcome?

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • @JohnDoe You can read evaluate as execute. When you write an expression in C, it is evaluated to a value based on priority and associativity of the operators and few more rules. For example in `x = x - 1` (let's say x was 5) will first subtract 1 from `x` then the value of subexpression `x - 1` is the result after subtraction (4 in this case). This is then assigned to `x` and evaluation of expression `x = x-1` is the subtracted value (4). Because the operator `&&` expects a logical value, this will treated as true or `1` as it is non-zero. – Mohit Jain Feb 23 '17 at 10:57
  • I see, this is very clear. Thank you. Am I also correct to believe that evaluate not only pertains to =, but also ==, >, <, !=, and? @Mohit Jain – John Doe Feb 23 '17 at 11:05
  • 1
    @JohnDoe Yes, you are right. It is done for all expressions. Operands for operator `+`, `==`, `>` etc are all expressions. – Mohit Jain Feb 23 '17 at 11:11