Read hex characters from an ini file - c++

I have an ini file with some hex characters,like this:
[FOO]
1=0x55
2=0x40
3=0x90
First, is this the right format for an ini file, or should i use \x50?
Second, how can i read the characters? i have this:
char Frame[4]
TIniFile* IniFile;
IniFile=new TIniFile(cPath+"\\"+"setup.ini");
for( int i = 1; i < 4; i++ )
{
Frame[i]=IniFile->ReadString("FOO",i,-1);
}
The problem is that IniFile->ReadChar doesn't exist (i am using borland c++ builder 6).
how can i cast the string (0x55 for example) to a char? so i can put it in the Frame array

The \x55 notation is typically used within string literals:
const char* s = "\x55";
When writing to a file 0x55 is common, but ultimately it is up to the code processing the file to know what it is consuming.
I cannot comment on IniFile but if you can manage to store the value into a char[] you can use std::strtol() to obtain the integer value:
const char* s = "0x55";
long value = std::strtol(s, 0, 16);
Also, note that the for loop is going beyond the bounds of array Frame as array indexes are zero based. The valid indexes for Frame are 0, 1 and 2 only but the loop would access 3 which is undefined behaviour. Change to:
for(int i = 0; i < 3; i++)
Note the for loop will not populate the first element of Frame, as array indexes are zero based (unsure if that is intentional).

Solution:
AnsiString string;
TIniFile* IniFile;
IniFile=new TIniFile(cPath+"\\"+"setup.ini");
for( int i = 1; i < 5; i++ )
{
string=IniFile->ReadString("FOO",i,-1);
Frame[i]=static_cast<char>(std::strtol(string.c_str(), 0, 16));
}

Since you are using the VCL, you can use the StrToInt...() family of functions, which support 0xXX notation in C++, and then cast the result to char, eg:
for( int i = 0; i < 4; i++ )
{
Frame[i] = (char) StrToIntDef(IniFile->ReadString("FOO", i+1, ""), -1);
}
Or:
for( int i = 0; i < 4; i++ )
{
Frame[i] = (char) IniFile->ReadString("FOO", i+1, "").ToIntDef(-1);
}

Related

Objective-C to C++ reading binary file into multidimensional array of float

