Convert If/Else's into a switch somehow - c++

So basically what I'm trying to do it turn this chunk of code into a switch statement somehow. I'm not really sure how to do this. I had a couple of ideas like making an enum with keywords that had a range of values (ie "enum hare { ONE =(range from 1-5) TWO = (range from 6-8)} - But i dont know if that is an error :S
Hopefully I've been clear in what I'm trying to ask.
int y = 1 + rand() % 10;
// determine which move to make
if ( y == 1 || y == 2 ) {
hare += 0;
} else if ( y == 3 || y == 4 ) {
hare += 9;
} else if (y == 5) {
hare -= 12;
} else if (y >= 6 && y <= 8){
hare += 1;
} else if (y == 9 || y == 10){
hare -= 2;
}else {
++( hare );
}
if ( hare < 1 ) {
hare = 1;
} else if ( hare > RACE_END ) {
hare = RACE_END;
}

The first question is whether there is real value in doing the conversion. Then the operation is actually simple for this case, since in all cases except the else there is a small number of valid cases:
switch (y) {
case 1: case 2:
break;
case 3: case 4:
hare += 9;
break;
case 5:
hare -= 12;
break;
case 6: case 7: case 8:
hare += 1;
break;
case 9: case 10:
hare -= 2;
break;
default:
++hare;
}

If you want to use switch statement, you can do like this
switch( y ){
case 1:
case 2: hare += 0; break;
case 3:
case 4: hare += 9; break;
case 5: hare -= 12; break
case 6:
case 7:
case 8: hare += 1; break;
case 9:
case 10: hare -= 2; break;
default: ++(hare);
}
But, using enum, enum hare { ONE =(range from 1-5) TWO = (range from 6-8)} is that ... you are trying to store multiple values in one variable, which is not possible.
Reference for switch statement

You can easily do something like this:
switch(y)
{
case 1:
case 2:
//do something
break;
default:
//
}
Therefore falling through your case conditions according the values of y.

int y = 1 + rand() % 10;
switch ( y )
{
case 1:
case 2:
hare += 0;
break;
case 3:
case 4:
hare+= 9;
break;
case 5:
hare -= 12;
break;
case 6:
case 7:
case 8:
hare += 1;
break;
case 9:
case 10:
hare -= 2;
break;
default:
++hare;
break;
}
if ( hare < 1 ) {
hare = 1;
} else if ( hare > RACE_END ) {
hare = RACE_END;
}

You can do it like this.
int y = 1 + rand() % 10;
switch(y)
{
case 1: //1 or 2
case 2:
hare += 0;
break;
case 3: //3 or 4
case 4:
hare += 9;
break;
case 5:
hare -= 12;
break;
case 6:
case 7:
case 8:
hare += 1;
break;
case 9:
case 10:
hare -= 2;
break
default:
if ( hare < 1 ) {
hare = 1;
} else if ( hare > RACE_END ) {
hare = RACE_END;
}
else
++( hare );
break;
}

Related

How it could be optimized [C++]?

I was doing some C++ "homework" and I've made an exercise which says the following:
Input
The input consists of a sequence of characters, which include exclusively lowercase letters, spaces and newlines.
[Table with letter-number values]
Output
Your program must print the total value of the message, computed as the sum of the value of all its letters.
And I've done this!:
#include<iostream>
using namespace std;
int main() {
char v;
int val = 0;
while(cin >> v){
if (v == 'a' or v == 'e') val += 1;
if (v == 'o' or v == 's') val += 2;
if (v == 'd' or v == 'i' or v == 'n' or v == 'r') val += 3;
if (v == 'c' or v == 'l' or v == 't' or v == 'u') val += 4;
if (v == 'm' or v == 'p') val += 5;
if (v == 'k' or v == 'w') val += 7;
if (v == 'b' or v == 'f' or v == 'g' or v == 'h') val += 6;
if (v == 'j' or v == 'q' or v == 'v' or v == 'x' or v == 'y' or v == 'z') val += 6;
}
cout << val << endl;
}
Example:
INPUT:
is a chinese wok
OUTPUT:
42
(I end the While loop by pressing Ctrl+D, which is how the evaluation web does.)
Which is a pretty simple and working solution but...
I was wandering if there's any way of doing this without a bunch of "if's". Gotta say, I can't include anything else than iostream.
Thanks!
As another answer indicates, you can use a map. That's the most compact way of writing this algorithm, but it will not necessarily result in best performance.
There are two more ways that I can think of. A somewhat better way is with a switch statement, like this:
int get_increment( char v )
{
switch( v )
{
case 'a': case 'e':
return 1;
case 'o': case 's':
return 2;
case 'd': case 'i': case 'n': case 'r':
return 3;
case 'c': case 'l': case 't': case 'u':
return 4;
case 'm': case 'p':
return 5;
case 'k': case 'b': case 'f': case 'g': case 'h':
return 6;
case 'w':
return 7;
case 'j': case 'q': case 'v': case 'x': case 'y': case 'z':
return 6;
default:
return 0; //not a letter!
}
}
but if you want the maximum performance, then a lookup table is the way to go.
Here is how to initialize the lookup table:
int increments[256];
for( int i = 0; i < 256; i++ )
increments[i] = 0;
for( char c = 'a'; c <= 'z'; c++ )
increments[c] = get_increment( c );
and then here is how to use it:
val += increments[(unsigned char)v];
Note: the cast of v to unsigned char is not strictly speaking necessary, if v is only going to contain letters. But it will save your program from a crash if characters in your architecture are signed, (and they usually are,) and v happens to contain a negative value.

Pass int Into Function, the int into Switch, and change value of int

int upgradeControl(int currentUpgrade) {
// This section returns the value of an upgrade
switch (currentUpgrade) {
case 0: currentUpgrade = 0;
break;
case 1: currentUpgrade = 100;
break;
case 2: currentUpgrade = 300;
break;
case 3: currentUpgrade = 600;
break;
case 4: currentUpgrade = 1000;
break;
case 5: currentUpgrade = 1500;
break;
default: std::cout << "We have an error";
}
}
I need my code to return a new value back to another function, but CLion says everything nested inside my switch is unreachable.
int upgradeControl(int currentUpgrade) {
// This section returns the value of an upgrade
switch (currentUpgrade) {
case 0: currentUpgrade = 0;
break;
case 1: currentUpgrade = 100;
break;
case 2: currentUpgrade = 300;
break;
case 3: currentUpgrade = 600;
break;
case 4: currentUpgrade = 1000;
break;
case 5: currentUpgrade = 1500;
break;
default: std::cout << "We have an error";
}
return currentUpgrade;
}

Set BSTR to null

In a Visual C++ i have a function like shown below.it is a dll code. From vb6 application i am calling dll and run the function and get result.But every time when i call this from my vb6 application(without closing vb6 exe) i get result with appended values of last result if exe is not closed.(ex when i run first result is "a" for second time it is "aa" and so on).So i am using i think it is due to BSTR Message not being set to NULL in the beginning of this function.
Below is code in VC++ . So how to set BSTR to null or empty in the beginning or how to solve my error?
BSTR __stdcall getHardDriveComputerID (short* disk_cnt , short* method)
{
BSTR Message=NULL;
int i,length;
size_t len = 0;
int done = FALSE;
__int64 id = 0;
OSVERSIONINFO version;
strcpy (HardDriveSerialNumber, "");
memset (&version, 0, sizeof (version));
version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&version);
if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// this works under WinNT4 or Win2K if you have admin rights
#ifdef PRINTING_TO_CONSOLE_ALLOWED
printf ("\nTrying to read the drive IDs using physical access with admin rights\n");
#endif
done = ReadPhysicalDriveInNTWithAdminRights ();
*disk_cnt=hard_disk_cnt;
*method=1;
if ( ! done)
{
done = ReadIdeDriveAsScsiDriveInNT ();
*disk_cnt=hard_disk_cnt;
*method=2;
}
if ( ! done)
{done = ReadPhysicalDriveInNTWithZeroRights ();
*disk_cnt=hard_disk_cnt;
*method=3;
if ( ! done)
{ done = ReadPhysicalDriveInNTUsingSmart ();
*disk_cnt=hard_disk_cnt;
*method=4;
}
}
else
{
// this works under Win9X and calls a VXD
int attempt = 0;
// try this up to 10 times to get a hard drive serial number
for (attempt = 0;
attempt < 10 && ! done && 0 == HardDriveSerialNumber [0];
attempt++)
done = ReadDrivePortsInWin9X ();
*disk_cnt=hard_disk_cnt;
*method=5;
}
if (HardDriveSerialNumber [0] > 0)
{
char *p = HardDriveSerialNumber;
WriteConstantString ("HardDriveSerialNumber", HardDriveSerialNumber);
// ignore first 5 characters from western digital hard drives if
// the first four characters are WD-W
if ( ! strncmp (HardDriveSerialNumber, "WD-W", 4))
p += 5;
for ( ; p && *p; p++)
{
if ('-' == *p)
continue;
id *= 10;
switch (*p)
{
case '0': id += 0; break;
case '1': id += 1; break;
case '2': id += 2; break;
case '3': id += 3; break;
case '4': id += 4; break;
case '5': id += 5; break;
case '6': id += 6; break;
case '7': id += 7; break;
case '8': id += 8; break;
case '9': id += 9; break;
case 'a': case 'A': id += 10; break;
case 'b': case 'B': id += 11; break;
case 'c': case 'C': id += 12; break;
case 'd': case 'D': id += 13; break;
case 'e': case 'E': id += 14; break;
case 'f': case 'F': id += 15; break;
case 'g': case 'G': id += 16; break;
case 'h': case 'H': id += 17; break;
case 'i': case 'I': id += 18; break;
case 'j': case 'J': id += 19; break;
case 'k': case 'K': id += 20; break;
case 'l': case 'L': id += 21; break;
case 'm': case 'M': id += 22; break;
case 'n': case 'N': id += 23; break;
case 'o': case 'O': id += 24; break;
case 'p': case 'P': id += 25; break;
case 'q': case 'Q': id += 26; break;
case 'r': case 'R': id += 27; break;
case 's': case 'S': id += 28; break;
case 't': case 'T': id += 29; break;
case 'u': case 'U': id += 30; break;
case 'v': case 'V': id += 31; break;
case 'w': case 'W': id += 32; break;
case 'x': case 'X': id += 33; break;
case 'y': case 'Y': id += 34; break;
case 'z': case 'Z': id += 35; break;
}
}
}
id %= 100000000;
if (strstr (HardDriveModelNumber, "IBM-"))
id += 300000000;
else if (strstr (HardDriveModelNumber, "MAXTOR") ||
strstr (HardDriveModelNumber, "Maxtor"))
id += 400000000;
else if (strstr (HardDriveModelNumber, "WDC "))
id += 500000000;
else
id += 600000000;
#ifdef PRINTING_TO_CONSOLE_ALLOWED
printf ("\nHard Drive Serial Number__________: %s\n",
HardDriveSerialNumber);
printf ("\nHard Drive Model Number___________: %s\n",
HardDriveModelNumber);
printf ("\nComputer ID_______________________: %I64d\n", id);
#endif
char tempdisk_serials[]="";
for(i = 0 ; i<=hard_disk_cnt ; i++)
{
if(hard_disk_serial[i] != "")
{
strcat(tempdisk_serials, hard_disk_serial[i]);
length = strlen(tempdisk_serials);
/* Check if we need to insert newline */
if(tempdisk_serials[length-1] != '\n')
{
tempdisk_serials[length] = '\n'; /* Append a newline */
tempdisk_serials[length+1] = '\0'; /* followed by terminator */
}
}
}
//Converting char[] to BSTR
Message = SysAllocStringByteLen (tempdisk_serials, strlen(tempdisk_serials));
return (BSTR) Message;
}
This is modified code of shown in link http://www.winsim.com/diskid32/diskid32.cpp
EDIT
Its not problem with tempdisk_serials actually .This variable is set from hard_disk_serial. It is declared globally as char hard_disk_serial[16][1024];(not shown in code in my question) . How to clear this variable in my function? i tried hard_disk_serial[][]={0}; and it gives syntax error.
To clear buffer, use memset function doc
memset (hard_disk_serial, 0, 1024*16);

My SDL_KEYUP argument isn't working

I tried setting the arguments up in different ways, but still no dice. Could someone tell me what's going wrong here?
void controls()
{
if(cancontrol = true)
{
if(window_key.type == SDL_KEYDOWN)
{
switch(window_key.key.keysym.sym)
{
case SDLK_UP:
haneposy =+ -1;
haneposx = 0;
break;
case SDLK_LEFT:
haneposx =- 1;
haneposy = 0;
break;
case SDLK_RIGHT:
haneposx =+ 1;
haneposy = 0;
break;
case SDLK_DOWN:
haneposy =- -1;
haneposx = 0;
break;
default:
break;
}
}
if(window_key.type == SDL_KEYUP)
{
switch(window_key.key.keysym.sym)
{
case SDLK_UP:
haneposx = 0;
haneposy = 0;
break;
case SDLK_LEFT:
haneposx = 0;
haneposy = 0;
break;
case SDLK_RIGHT:
if(haneposx && haneposy > 0)
{
haneposx = 0;
haneposy = 0;
}
break;
case SDLK_DOWN:
haneposx = 0;
haneposy = 0;
break;
default:
break;
}
}
}
}
The problem is that when the key is released it doesn't stop the sprite from moving by equaling the variable to zero. For additional information I am using glTranslate to move the sprite.
I think you confused += for =+. The first is an operator for increment and the second is an assignment followed by a plus sign.

C++ program not distinguishing between upper and lower case letters in OpenCV application

I'm editing a relatively big OpenCV-based program written by some colleagues.
The problem I'm facing is that the program does not distinguish between upper and lower case keystrokes (i.e both keystrokes 'd' and 'D' are seen as 0x65)
My colleague told me that he solved the problem on his machine by compiling the OpenCV libraries on his machine directly from source.
I'm a newbie, but also curious why such thing would even happen and how would it be related to OpenCV installation!
I still have the problem on my machine but I have not tried reinstalling openCV.
EDIT:
OS Linux-Ubuntu 12.10 64bit
The letters are keystrokes from the Keyboard and they are used in a switch statement.
static int process_key(struct cam_segment* cs, int key){
int res = 0;
double pdist;
struct stat sb;
char fn[4096];
static int out_id = 0;
fprintf( stderr, "%d\n", key&0xff );
switch (key & 0xff) {
case 'm':
show_merged = !show_merged;
res = 1;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
cam_id = (key & 0xff) - '1';
res = 1;
break;
case 'D':
ocv_mgrid_set_distortion( cs->mg, 0 );
res = 1;
break;
case 'd':
ocv_mgrid_set_distortion( cs->mg, 1 );
res = 1;
break;
case 'n':
res = 1;
break;
case 'C':
init_calibration(cs);
calibrate_camera_distortion(cs->mg);
output_calibration_results(cs);
cs->calib_mode = 1;
res = 1;
break;
case 'c':
init_calibration(cs);
fprintf(stderr,"searching.....");
calibrate_camera_rotation(cs->mg);
output_calibration_results(cs);
fprintf(stderr,"e1 %f\n",water_error(cs->mg));
cs->calib_mode = 1;
res = 1;
break;
case 'M':
init_calibration(cs);
fprintf(stderr,"searching pricipal point.....");
calibrate_camera_center(cs->mg);
output_calibration_results(cs);
cs->calib_mode = 1;
res = 1;
break;
case 'a':
init_calibration(cs);
int misscnt;
double e,en;
en = e = HUGE;
misscnt = 0;
for(int i=0;i<20;i++) {
e = water_error(cs->mg);
fprintf(stderr,"e1 %f %d \n",e,misscnt);
calibrate_camera_rotation(cs->mg);
output_calibration_results(cs);
en = water_error(cs->mg);
fprintf(stderr,"en1 %f\n",en);
if (en >= e)
misscnt++;
else
misscnt = 0;
if (misscnt > 3)
break;
e = water_error(cs->mg);
fprintf(stderr,"e %f %d\n",e,misscnt);
calibrate_coupled_focal_length(cs->mg);
output_calibration_results(cs);
en = water_error(cs->mg);
fprintf(stderr,"en %f\n",en);
if (en >= e)
misscnt++;
else
misscnt = 0;
if (misscnt > 3)
break;
e = water_error(cs->mg);
if (e > 100)
continue;
fprintf(stderr,"e %f %d\n",e,misscnt);
calibrate_camera_distortion(cs->mg);
output_calibration_results(cs);
en = water_error(cs->mg);
fprintf(stderr,"en %f\n",en);
if (en >= e)
misscnt++;
else
misscnt = 0;
if (misscnt > 3)
break;
}
cs->calib_mode = 1;
res = 1;
break;
case 'p':
init_calibration(cs);
calibrate_coupled_focal_length(cs->mg);
output_calibration_results(cs);
cs->calib_mode = 1;
res = 1;
break;
case 'F':
init_calibration(cs);
calibrate_focal_lengths(cs->mg);
output_calibration_results(cs);
cs->calib_mode = 1;
res = 1;
break;
case 't':
init_calibration(cs);
calibrate_target(cs->mg);
output_calibration_results(cs);
cs->calib_mode = 1;
res = 1;
break;
case 'e':
sprintf(fn, "%s_%03d.png",cs->inp_prefix, cs->inp_id);
if (!(input = cvLoadImage(fn, CV_LOAD_IMAGE_COLOR))) {
fprintf(stderr,"error calc: loading input failed\n");
} else if (!(ocv_mgrid_set_input(cs->mg, input))) {
fprintf(stderr,"error calc error 1\n");
}
pdist = water_error(cs->mg);
fprintf(stderr,"watererror: %f\n",pdist);
break;
case 'N':
res = 1;
cs->inp_id++;
cerr << "inp_id=" << cs->inp_id << "\n";
break;
case 'P':
res = 1;
cs->inp_id--;
cerr << "inp_id=" << cs->inp_id << "\n";
break;
case 'z':
cs->color_mode = OCV_MGRID_CMODE_THETA;
res = 1;
break;
case 'Z':
cs->color_mode = OCV_MGRID_CMODE_THETA_CHECK;
res = 1;
break;
case 'l':
cs->draw_legend = !(cs->draw_legend);
res = 1;
break;
case 'x':
cs->color_mode = OCV_MGRID_CMODE_X;
res = 1;
break;
case 'y':
cs->color_mode = OCV_MGRID_CMODE_Y;
res = 1;
break;
case 'X':
cs->color_mode = OCV_MGRID_CMODE_X_CHECK;
res = 1;
break;
case 'Y':
cs->color_mode = OCV_MGRID_CMODE_Y_CHECK;
res = 1;
break;
case 'o':
cs->color_mode = OCV_MGRID_CMODE_NONE;
res = 1;
break;
case 's':
sprintf(fn, "input_%03d.png",out_id);
while(stat(fn, &sb) != -1) {
out_id++;
sprintf(fn, "input_%03d.png",out_id);
}
fprintf(stderr,"saving %s \n",fn);
cvSaveImage(fn,OCV_MGRID_GET_INPUT(cs->mg));
break;
case 'r':
if (projection)
cvResetImageROI(projection);
if (merged_projection)
cvResetImageROI(merged_projection);
if (merged_grid)
cvResetImageROI(merged_grid);
if (output)
cvResetImageROI(output);
break;
case 'R':
reset_defaults();
reset_trackbars();
break;
case 'f':
ocv_mgrid_get_best_projection_distance(cs->mg, &pdist);
fprintf(stderr,"best match %f\n",pdist);
tb_pdist = (int) pdist;
cvSetTrackbarPos("proj_distance", "tbars", tb_pdist);
res = 1;
break;
case 'w':
if (use_camera)
if (!(ocv_ueye_whitebalance(cs->ueye)))
return 1;
break;
case 'W':
save_params(cs);
break;
default:
break;
}
return res;
}
I have no idea why until now!
But i have removed the old OpenCV libraries and compiled the latest version. And now it does distinguish between the upper and lower case letters.
The new version has some subtle differences which are not necessarily good, for example values of track bars cannot be edited by clicking on them anymore. In addition (# kebs) the key strokes have to be masked now with 0xff now!
I don't know maybe i had a weird OpenCV version all along!