Hello Guys,
Well i have a problem, I coded a program to print the ascii table, then give the user a option to either convert character into ascii or ASCII to character.
Well the latter is not working, and the loop to print the ascii table is having the same trouble.
Well I did that loop earlier, but there i used the characters as it is, having to make the loop little Inefficient. Here i want it to be done in this way...
But Explicit conversion of int to char is causing the trouble....
Please help me out...


Here is the code..

#include<iostream.h>
#include<conio.h>

int main()
{
	clrscr();
	int a,choice;
	char b, choice2;
	cout<<"Would you like to print the ASCII Table first? (Y/N)"<<endl;
	cin>>choice2;
	if(choice2=='y'||choice2=='Y')
	for(int i=0;i<=255;i++)
	{       cout<<endl;
		cout<<(char)i<<" = "<<i<<"   ";
	}
	else
	{ 	cout<<"1.Character to ASCII"<<endl;
		cout<<"2.ASCII to Character"<<endl;
		cin>>choice;
		if(choice==1)
		{
			cout<<"Enter the Character"<<endl;
			cin>>b;
			a=(char)b;
			cout<<"ASCII value is "<<a;
		}
		else if(choice==2)
		{
			cout<<"Enter the Value "<<endl;
			cin>>a;
			b=(int)b;
			cout<<"The character is "<<b;
		}
		else
		cout<<"Invalid Option"<<endl;
	}
	getch();
	return 0;
}

Not all 255 possible ascii characters are printable and you will just see blanks or funny looking squares for them. Here is one way the table should be printed.

Line 31 should be b = int(a);

I think you meant a = (int) b; , or maybe a = static_cast<int>(b); . Just saying.

EDIT: Just noticed that the variables were reversed, too. I've fixed that now.

Edited 5 Years Ago by Schol-R-LEA: n/a

Well the latter is not working, and the loop to print the ascii table is having the same trouble.

The loop to print the ASCII table seems to be working fine (?). The only thing that doesn't work is choice 2 - converting a numerical value into a character (plus one other little bug). Here is that section of code:

cout<<"Enter the Value "<<endl;
cin>>a;
b=(int)b;
cout<<"The character is "<<b;

First of all, you are using a to accept your input, then you ignore it for the rest of the program. Looks like your input got lost in the shuffle! And line 3 is pointless, and here is why. You can't change the type of a variable itself. You can only change it temporally in the middle of an operation, but at the end of the day, a char is still a char, and an int is still an int. You can't change THAT. And it looks like that is what you are trying to do in line 3. b will still be of type char. Here is what is happening in line 3: To the right of the "=" sign you have char b being temporally converted to type int (but just for the moment - as if on scratch paper) to be assigned to b. So now you have an int on the right of the "=" sign that you are trying to stuff into a char on the left. Well the compiler isn't going to "stuff" an int into a char, so it casts the int into a char first, then assigns that to char b.
So you yourself explicitly cast b to type int and then the compiler casts it back to char then assigns it to char b. Sure, it's a good workout, but it doesn't accomplish anything.

Why not just use this code:

cout<<"Enter the Value "<<endl;
cin>>a;
cout<<"The character is "<< (char)a;

Here, int a is momentarily cast to type char for the cout operation.

Now for choice 1 in your code, you have this:

cout<<"Enter the Character"<<endl;
cin>>b;
a=(char)b;
cout<<"ASCII value is "<<a;

