Link to home
Start Free TrialLog in
Avatar of s2ng
s2ng

asked on

How can i convert ascii to char*

is there anybody out there who can help me with this
convertion thing in c/c++.

example

ascii = 164    to    char = ñ

algo:
1. get a character from keyboard (using getch() which returns an int)
2. convert the inputted integer to ascii
3. convert the ascii to its corresponding char value

program:

//header files
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

int getkey;  //for holding the value from getch()

// for holding the inputted value which
// will be converted to character
char *convert;

// char storage
char *mychar;

void main(void)
{
   for(int x=0;x<=4;x++)
   {
      getkey = getch(); // getting a character from keboard (returns int)
      itoa(getkey,convert,10); // converts integer to ascii

      //converts ascii to char

      // this line here should convert ascii to char

      // well, this is where i get the trouble
      // i dont know if there's a function for
      // converting an ascii to character
      // could anyone help me out

      // append the converted character to mychar
      strcat(mychar,convert);  
   }
   printf("the 5 inputted characters %s",mychar);
   getch();
}

need ur help badly....

thanks
ASKER CERTIFIED SOLUTION
Avatar of Mayank S
Mayank S
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
And man! You're using C++. Get into the habit of using cout << instead of printf ().

Mayank.
Avatar of Salte
Salte

The character is input in an int.

I believe getch() returns the ascii value as an int or the value EOF (which is not an ascii value). However, provided the value is not EOF - which it shouldn't be from keyboard the value is actually already an ascii value and can be stored into a char directly:

char buf[30];

buf[0] = getkey;

should work.

the ltoa() is something you absolutely don't want to do.

It will take the character value 'q' for example and convert it to a string holding the value "113".

Not sure where you get the '164' from, in octal the ascii value for q is 161 and not 164.

'q' == 113 == 0161 == 0x71
't' == 116 == 0164 == 0x74

so it is possible it is 't' you mean?

In any case, your code thus does the opposite of what you want to do, it takes in a character q and converts it to the decimal representation of that ascii code.

If you want to read a decimal number and print out the ascii character that this represents you must do the reverse:

int x;

cin >> x;

// now you have x equal to for example 113 or some such
// if the characters "113" was input.
if (0 <= x && x <= 127) {
  // x is an ascii value.
  char c = static_cast<char>(x);
  cout << "The character is '" << c << "'" << endl;
}

One problem here is if the character is some control code such as '\n' (which isn't too bad, it will just break the line) or some other you might get odd output, so you might want to limit the output to only regular printable characters and so:

if (0 <= x && x <= 127) {
   char c = static_cast<char>(x);
   if (isgraph(c))
      cout << "The character is: " << c << endl;
   else
      cout << "No glyph associated with this character" << endl;
} else
   cout << x << " isn't an ASCII value" << endl;

Hope this is of help.

Beware that the data type 'char' can usually hold more than just plain ascii. ASCII are values from 0 to 127 but a char is usually a byte and can hold values from -128 to 127 (if char is signed) or values from 0 to 255 (if char is unsigned).

The values from 128 to 255 is not ascii and will typically have different meaning depending on which extention to ascii you're referring to. Unicode defines characters for those codes also, UTF-8 do as well (but they aren't the same) and ISO-LATIN-1 and similar systems do also.

Some character encoding systems uses multiple bytes encoding and so let the values 128 to 255 indicate that there is a 'follow byte' a next byte that is used in combination with this first 'lead byte' to make up the code.

UTF-8 uses values from 128 to 255 also indicate that there are bytes following and also indicate how many bytes will follow so that up to 4 bytes can be used to make a unicode character.

Unicode defines characters even above 255 so a single char cannot be used to hold a unicode character. For this and similar reasons C and C++ also have a wchar_t data type that is used to have characters beyond what one byte can hold. On some systems sizeof(wchar_t) == 2 and on those systems you can't even hold unicode characters but you can hold a UTF-16 code which is almost the same as unicode.

On most systems sizeof(wchar_t) == 4 and then you can store a unicode character in a wchar_t variable and a wchar_t string can be a string of unicode characters.

However, as you originally talked about ascii it is important to note that that only applies to values from 0 to 127. Even if you can store a value of 128 in a char variable there's no ascii character that corresponds to that value.

