C function call produces different result than C++ function call - c++

I have this C code:
#include <stdio.h>
#include <windows.h>
int main() {
int i;
while(1) {
for (i = 8; i <= 190; i++) {
if (GetAsyncKeyState(i) == -32767) // That number doesnt actually work, only works with -32768 (which checks to see if the key is pressed down)
printf("%c\n",i); // When using -32768, it prints the key if it is held down about 20 times
}
}
return 0;
}
so -32767 doesnt work in that C code, but I have this C++ code:
#include <iostream>
using namespace std;
#include <windows.h>
int main() {
char i;
while (1) {
for(i = 8; i <= 190; i++) {
if (GetAsyncKeyState(i) == -32767) // works as intended, prints the pressed key letter (doesnt have to be held down)
cout << i << endl;
}
}
return 0;
}
Which works with -32767. This is very confusing as both of these are being ran on the same computer with the same command: clang++ test.c
Output of C with -32768(pressing A):
A
A
A
A
A
A
A
A
A
A
A
output of C++ code with -32767:
A
B
C
D
E
F
G
H
Output of C code with -32767:
(Nothing)

According to the documentation of GetAsyncKeyState:
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.
This says that it is not reliable to treat -32768 differently to -32767. It also says nothing about all of the bits in between, but your code is assuming they are 1 bits without justification.
To be reliable, your code should only do the following tests on the return value:
>= 0 - key currently up, or info unavailable
< 0 - key currently down

Your code relies on implementation-defined behavior. It appears that your C compiler is using unsigned chars, while your C++ compiler uses signed ones. That is why the nested loop in C goes all the way to 190, while the same loop in C++ wraps around to zero upon reaching 128.
You can fix this by making the type of i an unsigned char in both implementations. You could also make i an int, and add a cast to char in the call of GetAsyncKeyState function.

See this topic:
http://www.cplusplus.com/forum/general/141404/
-32767 is actually 1000 0000 0000 0001 in binary, when you compare the returned value from GetAsyncKeyState(i), you're basically asking if only the left and right bits are on, but as it is said in the link above, the bits 1-14 may not always be zero.
A more proper expression would be like that:
if (GetAsyncKeyState(i) & -32767)
or maybe use a hex literal instead:
if (GetAsyncKeyState(i) & 0x8001)

Actually the reason why the C implementation didnt work was because I was manually executing ./a in the mingw32 terminal and for some reason it didn't print anything until after alot of keys have been pressed, so I just executed a.exe by double-clicking and it worked, this has been a very weird experience :/

Related

How to loop through all ASCII characters?

I am attempting to write a program which loops through all ASCII characters, selects those which are letters, appends them to a string and then outputs this string. I have written the following code:
#include <iostream>
#include <string>
#include "ctype.h"
using namespace std;
int main()
{
string str;
for (char k = 0; k <= 255; k++)
if (isalpha(k) != 0) {
str += k;
}
cout << str << '\n';
}
However, when I run this code I get a 'bad_alloc' error, which to my understanding means I ran out of memory. Thus, I must have done something terribly wrong in my code. I am very new to C++ in general, could someone point out my (possibly many) mistakes?
You should enable all warnings when you compile your code (-Wall -Wextra). Doing so would result in the following message by the compiler:
clang:
result of comparison of constant 255 with expression of type 'char' is always true [-Wtautological-constant-out-of-range-compare]
gcc:
warning: comparison is always true due to limited range of data type [-Wtype-limits]
Depending on the compiler and the target platform the signedness of char depends can vary. The defaults for ARM and PowerPC are typically unsigned, the defaults for x86 and x64 are typically signed.
The range of char, if signed, is -128 to 127, to be platform-independent, you need to ensure that you use unsinged char, but even then you would have the problem that <=255 would produce the same bad_alloc error, as the maximum value of a unsigned char is 255, so you have to use `k < 255;':
for (unsigned char k = 0; k < 255; k++)
On many platforms, char is signed. That means it goes to 127 then "overflows".
Overflowing has undefined behaviour, but sometimes that looks like a "wrap-around" to a negative value. The result is that k will always be less than 255, so your loop will never end, and you'll keep trying to add characters to the string forever, or until you run out of memory (boom).
Indeed even if you use an unsigned char, you're still never going to get above 255.
Use an int instead.
Your call to isalpha also has undefined behaviour, for similar reasons (refer to the documentation for functions that you use).
Change for (char k = 0; k <= 255; k++) to for (int k = 0; k <= 255; k++) then it will be fine.
Reason:
Char on the system is signed character, hence it's range is 2^n - 1 to -(2^n) - 1 where n is 8 (you can check it by printing macro CHAR_BIT).
So when the loop for k reaches 127 and goes for the next value, it becomes -128 as the value wraps around & then it becomes the infinite loop.
You can verify this by:
char c=127;
char d=c+1;
printf("%d\n",d);
OUTPUT: -128

Did I miss a code or something?

so I'm trying to write a guess the number game in C++.The computer is Supposed to take a random number with 4 digits then the player should enter a number too.Rules are:
if the computer chooses:1234
And the player enters:1356
1 must be displayed in green,3 must in yellow since it's in the wrong place and 5&6 in red.the game goes on till the player gets the right answer.
#include<iostream>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include<unistd.h>
using namespace std;
int main()
{
int b;
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
cout<<"System is now generating a number...."<<"\n";
int *Number = new int[4];
srand (time(NULL));
for(int counter=0;counter<4;)
{
Number[counter]=(rand()%9)+1;
if(Number[counter]!=Number[counter-1]&Number[counter]!=Number[counter-2]
2]&Number[counter]!=Number[counter-3])
{
counter ++;
}
else
{
counter--;
}
}
cout<<Number[0]<<Number[1]<<Number[2]<<Number[3]<<"\n";
int *Guess=new int[4];
cout<<"please enter 4 digits for your number"<<"\n";
for(int counterG=0;counterG<4;counterG++) //line 34
{
cin>>Guess[counterG];
for(int counter;counter<4&counter>0;)
{
if((counter=counterG)&(Guess[counterG]=Number[counter])) //line 40
{
b=Guess[counterG];
SetConsoleTextAttribute(handle,10);
cout<<b<<"\n";
}
if((counter=counterG)&(Guess[counterG]==Number[counter- 1]|Guess[counterG]==Number[counter+1]|Guess[counterG]==Number[counter-2]|Guess[counterG]==Number[counter+2]))
{
b=Guess[counterG];
SetConsoleTextAttribute(handle,14);
cout<<b<<"\n";
}
else
{
b=Guess[counterG];
SetConsoleTextAttribute(handle,12);
cout<<b<<"\n";
}
}
}
now the program is fine until line 34 but nothing happens after that!
It just gets the player digits
I'd be glad if you could tell me what I've done wrong
Not a complete answer, but it's too long for a comment:
if(Number[counter]!=Number[counter-1]&Number[counter]!=Number[counter-2]
2]&Number[counter]!=Number[counter-3])
This line alone contains a lot of errors:
To have the logical AND operator you need &&, not &.
You have typed an extra 2] at the beginning of the second line. I hope it's just a typo that you introduced when writing the question.
The first time you run this, counter is 0. What happens when you try to access Number[counter-3]? It's an out of bounds access, which leads to Undefined Behaviour, which can lead to anything.
And there are probably many more.
What to do now:
Work on your code indentation. It's really bad.
Start from a much simpler program, and verify that it works. Then, add one small step, verify it, and don't move on until you are happy with the result
Turn on your compiler warnings. Warnings are your friends, not a boring annoyance
Learn how to use a debugger. You won't go very far without debugging.
1- replace & with &&(AND operator)
2- take input in a simple integer variable and then validate the number by performing first check of number greater than 0 and less than 9999.
3- then seperate digits from this variable and then assign those digits to aaray indexes respectvely.

signed char overflow handling with GCC

The below example does not work as I expected (using ">" in the conditional) with GCC on an 8 bit machine, and neither on Linux 64 bit. If I make Timer_Secs and FutureTimeout_1Minute f.ex. 16 bits wide (int in those cases is 16 bits) it works as it should (using ">" in the conditional).
So, to get this to work for 8 bits with sign I seem to have to use "==" in the conditional.
{
// Example with 8-bit only as tested with GCC 3.2 on AVR ATmega 128
unsigned int Cnt1 = 0; // 16 bits (kind of system clock)
unsigned int Cnt2 = 0; // 16 bits (observer, see what happens)
signed char Timer_Secs = 0; // 8 bits with sign
signed char FutureTimeout_1Minute = 60; // 8 bits with sign
while (Cnt1 < 602)
{ // ##
if ((Timer_Secs - FutureTimeout_1Minute) == 0)
{
FutureTimeout_1Minute += 60; // Overflow/underflow allowed,
// so wraps and changes sign
Cnt2++;
} else {} // No code
Timer_Secs++;
Cnt1++;
}
// ##
// Cnt2 is 35 if > 0 above #define AFTER_F(a,b) ((a-b)>0)
// Cnt2 is 35 if >= 0 above #define AFTER_EQ_F(a,b) ((a-b)>=0)
// Cnt2 is 10 if == 0 above #define AFTER_ON_F(a,b) ((a-b)==0) **EXPECTED!**
}
The compare seems to involve some kind of sign conversion. I have not studied the assembly code for the different cases, since I thought this could be solved at code level.
Why is this so?
To me this looks plain wrong?
Still I assume it's compiled like this by design?
Is there some kind of type transfer or type decoration I could have done?
The context here is a blog note called "Know your timer's type" at: [blog]: http://www.teigfam.net/oyvind/home/technology/109-know-your-timers-type/
Disclaimer: this is a private blog with no money, ads, free things for me or etc. involved. Neither I nor anybody get anything from clicking on this url nor any of the urls in any of my blog notes.
It works as expected in Go, see blog note or http://play.golang.org/p/lH2SzZQEHG
It does not seem to work as expected in C++ either.

Variable declaration in c++

when i run the following c++ code
#include<iostream>
int main()
{
for(int i=1;i<=10;i++)
{
cout<<i<<endl;
}
cout<<i;
getch();
return 0;
}
I get result from no. 1 to 11.
i don't understand why the value of i = 11 after the block of for loop is finished,Please give me the reason.I have declared i inside for loop and scope of i has been finished after loop so why i get the outpout i=11 after execute second cout statement .I have not declared i in the variable declaration inside main.My question is that is i is visible outside of for loop?
Thanks in advance.
For multiple reasons, this program does not compile. You are either using an extremely old compiler, an extremely permissive compiler, or not showing us the program you're actually having a problem with.
From your comments it seems that you actually can compile it. I can only guess that you are using a very old compiler. Perhaps an old MS-DOS compiler (Zortech C++? Turbo C++?) since the getch function is not generally a standard library function and doesn't do the right thing in the curses library anyway. It's probably an old BIOS-based function from the MS-DOS days.
The standard was changed awhile ago (over 10 years now) so that variable declarations in the parenthesized section of a for loop are local to that loop. It was once not actually the case that this was true.
I no longer have access to any compiler that's so old it doesn't handle things this way. I'm surprised anybody does. Your program will not compile on my compiler.
Here is a version of your program that does compile, even though it requires the -lcurses option to link:
#include <iostream>
#include <curses.h>
using ::std::cout;
using ::std::endl;
int main()
{
for(int i=1;i<=10;i++)
{
cout<<i<<endl;
}
getch();
return 0;
}
Notice how the offending cout << i; statement is gone? That because it will not compile on a modern compiler.
Now, lets edit your program some more so it will compile with the cout << i; statement you're vexed about:
#include <iostream>
#include <curses.h>
int main()
{
using ::std::cout;
int i;
for (i = 1; i <= 10; i++)
{
cout << i << '\n';
}
cout << "last: " << i << '\n';
getch();
return 0;
}
This, of course, does print out last: 11 at the very end. This happens for a very obvious reason. What value does i have to have in order for the i <= 10 test to fail? Why, any value greater than 10! And since i is having one added to it every loop iteration, the first value i has that has the property of being greater than 10 is 11.
The loop test happens at the top of the loop and is used to decide if the remainder of the loop should be executed or not. And the increment happens at the very bottom of the loop (despite appearing in the body of the for statement). So i will be 10, will be printed, and then 1 will be added to it. Then the loop test (i <= 10) will be done, it will be discovered that 11 <= 10 is false, and control will drop out of the loop down to the print statement after the loop, and last: 11 will be printed.
And yes, the exact same thing will happen in C.
Because the loop breaks when the condition i<=10 becomes untrue, and this can happen when i becomes 11. Simple!
I think you wanted to write i < 10 .
Also, as #Omnifarious noted in the comment, the code shouldn't even compile, as i doesn't exist outside the loop. Maybe, you've declared i outside the loop, in your original code?
Besides the fact that it shouldn't compile (because i doesn't exist outside the loop block).
The loop runs from 1 to 10, so it stops when i reaches 11 and the condition fails. So i is 11 in the end of the loop.
This is because you have an old compiler.
cout<<i<<endl; should not compile, as cout and endl need to be qualified by the std namespace.
Fixing that, std::cout<<i; shouldn't compile because your variable is loop-scoped, so shouldn't even be visible outside the loop.
Fixing that, here's your code:
#include<iostream>
#include<conio.h>
int main()
{
int i;
for(i = 1; i <= 10; i++)
{
std::cout << i << std::endl;
}
std::cout << i;
getch();
return 0;
}
It should become more obvious why 11 is printed now.
When i == 10, the loop executes, increments i, and checks its value. It is then equal to 11, so it exits the loop.
Then you have another print statement, that will print the post-loop value, which is 11.
Here's the output I get from that corrected program:
1
2
3
4
5
6
7
8
9
10
11
This is the same as you are getting.
If you only want to print 1-10, then why have the extra std::cout << i;?
Recommendation
Get an up to date C++ compiler that will give you syntax errors on things that are no longer valid in standard-compliant C++
Get rid of the extra std::cout << i;
Keep your i variable loop-scoped, as in your original code
The result from my recommendations will be that you only see 1 through 10 printed, and you will have slightly fewer unexpected surprises in the future (as some "bad" and surprising code won't even compile).

error when i give sleep(1000), to make srand() work, in visual C++

i have following program:
srand((unsigned) time(NULL));
for (int w = 0; w < 10; w++) {
int ran_x;
ran_x = rand() % 255;
cout << "nRandom X = " << ran_x << endl;
//some more lines of code
Sleep(1000);
}
I am running it on visual c++ 2008, When I run this program, it doesnt show any errors or warnings. But when I run it, some of the times it runs fine, and some of the times it stops in the middle and gives this error "This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information."
What shall I do? Is it possible to do it with out using Sleep() function and still get randomly generated values. Because if I remove Sleep(1000), it doesnt give any error but it doesnt gives random values either
Obviously you shouldn't have to sleep. Code looks sane to me, as long as you only call srand() once. If you call this entire block of code multiple times intra-second, then time(NULL) will be returning the same second value and srand() will start the pseudo-random number generation at the same number, selecting the same set of 10 subsequent numbers....
Works without any problems with gcc
#include <iostream>
#include <cstdlib>
int main (int argc, char *argv[])
{
srand( time(0) );
for (int w = 0; w < 10; w++)
{
int ran_x = rand() % 255;
std::cout<<"\nRandom X = " << ran_x << std::endl;
sleep(1);
}
return 0;
}
Seems to me your program should work perfectly without the sleep call. In fact seems to work for me on VS2008 perfectly. I believe your problems must be in code that you have removed thinking it irrelevant.
The code snippet you posted is hardly responsible for your application terminating, Sleep or not.
Because if I remove Sleep(1000), it
doesnt give any error but it doesnt
gives random values either.
Well, rand() certainly gives you pseudo-random numbers, although the PRNG implementation might not return random values evenly distributed along the bits of the returned value, i.e. in many implementations, the higher bits are changing more often than the lower bits, which is why your code is a poor choice for selecting a random value between 0 and 255.
In general, I'd recommend switching from your standard library's rand/srand to an implementation like boost's mersenne twister (boost::random), or at least see
http://c-faq.com/lib/randrange.html
What's the content of "some more lines of code"?
<psychic debugging>I bet you have code that there that, directly or indirectly, depends on the random value you generated earlier. This code will likely be a division, or involve setting the length of some container, and borks when the generated random number is 0.</psychic debugging>