Read number from file, increment and write back - c++

I want to read a long number from file then increment it and write it back to file.
I am struggling with the convertion from string to long and back again.
I tried:
double id = atof("12345678901"); //using atof because numbers are too big for atio()
id++;
ostringstream strs;
strs << static_cast<long>((static_cast<double>(threadId)));
string output = strcpy_s(config->m_threadId, 20, strs.str().c_str());
But that converts the input to a negative or wrong number.

atoi is for normal integers. There's also atol and atoll (_atoi64 in windows):
//long long id = atoll( "12345678901" );
long long id = _atoi64("12345678901"); // for Visual Studio 2010
id++;
// write back to file here
As suggested by one commenter, use strtoll instead of the ato* functions:
char * data = "12345678901";
long long id = strtoull( data, NULL, 10 );
id++;
Since you're using C++ here, you should just pull it straight from the fstreams:
long long id;
{
std::ifstream in( "numberfile.txt" );
in >> id;
}
id++;
{
std::ofstream out( "numberfile.txt" );
out << id;
}

To go from a C string (char array), use this:
long id = atol("12345678901");
Now you can increment the number. Then, to go from a long to a C++ std::string, use this:
std::ostringstream oss;
oss << id;
std::string idAsStr = oss.str();
Now you can write the string back to the file.

Do you have access to Boost.Lexical_Cast? You could simply do the conversion like this:
double id = boost::lexical_cast<double>("some string");
++id
std::string id_string = boost::lexical_cast<std::string>(id);
and use whatever file transfer you currently have.

Related

C++ Having trouble with sscanf pattern

I am trying to "extract" the name and the next integer. When I run this, I get a run-time error. I have tested without the string and it runs fine.
// Test string
std::string show = "BlahBlah 3";
// Pickup string and int
std::string nameString;
int id;
sscanf(show.c_str(), "%s %i", &nameString, &id);
What am I doing wrong?
sscanf() is a C function, not a C++ function. It has no concept of std::string. You cannot use sscanf() to read into a std::string variable like you have attempted. You need to pre-allocate a char buffer for sscanf() to read into, and then assign that to your std::string, eg:
// Test string
std::string show = "BlahBlah 3";
// Pickup string and int
std::string nameString;
char buffer[32];
int id;
if (sscanf(show.c_str(), "%.31s %i", buffer, &id) == 2)
{
nameString = buffer;
// use values as needed...
}
else
{
// values not parsed...
}
Or, you can preallocate a std::string and have sscanf() fill it:
// Test string
std::string show = "BlahBlah 3";
// Pickup string and int
std::string nameString;
int id;
nameString.resize(32);
if (sscanf(show.c_str(), "%.31s %i", &nameString[0], &id) == 2)
{
nameString.resize(std::strlen(nameString.c_str()));
// use values as needed...
}
else
{
// values not parsed...
}
Since you are using C++, a better option is to use C++ classes to parse the string, eg:
// Test string
std::string show = "BlahBlah 3";
// Pickup string and int
std::string nameString;
int id;
std::istringstream iss(show);
if (iss >> nameString >> id)
{
// use values as needed...
}
else
{
// values not parsed...
}
Well, what you're doing wrong is using sscanf(), a C library function, with std::string, a C++ class. sscanf() does not know anything about C++ classes. sscanf() existed long before C++ was just a glimmer in Stroustrup's eye...

Converting string to char and int data types

I've populated a string vector with with numbers and characters (*,+,-,/). I want to assign each number and character to two new vector, and int vector and a char vector. Is there a way to convert the everything from string to the desired data type?
You can use string stream in the <sstream> header.
string myString = "123";
stringstream sStream( myString );
int convertedInt;
sStream >> convertedInt.
Include the <sstream> header and you can do something like this:
std::vector<std::string> stringVector = /* get data from somewhere */
std::vector<int> intVector;
std::vector<char> charVector;
for (std::vector<std::string>::const_iterator it = stringVector.begin(); it != stringVector.end(); it++)
{
if (it->length() == 0)
continue; // ignore any empty strings
int intValue;
std::istingstream ss(*it);
if (ss >> someValue) // try to parse string as integer
intVector.push_back(someValue); // int parsed successfully
else
charVector.pushBack((*it)[0]);
}
This assumes anything that cannot be parsed as an integer should be pushed into the char vector instead (so, 234, 100000 and -34 will be put into intVector, and /, + etc will be put into charVector). Only the first character of a non-integer value is pushed, so if you have *hello or *123, only * will be put into the charVector.
If you are using C++11, you can swap the std::vector<std::string>::const_iterator with auto to make it look a bit nicer.