In line 3 you are casting char b to type char, which it already is (there's nothing like a good workout!)

So again, why not use this code:

cout<<"Enter the Character"<<endl;
cin>>b;
cout<<"ASCII value is "<<(int)b

Again, we just momentarily cast b to int for the printout.

One more note about a bug in your program. Under choice 1, "Enter the Character", you get wrong results if you enter a character that is in the extended character set, like above ASCII value 127. In case you don't know, you can enter those strange symbols above 127 by holding down the ALT key while typing the ASCII value on the numeric keypad (not the numbers at the top of the keyboard). For example, if I hold down the ALT and type 178, then I would get this character: ▓ (not sure if this character will show up on the board, but it does in the editor box). Anyway, it is a block graphics character. But if you type that in your program, you get wrong results.

Here is the reason: The full ASCII character set consists of 256 characters (including zero) so then that requires a variable that can hold that many values. Now you are using your variable b which is type char. Since a char data type is 8 bits and thus can represent 256 values, all looks well. However, type char, like int, is signed by default. That means that the left most bit is used as a sign bit, leaving only 7 bits to represent a char value. So your variable b can only represent the lower half of the ASCII table. You can remedy this by changing your variable b to unsigned char. Signed char = -128 to 127 and unsigned char = 0 to 255.

Just one more clarification on typecasting: The type of the variable is never really changed, but rather a copy is made of the variable and that copy is type changed for the immediate use in a calculation or operation. With cout << (char)x; a copy of x is made and then that x is changed to type char just for the cout operation. But the original variable x never had it's type changed nor ever could have it's type changed.

The loop to print the ASCII table seems to be working fine (?). The only thing that doesn't work is choice 2 - converting a numerical value into a character (plus one other little bug).

No man! The loop also have some sort of error...

Sure, it's a good workout, but it doesn't accomplish anything.

I guess, you pointed out the way to make my prgm more efficient right? Or Do you mean that i can never get the ASCII value of a character, then save that value to a integer variable (Made it little confusing since you openly referred to "what i was trying to do"?

Here is the reason: The full ASCII character set consists of 256 characters (including zero) so then that requires a variable that can hold that many values. Now you are using your variable b which is type char. Since a char data type is 8 bits and thus can represent 256 values, all looks well. However, type char, like int, is signed by default. That means that the left most bit is used as a sign bit, leaving only 7 bits to represent a char value. So your variable b can only represent the lower half of the ASCII table. You can remedy this by changing your variable b to unsigned char. Signed char = -128 to 127 and unsigned char = 0 to 255.

K I understand, I edited the code so that it only prints what i want to print only (33-126), But still its giving me error, it just prints from from 102 to 126. I can't find what is causing that problem.

Edited 4 Years Ago by PrimePackster: Just added a useless [/QUOTE], now its removed

Just one more clarification on typecasting: The type of the variable is never really changed, but rather a copy is made of the variable and that copy is type changed for the immediate use in a calculation or operation. With cout << (char)x; a copy of x is made and then that x is changed to type char just for the cout operation. But the original variable x never had it's type changed nor ever could have it's type changed.

So does that mean (I know i have asked the same just above), I can't get that value to be saved into another integer type variable? i.e all this type casting just valid in run-time alone?

No, that really isn't what they mean. What MandrewP was saying was that the type cast doesn't change the type of the original variable; it just returns a copy of it's value, changed to the new type. for example, if you have

double a = 17.23;
int b;

b = (int) a;

Then a itself is still a double ; it hasn't changed at all. Only the value passed to b was cast to the new type.

As for the actual problem with the int=>char conversion, you are still getting part of it backwards: you need to cast the value to the type it is being copied into, not the type it is already.

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int a, choice;
    char b, choice2;
    cout << "Would you like to print the ASCII Table first? (Y/N)"<<endl;
    cin >> choice2;
    if(choice2=='y' || choice2=='Y')
    {
        for(int i = 0x21; i <= 0x7E; i += 6)
        {
            cout << setw(6) << static_cast<char>(i) << " = " << setw(3) << i;
            cout << setw(6) << right << static_cast<char>(i + 1) << " = " << setw(3) << i + 1;
            cout << setw(6) << right << static_cast<char>(i + 2) << " = " << setw(3) << i + 2;
            cout << setw(6) << right << static_cast<char>(i + 3) << " = " << setw(3) << i + 3;
            if ((i + 4) < 0x7f)
            {
                cout << setw(6) << right << static_cast<char>(i + 4) << " = " << setw(3) << i + 4;
                cout << setw(6) << right << static_cast<char>(i + 5) << " = " << setw(3) << i + 5;
            }
            cout << endl;
        }
    }
    else
    {
        cout << "1.Character to ASCII" << endl;
        cout << "2.ASCII to Character" << endl;
        cin >> choice;
        if(choice == 1)
        {
            cout << "Enter the Character" << endl;
            cin >> b;
            a = static_cast<int>(b);
            cout << "ASCII value is " << a;
        }
        else if(choice == 2)
        {
            cout << "Enter the Value " << endl;
            cin >> a;
            b = static_cast<char>(a);
            cout << "The character is " << b;
        }
        else
            cout << "Invalid Option" << endl;
    }

    return 0;
}

Captain Jake, if you still have questions or still don't understand something, let us know and we'll try to make it clear. And post all of your code that you have so we can examine it.

Well I understood this part.

else
    {
        cout << "1.Character to ASCII" << endl;
        cout << "2.ASCII to Character" << endl;
        cin >> choice;
        if(choice == 1)
        {
            cout << "Enter the Character" << endl;
            cin >> b;
            a = static_cast<int>(b);
            cout << "ASCII value is " << a;
        }
        else if(choice == 2)
        {
            cout << "Enter the Value " << endl;
            cin >> a;
            b = static_cast<char>(a);
            cout << "The character is " << b;
        }
        else
            cout << "Invalid Option" << endl;
    }

    return 0;
}

But i was not able to understand this loop. Can you please explain it step by step, that will be very grateful of you. You see it differs from my loop a lot...So please....

