1

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

sbi
  • 219,715
  • 46
  • 258
  • 445
cutsoy
  • 10,127
  • 4
  • 40
  • 57
  • show writer code, because in there is the bug – Svisstack Jun 01 '10 at 16:20
  • 1
    So you're new to C++, so here are a few pointers: 1) write C++ code, or C code. Don't mix and match. 2) http://www.parashift.com/c++-faq-lite/ is an awesome place to learn how to write C++ code. – Alan Jun 01 '10 at 16:35
  • By mix and match, I mean, don't mix and match C and C++ idioms. You can call C code from your C++ code, and likewise allow C code to call your C++ code. – Alan Jun 01 '10 at 16:49

4 Answers4

4

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
  • 45,915
  • 17
  • 113
  • 134
  • 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 Jun 01 '10 at 16:36
2

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
  • 219,715
  • 46
  • 258
  • 445
2

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
  • 64
  • 3
  • And what happens if I feed nonsense to `atoi()`? -1 – sbi Jun 01 '10 at 16:44
  • Oh, and the result of `sizeof` is `std::size_t`, not `int`. – sbi Jun 01 '10 at 16:44
  • 1
    @sbi - what happens if you feed nonsense to your answer? Seriously man. – J. Polfer Jun 01 '10 at 16:56
  • @sbi - re nonsense to atio() GIGO - http://en.wikipedia.org/wiki/Garbage_In,_Garbage_Out – Chris Mc Jun 01 '10 at 17:02
  • @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? – Puppy Jun 01 '10 at 17:13
  • @sheepsimulator: The error is caught and an exception is thrown. That's __very__ different from muddling on with nonsense data. – sbi Jun 01 '10 at 17:27
  • @Chris: That wikipedia page, in its current form (http://en.wikipedia.org/w/index.php?title=Garbage_In,_Garbage_Out&oldid=365241305), __very nicely__ demonstrates the results of such a philosophy in its very first sentence. Honestly, that's a fine philosophy when you create a small, lightweight command line utility. When you create a piece of library code, it hurts. – sbi Jun 01 '10 at 17:31
  • @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 Jun 01 '10 at 17:33
  • Because int is less than half the number of characters and there's no benefit to using std::size_t. – Puppy Jun 01 '10 at 18:10
  • @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 Jun 01 '10 at 18:56
  • 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". – Puppy Jun 01 '10 at 19:31
  • @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 Jun 07 '10 at 16:07
  • @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. – Puppy Jun 07 '10 at 17:38
  • @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 Jun 08 '10 at 13:26
  • @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. – Puppy Jun 08 '10 at 15:38
  • @DeadMG: Do they now? Ah, that must be why `size_type` maps to `int` in the std lib! I always wondered... – sbi Jun 08 '10 at 19:50
-1

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
  • 9,601
  • 3
  • 34
  • 50