Convert octal string to decimal string in C++

What is the easiest way to convert string holding octal number into string holding decimal representation of the same number?
I could convert it into int value using strtol, then convert into string again using stringstream:
string oct_number("203");
// converts into integer
int value = strtol(oct_number.c_str(), NULL, 8);
// converts int to decimal string
stringstream ss;
ss << value;
string dec_number = ss.str();
But: is there any quicker way to do it?
I have a rather poor understanding of the stringstream class, am I missing something?
std::string result;
Try
{
result = std::to_string( std::stoi( oct_number, 0, 8 ) );
}
catch ( ... )
{
//...
}
In c++11 you can use string dec_number = to_string (value);.
Also you can use sprintf but you will need some buffer:
char buf[64];
sprintf(buf,"%d",value);
string dec_number = buf;

Read/write binary object as hex?

I need to serialize various structs to a file.
If possible I'd like the files to be pure ASCII. I could write some kind of serializer for each struct, but there are hundreds and many contain floats and doubles which I'd like to represent accurately.
I can't use a third-party serialization library and I don't have the time to write hundreds of serializiers.
How can I ASCII-safe serialize this data?
Also streams please, I hate the look of C-style printf("%02x",data).
I found this solution online and it addresses just this problem:
https://jdale88.wordpress.com/2009/09/24/c-anything-tofrom-a-hex-string/
Reproduced below:
#include <string>
#include <sstream>
#include <iomanip>
// ------------------------------------------------------------------
/*!
Convert a block of data to a hex string
*/
void toHex(
void *const data, //!< Data to convert
const size_t dataLength, //!< Length of the data to convert
std::string &dest //!< Destination string
)
{
unsigned char *byteData = reinterpret_cast<unsigned char*>(data);
std::stringstream hexStringStream;
hexStringStream << std::hex << std::setfill('0');
for(size_t index = 0; index < dataLength; ++index)
hexStringStream << std::setw(2) << static_cast<int>(byteData[index]);
dest = hexStringStream.str();
}
// ------------------------------------------------------------------
/*!
Convert a hex string to a block of data
*/
void fromHex(
const std::string &in, //!< Input hex string
void *const data //!< Data store
)
{
size_t length = in.length();
unsigned char *byteData = reinterpret_cast<unsigned char*>(data);
std::stringstream hexStringStream; hexStringStream >> std::hex;
for(size_t strIndex = 0, dataIndex = 0; strIndex < length; ++dataIndex)
{
// Read out and convert the string two characters at a time
const char tmpStr[3] = { in[strIndex++], in[strIndex++], 0 };
// Reset and fill the string stream
hexStringStream.clear();
hexStringStream.str(tmpStr);
// Do the conversion
int tmpValue = 0;
hexStringStream >> tmpValue;
byteData[dataIndex] = static_cast<unsigned char>(tmpValue);
}
}
This can be easily adapted to read/write to file streams, although the stringstream used in fromHex is still necessary, the conversion must be done two read characters at a time.
Any way you do it, you're going to need serialization code for
each struct type. You can't just bit-copy a struct to the
external world, and expect it to work.
And if you want pure ascii, don't bother with hex. For
serializing float and double, set the output stream to
scientific, and the precision to 8 for float, and 16 for
double. (It will take a few more bytes, but it will actually
work.)
For the rest: if the struct are written cleanly, according to
some in house programming guidelines, and only contain basic
types, you should be able to parse them directly. Otherwise,
the simplest solution is generally to design a very simple
descriptor language, describe each struct in it, and run a code
generator over it to get the serialization code.

can we store the value printed by printf() into a unsigned long variable?

I have a following array and a printf() stament,
char array[1024] = "My Message: 0x7ffff6be9600";
printf("%.14s", strstr(array, " 0x") + 1);
The output of above printf() is 0x7ffff6be9600,
can we store it into a unsigned long variable?
Look at sscanf
Since you tagged this as C++, see istringstream.
using std::istringstream;
const char source_text[] = "0x7ffff6be9600";
unsigned long value;
istringstream input(source_text);
input >> hex >> value;
Try this:
const char* numBuf = strstr(array, " 0x");
unsigned long number = 0; /* Set default value here. */
if(numBuf)
number = strtoul(numBuf + 1, 0, 0);