简体   繁体   中英

A shorter way to write following c++ code (if-else)

I need to know is there a better / shorter way to write following code in c++. (while going through the main if-else (step by step), additional check for variable 'y' will be added)

int x = 5, y = 4;        

if(x == 1){
  if(y == 1)
      printf("ok");
  else
      printf("not ok");
}
else if(x == 2){
  if((y == 1) || (y == 2))
      printf("ok");
  else
      printf("not ok");
}
else{
  if((y == 1) || (y == 2) || (y == 3))
      printf("ok");
  else
      printf("not ok");
}
if(0<y && y<4 && (y<=x || x<1))
    printf("ok");
else
    printf("not ok");

@Christophe you're right, an explanation could be helpful:

int x = 5, y = 4;        

if(x == 1){
  if(y == 1)
      printf("ok");
  else
      printf("not ok");
}
else if(x == 2){
  if((y == 1) || (y == 2))
      printf("ok");
  else
      printf("not ok");
}
else{
  if((y == 1) || (y == 2) || (y == 3))
      printf("ok");
  else
      printf("not ok");
}

When 'printf("ok");' was executed, '(y == 1) || (y == 2) || (y == 3)' had to be 'true'.

'x' and 'y' are integers implies:

'(y == 1) || (y == 2) || (y == 3)' is equivalent to '0<y && y<4', because '0<y' is 'true', when 'y' is one of them {1,2,3,4,...} and 'y<4' is 'true', when 'y' is one of them {3,2,1,0,-1,-2,...} and '0<y && y<4' is 'true' means: 'y' is one of them {1,2,3}.

When you write:

if(0<y && y<4)
    printf("ok");
else
    printf("not ok");

there will be too much 'ok', if you get into this branch:

if(x == 1){
  ...
}

or into this:

else if(x == 2){
  ...
}

in both branches '1<=x' is 'true', when you get into one of them.

This implies: if 'x<1' (equivalent to '!(1<=x)') is 'true', you won't get into one of them.

When you write:

if(0<y && y<4 && x<1)
    printf("ok");
else
    printf("not ok");

there would be too much 'not ok', when 'x' is one of them {1,2,3,4,5,...} and 'y' is right.

  1. 'x' is 1: '0<y && y<4' had to be 'true' for 'ok', but 'x<1' will be 'false'!.
  2. 'x' is 2: '0<y && y<4' had to be 'true' for 'ok', but 'x<1' will be 'false'!.
  3. 'x' is 3 or bigger: '0<y && y<4' had to be 'true' for 'ok', but 'x<1' will be 'false'!.

for 1. and 2. '0<y && y<4' is too much (think of equivalence 'y==1 || y==2 || y==3'), but in both it will be 'true' and 'x<1' is 'false', but there must something like '(... || x<1)' and this '...' have to ensure that:

  1. 'y' is 1, when 'x' is 1 and
  2. 'y' is 1 or 'y' is 2, when 'x' is 2 and
  3. 'y' is 1 or 'y' is 2 or 'y' is 3, when 'x' is 3 or bigger.

for 1. 'x' is 1: 'y<=1'

for 2. 'x' is 2: 'y<=2' in both cases, 'y<=x' would be right.

for 3. 'x' is 3 or bigger: 'y<=x' will always be 'true', when 'y' is right ('y==1 || y==2 || y==3').

and you get the answer.

You can test y first:

if (y == 1 
|| (y == 2 && x != 1)
|| (y == 3 && x != 1 && x != 2))
    printf(“ok”);
else
    printf(“not ok”);

(There may be redundant parentheses, but this is one situation where I personally feel that possibly redundant parentheses are A Good Thing.)

I answer to the question stricto sensu , if the value of x and y are unknown this is an other question

Thanks to the line int x = 5, y = 4; the value of x and y are known and the code can be reduced to

printf("not ok");

gcc knows that, having (I replaced "ok" by "is ok" to not allow to use "not ok"+4 to get "ok") :

#include <stdio.h>

int main()
{
  int x = 5, y = 4;

  if(x == 1){
    if(y == 1)
      printf("is ok");
    else
      printf("not ok");
  }
  else if(x == 2){
    if((y == 1) || (y == 2))
      printf("is ok");
    else
      printf("not ok");
  }
  else{
    if((y == 1) || (y == 2) || (y == 3))
      printf("is ok");
    else
      printf("not ok");
  }
  return 0;
}

Compilation to produce assembler :

pi@raspberrypi:/tmp $ gcc -S -O2 c.c
pi@raspberrypi:/tmp $ more c.s
    .arch armv6
    .eabi_attribute 28, 1
    .eabi_attribute 20, 1
    .eabi_attribute 21, 1
    .eabi_attribute 23, 3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 2
    .eabi_attribute 30, 2
    .eabi_attribute 34, 1
    .eabi_attribute 18, 4
    .file   "c.c"
    .section    .text.startup,"ax",%progbits
    .align  2
    .global main
    .syntax unified
    .arm
    .fpu vfp
    .type   main, %function
main:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    push    {r4, lr}
    ldr r0, .L3
    bl  printf
    mov r0, #0
    pop {r4, pc}
.L4:
    .align  2
.L3:
    .word   .LC0
    .size   main, .-main
    .section    .rodata.str1.4,"aMS",%progbits,1
    .align  2
.LC0:
    .ascii  "not ok\000"
    .ident  "GCC: (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516"
    .section    .note.GNU-stack,"",%progbits
pi@raspberrypi:/tmp $ grep ok c.s
    .ascii  "not ok\000"

there is no test or equivalent in main , and the string "is ok" not in the generated code

not glamorous but still..

if(x == 1 && y == 1) {
     printf("ok");
} else if(x == 2 && y == 1) {
     printf("ok");
} else if(x == 2 && y == 2) {
     printf("ok");
} else if(y == 1 || y == 2 || y == 3) {
     printf("ok");
} else {
     printf("not okay");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM