1. ## strings check problem

Hello guys (newbie here),
My problem stands for strings. Somehow, I can't check properly if the user entered the correct answer when is asked about unit (wh, kwh and mwh). Thanks!

Code:
```if(choose == 'w') {
printf("Choose unit (wh, kwh, mwh):");
fflush(stdin);
fgets(unit,4,stdin);
for (i = 0; unit[i]; i++){
unit[i] = tolower(unit[i]);
}
printf("Enter the value:"); //sa verifici daca introduce altceva decat decimal sau float
fflush(stdin);
scanf("%f",&whour);

//problem HERE!--------------------------------
for(;;){

if (unit == "wh"){
result = whour * 3600;
break;
} else if (unit == "kwh"){
result = (whour*1000) * 3600;
break;
} else if (unit=="mwh"){
result = (whour*1000000)* 3600;
break;
} else {
printf("Wrong!");
printf("Choose unit (wh, kwh, mwh):");
fflush(stdin);
fgets(unit,4,stdin);
for (i = 0; unit[i]; i++){
unit[i] = tolower(unit[i]);
}
}
}
//problem  Here! --------------------------------------```

2. Don't use fflush(stdin). Its behavior is undefined.

You cannot compare strings with == in C. You need to use strcmp. Google it.

3. fgets will read (if there is space) '\n' into the buffer
so comparing unit to "wh" will fail till you get rid of \n

4. I suggest to turn once the string to a number and then compare the numbers. This is called hashing. For such short strings even perfect hashing (when two different strings never generate the same hash) is trivial.

5. Many many thanks! Like always, very helpful! Right now, I'm trying all of these options.

Zub, first I used numbers to select options, however, somehow if the input required is a number and the user enters a char, at some specific letters (don't remember witch of them), the program will run (Am i wrong if I say that is because of the ASCII code of the letters?).

6. Originally Posted by Ionut Achim
...
Zub, first I used numbers to select options, however, somehow if the input required is a number and the user enters a char, at some specific letters (don't remember witch of them), the program will run (Am i wrong if I say that is because of the ASCII code of the letters?).
I guess that depends on the format specifiers you are using when inputting an option ("%c" or "%d") and the data-type of the option (int or char).

Anyway, zub's suggestion for hashing a string to an int (I guess for efficiency reasons later on in the program) which in your case can be done with perfect-hashing (as also suggested by zub), is a nice option imho, because it will open possibilities for improving your code.

If you want to give another chance in reading ints instead of strings, then the reverse kind of the suggested hashing (int to string) may also prove useful in the long run. With a little extra code for hard-coding the hash-table and a couple of supporting code (an enum and a validation macro) you can have something like this:

Code:
```#include <stdio.h>
#include <stdlib.h>

#define VALID_UNIT(u)  ( (u) > UNIT_NONE && (u) < MAX_UNITS )
enum {
UNIT_NONE = -1,
UNIT_WH   = 0,
UNIT_KWH,
UNIT_MWH,

/* not a unit, just their total count */
MAX_UNITS
};

...

int main( void )
{
int    unit = UNIT_NONE;
char   *labels[MAX_UNITS] = { "wh", "kwh", "mwh" };

...```
You can then use the enumerated values for indexing the labels array and getting the corresponding string, if for some reason you want to handle units as strings instead of int... e.g. for printing them in human readable form.

In such a case, you would input the unit variable from the user, validate it, and then print the label that corresponds to that unit...

Code:
```printf( "Choose unit: " );
if ( 1 == scanf("%d", &unit) && VALID_UNIT(unit) ) {
printf( "you chose \"%s\"\n", labels[unit] );
}```
Actually, the enumerated values may now be used for indexing any array related to your units. For your example, you could define a multipliers array, in parallel with the labels array... something like this:

Code:
```...

int main( void )
{
int    unit = UNIT_NONE;
char   *labels[MAX_UNITS] = { "wh", "kwh", "mwh" };
double multipliers[MAX_UNITS] = { 1.0, 1000.0, 1000000.0 };
...```
so that when the user inputted unit var has been successfully validated, along with the whour var, you can calculate your result directly:

Code:
```...
result = 3600.0 * ( whour * multipliers[unit] );
...```
If you are up to it, you could also warp the labels & multipliers arrays into a struct, or if you are not very fond of parallel-arrays, you could define a struct with a string and a double field, and then define an array of that struct.

Parallels arrays are just fine for getting you started though, imho.

On another note, regarding fflush( stdin ). As already pointed out by Elkvis, this happens to work on Windows, but according to the C standards it produces undefined behavior. If you try it on other platforms, you'll see that on most of them it is not working.

It has to do with the buffered nature of stdin, and a somewhat quick & dirty solution (although not full proff) is to use fgets() along with sscanf() when reading from stdin, using a custom buffer in between.

For example...

Code:
```#include <stdio.h>   /* for BUFSIZ among other things */

int main( void )
{
char input[BUFSIZ] = {'\0'};
double d = .0;

if ( NULL == fgets( input, BUSIZ, stdin )
|| 1 != sscanf( input, "%lf", &d )
){
fputs( "*** error, bye...\n", stderr );
return 1;
}

printf( "You entered: %f\n", d );
return 0;
}```
The user can still mess you up if he/she overflows your input buffer in stdin (you can prevent that too, but the code would be even more cumbersome).

So, all in all... the code-snippet you presented in the 1st post, converted to a small program using what I'm trying to demontsrate in this post, would look something like the following...

Code:
```#include <stdio.h>

#define VALID_UNIT(u)  ( (u) > UNIT_NONE && (u) < MAX_UNITS )
enum {
UNIT_NONE = -1,
UNIT_WH   = 0,
UNIT_KWH,
UNIT_MWH,

/* not a unit, just their total count */
MAX_UNITS
};

/* ------------------------------------------
*
* ------------------------------------------
*/
{
int i;

if ( NULL == labels ) {
return;
}

puts( "Choose unit" );
for (i=0; i < MAX_UNITS; i++) {
if ( NULL == labels[i] ) {
fprintf(
stderr,
"\n%s: NULL element found (labels[%d])\n",
__func__,
i
);
return;
}
printf( "%d. %s\n", i, labels[i] );
}
printf( "> " );
fflush( stdout );
}

/* ------------------------------------------
*
* ------------------------------------------
*/
int main( void )
{
char   input[BUFSIZ] = {'\0'};
int    unit = UNIT_NONE;
double whour = 0;
double result = 0;
char   *labels[MAX_UNITS] = { "wh", "kwh", "mwh" };
double multipliers[MAX_UNITS] = { 1.0, 1000.0, 1000000.0 };

for (;;) {

if ( NULL == fgets( input, BUFSIZ, stdin )
|| sscanf( input, "%d", &unit ) < 1
|| !VALID_UNIT( unit )
){
puts( "*** invalid unit or error, try again...\n" );
continue;
}

putchar( '\n' );
printf( "Enter the value: " );
if ( NULL == fgets( input, BUFSIZ, stdin)
|| sscanf( input, "%lf", &whour) < 1
){
puts( "*** invalid whour or error, start over...\n" );
continue;
}

result = 3600.0 * ( whour * multipliers[unit] );
break;
}

printf( "%f\n", result );

return 0;
}```

7. Code:
```/* My variation of Bernstein algorithm:
1. Perfect hashing for a string consist of no more than 6 symbols of the same type.
For example, alphabetic only or numeric only, but not alphanumeric.
2. Not bad hashing for longer strings.
3. Mixing of different symbols (alphanumeric) may provoke more frequent collisions.
4. Case-insensitive.
*/

unsigned long hash(const char* str)
{
unsigned long h = 0;
unsigned long c;
while( c = (unsigned char) *str++ ) {
c &= 31;
h *= 33;
h += c;
}
return h;
}

double multiplier(const char* const str)
{
static const mult_1 = hash("wh");
static const mult_1000 = hash("kwh");
static const mult_1000000 = hash("mwh");
switch( hash(str) ) {
case mult_1: return 1.0;
case mult_1000: return 1000.0;
case mult_1000000: return 1000000.0;
}
return 0.0;
}```

8. I wish to stress that all hashing involves something called a hash function. Methods that do not use such a function are not hashing, despite claims to the contrary. Zub has it right.

9. Originally Posted by whiteflags
I wish to stress that all hashing involves something called a hash function. Methods that do not use such a function are not hashing, despite claims to the contrary. Zub has it right.
If I get this right, you are suggesting that this for example...

Code:
```#define VALID_UNIT(u)  ( (u) > UNIT_ERR && (u) < MAX_UNITS )
enum {
UNIT_ERR = 0,
UNIT_WH  = 1,
UNIT_KWH,
UNIT_MWH,

/* not a unit, just their total count */
MAX_UNITS
};

int hash( int key )
{
return VALID_UNIT(key) ? key : UNIT_ERR;
}

int main( void )
{
int unit = UNIT_ERR;
char *labels[MAX_UNITS] = { "#ERROR", "wh", "kwh", "mwh" };

printf( "Choose unit: " );
scanf( "%d", &unit );
printf( "you chose \"%s\"\n", labels[ hash(unit) ] );

return 0;
}```
involves hashing, but the code I posted in the previous post, which uses array-indexing directly instead of repeating itself into a hash function, does not involve hashing?

I can understand that the term "hashing" may be a bit of a stretch for this case, but I think you are way too picky for no apparent reason.

10. Code:
```            printf("Choose unit (wh, kwh, mwh):");
fflush(stdin);
fgets(unit,4,stdin);```
For some reason I have seen this a few times: You probably want fflush(stdout), because the printf does not end in a new line character

Code:
```            printf("Choose unit (wh, kwh, mwh):");
fflush(stdout);
fgets(unit,4,stdin);```
A buffer only has to be flushed when the buffer is full, or a new line is detected.
C99 7.19.3 #3 (I have split the paragraphs for readability)
When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block.

When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered.

Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment.

Support for these characteristics is implementation-defined, and may be affected via the setbuf and setvbuf functions.
This being said, most hosted environments will flush stdout without the new line.

I have heard of problems with UNIX, so it is worth keeping in mind.

11. Originally Posted by migf1
I can understand that the term "hashing" may be a bit of a stretch for this case, but I think you are way too picky for no apparent reason.
I did not actually correct you for your benefit.

12. Originally Posted by migf1
If I get this right, you are suggesting that this for example...
Not likely. Your function named hash performs validation (via a macro that contains the actual validation code), not hashing.

Originally Posted by migf1
involves hashing, but the code I posted in the previous post, which uses array-indexing directly instead of repeating itself into a hash function, does not involve hashing?
From what I see, in your code from post #6, the user is required to enter the unit as an integer. Therefore, there is no mapping from key to value, thus there is no hash function needed, i.e., it does not involve hashing. The value is used as-is after validation.

Originally Posted by migf1
I can understand that the term "hashing" may be a bit of a stretch for this case, but I think you are way too picky for no apparent reason.
There is a pretty good reason from what I see: in post #1, the user enters the unit as a string, and indeed zub's suggestion of hashing in post #4 operates on that assumption.

13. Originally Posted by laserlight
Not likely. Your function named hash performs validation (via a macro that contains the actual validation code), not hashing.

From what I see, in your code from post #6, the user is required to enter the unit as an integer. Therefore, there is no mapping from key to value, thus there is no hash function needed, i.e., it does not involve hashing. The value is used as-is after validation.

There is a pretty good reason from what I see: in post #1, the user enters the unit as a string, and indeed zub's suggestion of hashing in post #4 operates on that assumption.
Yes, I believe I was explicit when I was writing:

If you want to give another chance in reading ints instead of strings, then the reverse kind of the suggested hashing (int to string) may also prove useful in the long run. With a little extra code for hard-coding the hash-table and a couple of supporting code (an enum and a validation macro) you can have something like this...

As for the hash() function, if we are to play "who is more picky" guys, then I'm not familiar with any definition that mandates the way any hash function is implemented.

I also very much doubt that there is a strict definition at all.
For example, according to this definition...

Hash function

A hash function is any well-defined procedure or mathematical function that converts a large, possibly variable-sized amount of data into a small datum, usually a single integer that may serve as an index to an array (cf. associative array). The values returned by a hash function are called hash values, hash codes, hash sums, checksums or simply hashes.
...
my redundant hash() function of the previous post, does indeed map a large set amount of data (the int range) into a very small data, (an int of a much smaller range) that is used as an index to an array. Thus, I don't see why it is not qualified as a hash function.

PS. Btw, I don't think that excessive pickiness is in any way constructive.

14. Originally Posted by migf1
I'm not familiar with any definition that mandates the way any hash function is implemented.
There isn't, but not all mapping functions are hash functions. Like "reverse kind of the suggested hashing (int to string)" is just a mapping, not hashing.

Originally Posted by migf1
my redundant hash() function of the previous post, does indeed maps a large set amount of data (the int range) into a very small data, (an int) that is used as an index to an array. Thus, I don't see why it is not qualified as a hash function.
Because it is performing validation, not hashing. You aren't mapping from a valid key to a valid value. Rather, you are checking if a key is invalid, and if so, the result is a value that is used to denote an error, otherwise the valid key is returned as-is. Consequently, your function is not "redundant": it is important because validation is important, but at the same time it isn't hashing. So yes, indeed the function maps a large range into a small range, and indeed the result, including the one that denotes an error, is used as an array index, but it is not the same concept, and portraying it as such does a disservice to learners.

Instead of saying hashing, one could just say: print a menu such that the units are numbered. The user will enter the number corresponding to the unit. Check that the number entered is valid. Here's how you might handle the validation and matching of the number entered to the unit name... (insert code example here).

Originally Posted by migf1
I don't think that excessive pickiness is in any way constructive.
Discussion of important terminology is not excessive and is constructive.

15. If you want to give another chance in reading ints instead of strings, then the reverse kind of the suggested hashing (int to string) may also prove useful in the long run. With a little extra code for hard-coding the hash-table and a couple of supporting code (an enum and a validation macro) you can have something like this...