for(int i = 0x21; i <= 0x7E; i += 6)
        {
            cout << setw(6) << static_cast<char>(i) << " = " << setw(3) << i;
            cout << setw(6) << right << static_cast<char>(i + 1) << " = " << setw(3) << i + 1;
            cout << setw(6) << right << static_cast<char>(i + 2) << " = " << setw(3) << i + 2;
            cout << setw(6) << right << static_cast<char>(i + 3) << " = " << setw(3) << i + 3;
            if ((i + 4) < 0x7f)
            {
                cout << setw(6) << right << static_cast<char>(i + 4) << " = " << setw(3) << i + 4;
                cout << setw(6) << right << static_cast<char>(i + 5) << " = " << setw(3) << i + 5;
            }
            cout << endl;
        }
    }

But i was not able to understand this loop. Can you please explain it step by step, that will be very grateful of you. You see it differs from my loop a lot.

Is there any table you can show me regarding 0x21, 0x7E? And why in each loop i is incremented by 6? And the why those 4 cout statments. I think as long as i don't understand that Interrupt values(I am not sure, if they are called so), i may not be able to understand this loop & same goes for that if statement too.

Captain Jake, if you still have questions or still don't understand something, let us know and we'll try to make it clear. And post all of your code that you have so we can examine it.

Well thats the whole program. And i have already quoted your lines and asked you questions before, in the previous page. I think you must have missed it. Anyway check and please reply. And thanks for your posts..

for(int i = 0x21; i <= 0x7E; i += 6)
        {
            cout << setw(6) << static_cast<char>(i) << " = " << setw(3) << i;
            cout << setw(6) << right << static_cast<char>(i + 1) << " = " << setw(3) << i + 1;
            cout << setw(6) << right << static_cast<char>(i + 2) << " = " << setw(3) << i + 2;
            cout << setw(6) << right << static_cast<char>(i + 3) << " = " << setw(3) << i + 3;
            if ((i + 4) < 0x7f)
            {
                cout << setw(6) << right << static_cast<char>(i + 4) << " = " << setw(3) << i + 4;
                cout << setw(6) << right << static_cast<char>(i + 5) << " = " << setw(3) << i + 5;
            }
            cout << endl;
        }
    }

But i was not able to understand this loop. Can you please explain it step by step, that will be very grateful of you. You see it differs from my loop a lot.

Is there any table you can show me regarding 0x21, 0x7E? And why in each loop i is incremented by 6? And the why those 4 cout statments. I think as long as i don't understand that Interrupt values(I am not sure, if they are called so), i may not be able to understand this loop & same goes for that if statement too.

Oops, I meant to explain about the hex values earlier, but forgot. Values beginning with '0x' are hexadecimal value, that is, base 16 values. These are useful because, unlike decimal values, hex values line up exactly with binary values. If you look at an ASCII table which lists both the decimal and hexadecimal values, you'll see that 0x21 == 33 decimal, which is the first printable character other than a space on the ASCII table. Similarly, 0x7E = 126 decimal, which is the last printable character. If you know hex, then the hex values make more sense for the ASCII table, because the ASCII code is set up so that certain key groups of characters start or end at bit transitions.

I hope that explanation made sense. The takeaway is that they are equal to the same decimal values you were already using.

The other thing I probably should have explained was the use of the setw() manipulators. They are for setting the width of a section being printed (called a field). So if you have as line:

cout << setw(16) << left << "field one" << "field two" << endl;

it will print like this:

field one       field two

It is useful for setting the widths of columns when printing a table.

I probably should explain the static_cast<char>() as well, but the whole issue of C++ style casts is a bit hairy. Suffice it to say that it's just another way of writing a type cast, but with more control over how the value is converted (at the cost of a much uglier syntax).

As for why I used an increment of 6, and printed six pairs of values, (two of which I tested for, the reason is simple: because it prints them across the screen in rows of six, with the last two columns being skipped on the final line because they weren't printable characters. I could have used an inner for() loop, but it was just as easy to do it this way for such a short group.

Comments
This explained a lot for me

Oops, I meant to explain about the hex values earlier, but forgot. Values beginning with '0x' are hexadecimal value, that is, base 16 values. These are useful because, unlike decimal values, hex values line up exactly with binary values. If you look at an ASCII table which lists both the decimal and hexadecimal values, you'll see that 0x21 == 33 decimal, which is the first printable character other than a space on the ASCII table. Similarly, 0x7E = 126 decimal, which is the last printable character. If you know hex, then the hex values make more sense for the ASCII table, because the ASCII code is set up so that certain key groups of characters start or end at bit transitions.

I hope that explanation made sense. The takeaway is that they are equal to the same decimal values you were already using.

Oh i see, thats how it works....

Well i already knew about the that type of type casting & setw. Still your explanation was really helpful...

As for why I used an increment of 6, and printed six pairs of values, (two of which I tested for, the reason is simple: because it prints them across the screen in rows of six, with the last two columns being skipped on the final line because they weren't printable characters. I could have used an inner for() loop, but it was just as easy to do it this way for such a short group.

Well that was very tricky. Thanks for that too...Now let me check it in my program and will let you know..

This question has already been answered. Start a new discussion instead.