views:

256

answers:

4

Hi, I'm a beginning user in C++ and I want to know how to do this: How can I 'create' a byte from a string/int. So for example I've:

string some_byte = "202";

When I would save that byte to a file, I want that the file is 1 byte instead of 3 bytes. How is that possible? Thanks in advance, Tim

A: 

Use boost::lexical_cast

#include "boost/lexical_cast.hpp"
#include <iostream>

int main(int, char**)
{
    int a = boost::lexical_cast<int>("42");
    if(a < 256 && a > 0)
        unsigned char c = static_cast<unsigned char>(a);

}

You'll find the documentation at http://www.boost.org/doc/libs/1_43_0/libs/conversion/lexical_cast.htm

However, if the goal is to save space in a file, I don't think it's the right way to go. How will your program behave if you want to convert "257" into a byte? Juste go for the simplest. You'll work out later any space use concern if it is relevant (thumb rule: always use "int" for integers and not other types unless there is a very specific reason other than early optimization)

EDIT As the comments say it, this only works for integers, and switching to bytes won't (it will throw an exception). So what will happen if you try to parse "267"? IMHO, it should go through an int, and then do some bounds tests, and then only cast into a char. Going through atoi for example will result extreamly bugs prone.

Tristram Gräbener
`sizeof(int)` is usually not `1`.
Georg Fritzsche
Streaming an integer to `cout` will convert it back to a decimal string.
Mike Seymour
I'd change the type from int to a unsigned char, to prevent any values larger than 255.
Alan
+4  A: 

I would use C++'s String Stream class <sstream> to convert the string to an unsigned char.

And write the unsigned char to a binary file.

so something like [not real code]

std::string some_byte = "202";
std::istringstream str(some_byte);
int val;
if( !(str >> val))
{
  // bad conversion
}

if(val > 255)
{
  // too big
}

unsigned char ch = static_cast<unsigned char>(val);

printByteToFile(ch); //print the byte to file.
Alan
But reading an `unsigned char` from the stream will read only one byte, and store it directly. You have to read an `int` in order to make `istream` understand it as a number.
Magnus Hoff
thanks. edited.
Alan
+2  A: 

In C++, casting to/from strings is best done using string streams:

#include <sstream>
// ...
std::istringstream iss(some_string);
unsigned int ui;
iss >> ui;
if(!iss) throw some_exception('"' + some_string + "\" isn't an integer!");
unsigned char byte = i;

To write to a file, you use file streams. However, streams usually write/read their data as strings. you will have to open the file in binary mode and write binary, too:

#include <fstream>
// ...
std::ofstream ofs("test.bin", std::ios::binary);
ofs.write( reinterpret_cast<const char*>(&byte), sizeof(byte)/sizeof(char) );
sbi
+1  A: 

The simple answer is...

int value = atoi( some_byte ) ;

There are a few other questions though.

1) What size is an int and is it important? (for almost all systems it's going to be more than a byte)

int size = sizeof(int) ;

2) Is the Endianness important? (if it is look in to the htons() / ntohs() functions)

Chris Mc
And what happens if I feed nonsense to `atoi()`? -1
sbi
Oh, and the result of `sizeof` is `std::size_t`, not `int`.
sbi
@sbi - what happens if you feed nonsense to your answer? Seriously man.
sheepsimulator
@sbi - re nonsense to atio() GIGO - http://en.wikipedia.org/wiki/Garbage_In,_Garbage_Out
Chris Mc
@sbi- maybe the result of sizeof is a std::size_t- but let's be honest, what the hell kind of sized object do you have where it's size won't fit in an int?
DeadMG
@sheepsimulator: The error is caught and an exception is thrown. That's __very__ different from muddling on with nonsense data.
sbi
sbi
@DeadMG: So what? The result of `sizeof` certainly is of the type `std::size_t`, what's wrong with using that type to store its result? I don't see the point in not doing that.
sbi
Because int is less than half the number of characters and there's no benefit to using std::size_t.
DeadMG
@sbi - Fair enough.
sheepsimulator
@DeadMG: To me it seems you're asking the question the wrong way. It should be "What's the benefit of __not__ using the appropriate type?"
sbi
The benefit of typing "int" over "std::size_t", which is, I am a lazy person and thus saves me nearly 75% of typing, more if you include hitting shift for the colons.On the other hand, I am using C++0x, so I could just type "auto".
DeadMG
@DeadMG: Since a line of code is written only once, but read dozens, hundreds, or even thousands of times, the time it takes to write it is irrelevant compared to the time it takes to read and understand it. See [here](http://stackoverflow.com/questions/2879555/2880136#2880136) for a rant of mine regarding a similar issue.
sbi
@sbi: And the understandability issue between int and std::size_t is.. what, exactly? If you have the vaguest understanding of what sizeof() does, you'll know that it's not important between 2^31 and 2^32/64. OTOH, I seriously agree with you about the std::. I stopped `using namespace std;` after I realized what a horrific mess the standard namespace is anyway and I had to use Intellisense so often, it never saved me any time.
DeadMG
@DeadMG: If I see `int`, for me this automatically means the values stored in the object could be negative. For results of `sizeof` this is obviously wrong, which is why I would look for a deeper meaning in your code. Maybe you later would subtract two such numbers from each other and expect negatives? Or what else could it be? So I try to find some meaning, where you just were too lazy type 8 more characters for the proper type. Even if the code is incredibly simple, the time I spend wondering is very likely several times the time it takes you to type 8 more characters.
sbi
@sbi: I think that is your problem that int is automatically associated that way. Everyone else uses int as the integral type of convenience, as well as for the integral type of negative numbers exceeding -65535.
DeadMG
@DeadMG: Do they now? Ah, that must be why `size_type` maps to `int` in the std lib! I always wondered...
sbi