Alf
If I understand right, you need to read 5 chars from keyboard and store them in mychar.
---------------
1. Do not forget to allocate memory for mychar:
char mychar[6];
or
const int cnt = 5;
char mychar[cnt+1];
---------------
2.
char ch;
for(int x=0; x<cnt; x++) {
ch=getch(); // getting a character from keboard
mychar[x]=ch;
}
mychar[cnt]=0;
printf("the 5 inputted characters %s",mychar);
@mayankeagle:
~quote~
And man! You're using C++. Get into the habit of using cout << instead of printf ().
~quote~
Could you please explain me the advantage of << over fprintf?
I used it only for a very short time befor I went back to use fprintf again. And I'm still satisfied with it after all that years ;-).
Nice page. But it did'nt convince me ;-).
What is totally left out on the page is formatting the output.
Nevertheless I learned a lot. The book I read (6 years ago ore somthing like that :) ) was obviously not very complete.
But I don't think that I will have to inherit from that class.
Also I forgot that of course I use it for object serialization.
I had nothing to do with console I/O for some time :). I need it for assembling error messages and log files.
If you know an appropriate forum we can conitue a discussion there, if you want.

Regards
Leo
@ Leo71:
The advantage of stream-operators over the clumsy printf-family are rather obvious: they work consistently on all streams, which greatly increases the maintainability of code. Another not so obvious advantage: vprintf can cause buffer-overruns, presenting a potential security hazard.
Formatting may feel awkward when you first use it and this impression won't go away for quite some time. Once you see through the system though, it all makes sense.

.f
There.... I hope you got it.

Mayank.
Avatar of s2ng

ASKER

hmnnn... well it did the job...
i thought getch() always returns
an integer.... so thats why the data type
of my getkey is int.

i didnt know that char is okay.

well, thank you very much. congratulations

s2ng
"they work consistently on all streams"
So does fprintf, doesn't it?
But I have to admit that I did'nt try it with sockets yet.
"vprintf can cause buffer-overruns, presenting a potential security hazard"
I'm sure you know what you saying. I thought the security sensitive stuff regardings buffer overflows only concerns input functions, but fortunately I did'nt have these worries.
"Formatting may feel awkward"
I don't know how to format at all. With fprintf I know by hart, what I have to do if I want 4 numbers of a float before the dezimal point and 2 numbers after it.
-But I have to say the MS help improoved. I found how to accomplih that with streams within 5 minutes, while I did'nt find it at all 6 years ago in VC++ 2.0 ;-).
Awkward seems to be understated. I guess for a two line fprintf with some nice formatting I need 30 lines with streaming operators.
I think I reserve the right to be a pighead, an take fprintf for simple output formatting (like log files, errormessages) and use streaming for object serialization, where I greatly benefit from the advantages.

Regards
Leo
Sorry, I meant sprintf, not vprintf, which is probably the easiest way to break into computer systems. My mistake, I admit. But anyway, buffer overruns aren't exclusively present in input functions, although with sprintf the exploit is tightly related to input data.

As for the consistency: Yes, fprintf does work somewhat consistent on streams. But.... you cannot change the target stream quite so easily. Suppose you have a simple logging system that writes info to std::cout. One day you may decide that you want to have the information written to a file. All you have to do is change one line of code, where you declared the stream target:

//ostream& os = std::cout;
ofstream os = ofstream( "debug.log" );

os << "some function entered with argument: " << arg << std::endl;

I do agree on the fact, that formatting is a lot easier to follow with fprintf. After all, there has got to be a reason why a great number of wrapper implementations are around to mimick the fprintf formatting behaviour with stl streams, although your 2 vs. 30 lines of code argument is rather far-fetched. After all, c++ is a context-free language and you can write it all on one line, if you feel like it.

And yes, the MS help is a great tool. Yet judging it by the quality of the stl documentation isn't actually fair. This is just too obvious that MS shows quite some hostility towards stl implementations to push their proprietary class libraries like MFC.

A last note: I'm not evangelizing anything here, just meant to state one of the advantages, while still putting it into perspective by contrasting it with it's shortcomings.

.f
Well I think the thing with stream I/O vs. printf functions is eaten now :). The few things I could still annotate would not bring more light into the discussion :).
But I'm curious about the exploit ;-).
If an input function already accepts the code why does it need the sprintf function to copy it to somewhere else? (Probably not the function itself, but the variable (buffer) that you write to has the overflow).
Also it should not be possible to execute code in the data segment. Or is this the point that with copying (and formatting) the data sprintf might store it in some place where it exceeds the data segment? Should'nt writing to code segment also throw an exception?
-I think I would'nt be the best hacker ;-). May be this exploit would not work on i386 machines?
Also I think that not even 1 percent of the code is so secure that you don't find an easier way than to search for such exploits.
Last not least: I did'nt feel that you're evangelising, but i seemed to me that mayankeagle was.

Regards
Leo
It is true that scanf and friends can easily cause buffer overruns, but so too can iostreams!

char buf[10];

cin >> buf;

input a string of characters where size is too large and the cin above will crash.

You can change that to:

string buf;
cin >> buf;

but the point here is that it is the string that changes and not the stream.

True, you can't make a similar change with sscanf and friends since they won't understand classes etc.

Hoowever, this also shows that the main problem with variable number of argument functions isn't so much that they are variable number of arguments (which by itself is a good thing) but the fact that if you provide a class argument (or struct argument) they cannot handle that properly.

Of course, the best solution to variable number of arguments is probably a C# style solution which is such that you simply declare an array argument that get the parameters collected into one array. The main problem is that it isn't so easy to translate that to C++ or C since it require that you can build an array on the fly. Which in turn requires some form of garbage collection.

Barring that possibility I think C++ has a very good solution in the 'chained operator calls' feature:

T & operator OP (T & t, U u)
{ ......; return t; }

Means that you can chain the calls to operator OP and if it is left associative this means that things are handled in the right order as far as chains of OP is concerned, the rest depends on the priority of OP relative to other operations you might want to do in the chain.

The lack of printf may seem hard but there are ways out of it:

you can create a format class which takes a format string in the constructor and then is fed the values in such operations:

class format {
public:
   format(const string & fmt);
   format(const char * fmt);

   operator const sstring() const;

   format & operator % (int x);
   format & operator % (unsigned int x);
   format & operator % (double x);
   ...etc...

private:

   ...
};

I chose the % operator above, the reasons for that will become cleareer later on but you could have chosen another operator if you wanted to.

In addition you also make:

ostream & operator << (ostream & os, const format & f)
{ return os << static_cast<string>(f); }

Now, I chose the % operator for two reasons:

1. It reminds you of % codes in printf which they are associated with.

2. It is the same as the boost::format library is using and it gets me to the point that you don't have to make a class like this. It's already been made for you.

Check out http:://www.boost.org/libs/format/doc/format.html

Now, personally I think the boost::format class has one big drawback and that is that although it support user defined types it doesn't do so properly. For one thing you don't have user defined type specifications. Also, for user defined types you might want to have more elaborate type specifications.

Personally I think the user defined types should be supported in the way that when you make a function like this:

format & operator % (format & f, const my_type & obj)
{
}

You should be allowed to inside that function call refer to f.cur_format() which indicated the format for this particular object. For this to work you really need a more elaborate format scheme than provided by printf() since that only support predefined types:

for example you could have a scheme saying that a format can start with curly brace and then end with the closing curly brace and anything in between is the format.

In this way %{x} would be the same as simple %x but for user defined types you could do something like:

%{..........}

and by doing f.cur_format() you would get the whole string of data between the curly braces and could interpret that as you wished.

A set of functions to f.set_format(...) could then be used to set the formatter for the basic types as you fed them into the format object.

Functions like cur_format and set_format() shouldn't be used by regular code so:

format fmt(....);

fmt.set_format(....);

should result in an error, but when read in the context of formatting a value the format object enabled these functions for the format object at hand.

For example, let's say you have a clock class that holds the current date and time in some members so that you can do: clock.time() to get a time_t of the time but it could also hold the time more accurately than time_t does (sub second accuracy).

Now, you might want to use strftime() codes for the time and so you can do:

int x = 5;
clock c = clock::now();

cout << format("x = %d, today = %{%d-%M-%Y}") % x % c << endl;