I want to convert the following code from objective C to C++.
In the class myClass, I have this attribute:
float tab[dim1][dim2][dim3];
In an objective-C file, the multidimensional array is filled from a binary file:
NSData *dataTab=[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pathOfMyTab" ofType:#""]];
[dataTab getBytes:myClass -> tab length:[dataTab length]];
How could I translate this part into C++ ?
I am assuming that your file contains the byte-representation of the array. If this is the case, then to mimic the behaviour of your Objective-C code using only C++ (the only thing that makes this C++ is the reinterpret_cast<>, otherwise it is just straight C), you could use the following code. I have not added any error checking, but left some comments where you might want to perform some.
float tab[dim1][dim2][dim3];
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef dataTabURL = CFBundleCopyResourceURL(mainBundle, CFSTR("pathOfMyTab"), NULL, NULL);
CFReadStreamRef stream = CFReadStreamCreateWithFile(NULL, dataTabURL); // check for NULL return value
CFReadStreamOpen(stream); // check for errors here
CFReadStreamRead(stream, reinterpret_cast<UInt8 *>(tab), sizeof tab); // check that this function returns the number of bytes you were expecting (sizeof tab)
CFReadStreamClose(stream);
// we own "stream" and "dataTabURL" because we obtained these through functions
// with "create" in the name, therefore we must relinquish ownership with CFRelease
CFRelease(stream);
CFRelease(dataTabURL); // ditto
If you already have the path available in a std::string, then you can use the following C++ code to mimic the behaviour of your Objective-C code:
// make sure to include this header
#include <fstream>
// ... then elsewhere in your .cpp file ...
float tab[dim1][dim2][dim3];
std::string path = "path/to/mytab"; // obtain from somewhere
std::ifstream input(path, std::ios::binary); // check that the file was successfully opened
input.read(reinterpret_cast<char *>(tab), sizeof tab); // check that input.gcount() is the number of bytes you expected
I believe in this case we have to use reinterpret_cast<> because the file contains the actual representation of the array (assuming it was previously written to the file in a similar manner).
You can use a hybrid approach, once you have the CFURLRef containing the path to the resource, you can obtain a file system representation of the URL using this function (providing a suitably sized output buffer to store the result), and from there you should be able to pass that to one of std::ifstream's constructors (although, you may need to cast to the appropriate type).
C++ doesn't support variable-length arrays (the size of arrays must be known at compile time). There is also no matrix type provided by the standard library, so if the dimensions of your table vary at run time, then you will need a completely separate approach to the one in my answer. You could consider serialising the output from Objective-C (using e.g. JSON or another format) such that the dimensions of the matrix are also written to the output, making it easier to parse the file in C++.
Take a look at fstream, fread and read, all read binary files, pick the approach that suits.
On my mind the simplest and fastest way is to use memcpy() to copy NSData' bytes into target array with same structure (dimensions) as a source one. See, for example:
https://github.com/Voldemarus/MultiDimensionalArrayDemo/tree/master
#import "DemoClass.h"
#define DIM1 3
#define DIM2 4
#define DIM3 2
#interface DemoClass() {
int src[DIM1][DIM2][DIM3]; // source (initial) array
int dst[DIM1][DIM2][DIM3]; // destination array
}
#end
#implementation DemoClass
- (instancetype) init
{
if (self = [super init]) {
for (int i = 0; i < DIM1; i++) {
for (int j = 0; j < DIM2; j++) {
for (int k = 0; k < DIM3; k++) {
int value = i*100 + j*10 + k;
src[i][j][k] = value;
}
}
}
}
return self;
}
int getIntFromArray(int *array, int i, int j, int k) {
int offset = j*DIM3 + i*DIM2*DIM3;
return array[offset];
}
void putIntToArray(int *array, int i, int j, int k, int value) {
int offset = j*DIM3 + i*DIM2*DIM3;
array[offset] = value;
}
- (void) run
{
// Step 1. Save array into NSData
NSInteger s = sizeof(int)*DIM1*DIM2*DIM3;
NSData *data = [[NSData alloc] initWithBytes:src length:s];
NSAssert(data, #"NSData should be created");
//Step2 - Create new array
int *bytes = (int *)[data bytes];
memcpy(dst,bytes,s);
// Step 3. Compare src and dst
for (int i = 0; i < DIM1; i++) {
for (int j = 0; j < DIM2; j++) {
for (int k = 0; k < DIM3; k++) {
int template = i*100 + j*10 + k;
int s = src[i][j][k];
int d = dst[i][j][k];
// NSLog(#"i %d j %d k %d -->s = %d d = %d",i,j,k,s,d);
NSAssert(s == template, #"Source array should have value from template");
NSAssert(d == s, #"Destination array should be identical to the source");
}
}
}
}
#end
float tab[dim1][dim2][dim3] looks like a three-dimensional array. The standard implementation is with three nested FOR loops.
So your C++ implementation can look like this:
read dim1, dim2, dim3 from somewhere, usually the first values in the file (for example 12 bytes, 4 bytes for each number)
read the rest of the file in three nested FOR loops
Something like:
for (size_t i = 0; i < dim1; ++i)
for (size_t j = 0; j < dim2; ++j)
for (size_t k = 0; k < dim3; ++k)
tab[i][j][k] = read_float_value(inputFile);
In Objective-C you can write the file in a similar way.
Here are some examples to get you started:
Three dimensional arrays of integers in C++
3D array C++ using int [] operator

Comparison between signed and unsigned integer expression for loop error

I was writing a program that went through a string but in the for loop it gave me an error and the answers online that I found used only vectors.
std::string str = "Test";
for (int i = 0, max = str.size; i < max; i++)
std::string::size is a member function, you need to call it:
for (int i = 0, max = str.size(); i < max; i++)
// ^^ here
... and in order to make the issue with signed-unsigned conversion go away:
for (std::size_t i = 0, max = str.size(); i < max; i++)
// ^^^^^^^^^^^ index type for standard library container
Besides, if you need to process every char in the string, consider using a range based for loop;
for (char c : str)
// ...

Filling and comparing char* inside a function

I wrote the function readChar() which is designed to read the characters send by my WiFi module one by one(function works has advertised) and pass them to a char buffer of increasing size. The function should stop when char *endChar (multiple characters) have been detected or the number of character returned by timedRead() has exceeded size_t length.
I have several issues:
1/. I don't understand the syntax (found inside the Arduino Stream library) :
*buffer++ = (char)c;
Can you explain how the array buffer gets filled?
And why buffer[index] = (char)c; doesn't work here?
2/. I would like to compare buffer and endChar in the loop, possibly by using strcmp(buffer,endChar) (maybe there is a better way). But that doesn't seem to work. In fact when printing the ASCII values of my char *buffer then seem to increment from the end of the buffer. E.G.:
So what is the best way to do that comparison?
The code, inserted in the loop:
_dbgSerial->println("buffer");
for (int i = 0; i < 32; i++){
_dbgSerial->print(buffer[i], DEC);
_dbgSerial->print(",");
}
_dbgSerial->println("");
prints:
buffer
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,10,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,10,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,10,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,10,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,10,13,10,0,0,0,0,
Here is the function readChar():
size_t Debugwifi::readChar(char *endChar, char *buffer, size_t length) {
if (length < 1) return 0;
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 ) break;
//buffer[index] = (char)c;
*buffer++ = (char)c;
_dbgSerial->println("buffer");
for (int i = 0; i < 32; i++){
_dbgSerial->print(buffer[i], DEC);
_dbgSerial->print(",");
}
_dbgSerial->println("");
if (strcmp(buffer,endChar)==0) {
break;
_dbgSerial->println("brk");}
index++;
}
return index;
}
As Rickard has explained, *buffer++ = (char)c; is how you assign a character to the memory a pointer points at, and then increment the pointer.
However, your function has a lot of problems - you keep comparing unset memory with *endChar. I suggest:
size_t Debugwifi::readChar(const char * const endStr, // const pointer to const.
char * const buffer, const size_t length) {
if (length < 1) return 0;
const size_t endLen = strlen(endStr);
for (size_t index = 0; index < length; index++) {
const int c = timedRead();
if (c < 0 ) break;
buffer[index] = (char)c;
// Debug
_dbgSerial->println("buffer");
for (size_t i = 0; i < length; i++){ // Better to use size_t here,
// and compare against length not 32
_dbgSerial->print(buffer[i], DEC);
_dbgSerial->print(",");
}
_dbgSerial->println("");
// Finished?
if (index >= endLen) {
if (memcmp(&buffer[index-endLen], endStr, endLen)==0) {
_dbgSerial->println("brk"); // Must do this *before* "break"!
break;
}
}
}
return index;
}
I have added a lot of consts. It's hard to have too many.
The important point is that once you have read enough characters, to start comparing the last characters you have read to the end marker.
Note that this function does not remove the end marker, and if you pass a 32-byte zero-filled array and it reads 32 characters, the result will NOT be zero terminated.
Finally, I changed the argument name to endStr because I had expected endChar to be a pointer to a single character - not a NUL-terminated string.
*buffer++ = (char) c;
First writes the value of c to what buffer is currently pointing to.
Then it increments the buffer
This is also why your loop to print buffer doesn't work.
You start printing from the position after what was just filled.
This is also why your strcmp doesn't work. It doesn't actually compare what you have filled your buffer with. It compares the content beyond what have been filled.
If you want your printing code to work you should save the initial value of buffer before the loop;
const char *buffer_start = buffer;
Then use that in your printing code instead of buffer.

Writing a loop to change the value in a int array with different names

My title is a bit confusing, but I'm trying to write a loop that will change the value in 81 arrays with different names. I want to either initiated the array with a value or an array of values. This is part of my sudoku solver code since I don't think I'm explaining it well.
int cell1[], cell2[9], cell3[9],cell4[9]......cell81[9]; // <-- this will make 81 cells with an array that can hold a possible of 9 candidates
cout << "User input: << endl; // lets use ...1.5...14....67..8...24...63.7..1.9.......3.1..9.52...72...8..26....35...4.9...
// as an example
Let's assume I store that input into a Char Array and I'm going to use a loop to decide whether to initiate the given value or '.' as an empty value.
For empty values, I'm looking to initialize the array with 1-9 values. I can do this easily with this code.
If( ( (int)charArray[ 0 ] - 48) > 0 ) { // type cast to int. Neg = initialize array with 1-9
// pos = initialize with original value
cell1[ 0 ] = (int)charArray[ 0 ] - 48;
} else {
cell1[ 9 ] = { 1,2,3,4,5,6,7,8,9};
}
I want to avoid writing this code 81 times for 81 cells ( Considered as writing junk code ). I can't figure out how to write the loop. I'm open to suggestions on how I can code this different using classes, functions, and etc. Thanks in advance.
Create the cell array as a 2-dimensional array, with 81 rows and 9 columns.
int cell[81][9];
Now you can loop through them using the syntax cell[r][c]. For instance,
for( i = 0; i < 81; ++i ) {
cell[i][0] = 1;
// ...
cell[i][8] = 9;
}
If you'd prefer to avoid 2-D arrays, you can declare the array as a 1-dimensional array, and just index into it appropriately.
int cell[81 * 9];
for( i = 0; i < 81; ++i ) {
cell[i + 0*81] = 1;
// ...
cell[i + 8*81] = 9;
}
int a1[9],a2[9],a3[9],a4[9],...
void init_array(int *ptr, const char *chr, int len, int start){
for(int i = start; i < len; i++){
if(chr[i] == '.')continue;
ptr[i] = chr[i]-'0';//converts character to integer.
}
}
int main(int argc, char **argv)
{
std::string str;
cin >> str;
init_array(a1,str.c_str(),9,0); init_array(a2,str.c_str(),9,9/*increment by 9*/);...
//..
return 0;
}
Write a function called init_array() that accepts an integer pointer and initializes the array for you. You can avoid duplicating the code this way.

Calculating the hexadecimal of the elements of a string/array and then convert these to decimal

I have a UI designed with wxwidgets in which I enter a user name. I want the hexadecimal sum of all the elements which would then to be converted to decimal. This is what I have done:
wxArrayString TextAlia = wxT("");//declared global
TextBox1 = new wxTextCtrl(this, TEXT_BOX1, wxT(""), wxPoint(300, 10), wxSize(100, 20), wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxTE_LEFT, wxDefaultValidator, wxT("WxTextBox"));
void MyFrame::OnGenerateKey(wxCommandEvent& WXUNUSED(event)) {
int i;
char name[i];
TextAlia = TextBox1->GetValue();
i = strlen(TextAlia);
for (i = 0; i < strlen(TextAlia); i++) {
char buffer[3];char Temp[3];
_itoa( name[i], buffer, 16 );
}
This is what I have tried to do please help me.
What now id did is :
int lengtharray = sizeof(name)/sizeof(name[0]);
for (int j=0; j<lengtharray; j++)
{
name[j] = ?//i need to write something here so that the name[1] is changed to 45 for
capital "E"
// avariable may be of type hex just like sum that keeps on incrementing the value
}
If I understand correctly, you want to sum the number representation of characters in a string. I'm not familiar with wxwidgets, I think it uses its own string type, but I'll show how to do it with c-style strings and c++ std::strings. The first thing to note is that char is just a numeric type able to store at least the numbers 0 to 127. You can use it directly in a sum. It's just when you print it out it gets turned into recognisable letters.
I've pasted a simple program here: http://ideone.com/dqIE5 with two functions that show how to loop over characters in a string and sum them. In both cases you just have a loop over the characters, adding to a running sum.
There are also several errors in the code you show. First:
int i;
char name[i];
There are two mistakes here. You try to use i without initialising it (giving it a value). How big do you expect name to be? Second, the size of an array must be a constant, known at compile time. So you could do something like
const int i = 10;
char name[i];
Another probable mistake:
i = strlen(TextAlia);
for (i = 0; i < strlen(TextAlia); i++) {
You set i to the length of TextAlia and then immediately set it to 0. Then call strlen over and over. Perhaps you want:
int length = strlen(TextAlia);
for (i = 0; i < length; ++i) {
i = strlen(TextAlia);
int sum = 0;
for (int j = 0; j < i; ++j) {
sum += TextAlia[j]
}
char* a = new char[40];
sprintf(a, "%d", sum); // decimal value
sprintf(a, "%x", sum); // hexadecimal value