?
Solved

How can i convert  ascii to char*

Posted on 2003-03-21
18
Medium Priority
?
13,104 Views
Last Modified: 2013-12-14
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
0
Comment
Question by:s2ng
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 4
  • +3
18 Comments
 
LVL 30

Accepted Solution

by:
Mayank S earned 225 total points
ID: 8180382
Man, you already have it. getch () returns an integer and this integer is the ASCII code of a character. Remember, that characters are always stored as integers. It depends upon you on how you interpret them.

There is no need to use itoa () in your program, and as it is since you haven't allocated any memory for for mychar and convert using the new operator, it is not advisable to pass them to itoa () and strcat () without doing so.

Try this:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

void main ( void )
{
  char getkey ;  
  char mychar[6] = "" ; // initially null
  char temp[2] ;

  for ( int x = 0 ; x <= 4 ; x ++ )
  {
    getkey = getch () ; // the equivalent character
    temp[0] = getkey ;
    temp[1] = '\0' ; // null
    strcat ( mychar, temp ) ;  

  } // end for

  printf ( "\n The 5 inputted characters were: %s", mychar ) ;
  getch () ;

} // end of main ()


Hope that helps!

Mayank.

0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8180387
And man! You're using C++. Get into the habit of using cout << instead of printf ().

Mayank.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8180437
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
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Expert Comment

by:fsign21
ID: 8180442
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);
0
 

Expert Comment

by:Leo71
ID: 8180538
@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 ;-).
0
 
LVL 1

Expert Comment

by:fsign21
ID: 8180676
0
 

Expert Comment

by:Leo71
ID: 8183140
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
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8184794
@ 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
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 8185615
There.... I hope you got it.

Mayank.
0
 

Author Comment

by:s2ng
ID: 8185918
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
0
 

Expert Comment

by:Leo71
ID: 8187031
"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
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8188012
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
0
 

Expert Comment

by:Leo71
ID: 8189642
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
0
 
LVL 12

Expert Comment

by:Salte
ID: 8189826
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
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8189986
@ 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
0
 
LVL 12

Expert Comment

by:Salte
ID: 8191066
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
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8193604
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
0
 
LVL 12

Expert Comment

by:Salte
ID: 8193746
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
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
Suggested Courses
Course of the Month11 days, 22 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question