using this overload for the clock type:

format & operator % (format & fmt, const clock & clk)
{
   struct tm x;
   clk.get_tm(x);
   char buf[100];
   strftime( buf, sizeof(buf), fmt.get_format(), & x);
   return fmt % buf;
}

The fmt.get_format() would return the string "%d-%M-%Y".

Personally I would think that would be a better format class.

I might write a such format class one day if I need it myself :-)

Alf
@ Salte:

Doh, why would you mix stream operators with c-strings?!? Do it the correct way and you are safe:

std::string str( "" );
std::cin >> str;

@ Leo71:

The exploit can be very easily used to execute any code code you want on a target machine. It doesn't matter at all, whether the code is located in the data segment, you can execute it nevertheless. To test it, write a little asm function and put it into a char-array and call its address -- no problems there. You are right, that 386+ cpu's have precautions built into hardware that makes it impossible to execute code in the data segment, if the memory descriptor tables are set to those needs. To access those features you will have to get ring-0 access, though, which is usually only granted to device drivers and the OS itself.

.f
fl0yd,

As I said, you can use string instead of C strings but that has absolutely nothing to do with the streams other than the fact that string doesn't work that well with scanf/gets/etc type of functions.

The advantage there isn't so much in the streams but in the string class. The stream only benifit from the fact that the C++ class methods can handle C++ class arguments.

However a format class can also do that - I do think that it is a weakness of the boost::format class that it doesn't handle user defined format - not just user defined types using pre defined formats.

As I said, if I really need it one day I might write a class that does :-)

I also think the std::iostream library has a serious weakness in that the iostream classes has wrong template arguments, they all have 'char' and 'char traits' as template arguments when the stream classes should have had only one template argument being the streambuf type and the char and char traits and any other types should be defined by the streambuf type which really is the one that defines what a stream can do and cannot do.

So, bottom line is that the standard library isn't perfect but it does the job 80% or so of the time and of the remaining 20% of the time you can find workarounds so it works in 15 more percents and with even more trickery you can get it to work 4 more so you get the percentage up to 99% of the time and for the last percent a combination of sprintf() and conversion to string and then output etc and other trickery usually get the job done most of the time. The code however tend to be inelegant in those cases where you're not covered by the initial 80% even if it works.

Alf
Salte,

I disagree with you on the opinion, that the std::iostream has wrong template arguments. Sure, the streambuf is the one that is limiting abilities or diasabilities, but that isn't the point. What the STL uses is called policy-based design and a streambuf just isn't a policy, but rather an implementation specific detail that should be hidden from the user anyway.

At any rate, as Leo71 has already pointed out, the discussion has lost focus on the original question quite some time ago already, so I'm out now.

Regards,
.f
fl0yd,

The point is that it is the streambuf that is the 'interesting' thing about an istream or ostream or iostream class. If you want to expand the behavior of an istream or ostream class today you have to:

1. Make a new streambuf class derived from basic_streambuf.

2. Make a new class derived from istream/ostream/iostream as appropriate.

3. The sole purpose of that stream class is to create a streambuf object of your class and attach it to the stream. The stream itself does little else, yet for that little work you have to do all the nitty gritty things details in order to get your class to work properly.

If the streambuf class had been the template argument you could have written your own streambuf class (which really does most of the work) and that's it.

The point is that the stream classes do the formatting of data etc and that is largely independent of the stream. It does - on the whole - very little else, most of the other code simply delegates the job to the streambuf which does the real job.

However, if you write your own stream class you still have to write many of those functions that delegates the job to the streambuf.

This indicates to me that it is bad design, if they instead had let the streambuf be the template argument it would be easier to extend and easier to use.

Another problem with the current design is that the stream class really depends on the streambuf being 'compatible'. If you try to write a stream using wchar_t having a char streambuf thing simply won't work, the parameter types will clash. This really shows that the stream class' character type really depends on the streambuf's character type and so it really shouldn't be a template argument to the stream class.

Also, streambuf's aren't just 'implementation details'. If they were you wouldn't have streambuf in its own file and showing up as part of the standard interface defined by ANSI C++. streambuf is just as public and standard as are iostream, istream and ostream.

Alf