Need help in extracting field values for hexadecimal string

Pages: 12
Its late, and maybe my output above was backwards for your wants. If so you can reverse it easily enough (generate it reversed, don't generate wrong and fix).
All you have to do to reverse it is iterate the string forward, but you have to start at some offset for non multiples of 4, so length %4 as the starting position I think (again, getting late & sleepies).

Either way, is the above, using only string, OK for you now? Or is your own working right now?
Last edited on
I am not sure that his stringstream is doing anything cout won't?


Correct. I was playing with things and could have removed stringstream and just used cout. I was first building the required extract before display. It could be:

1
2
//std::cout << "x = " << x << ", y = " << y << ", extract = ";
std::cout << "0x" << std::hex << std::setw(4) << std::setfill('0') << std::uppercase << res << '\n';

Last edited on
Hello jonnin, JLBorges and others,
Thank you very much for your great C++ code and ideas.
I am currently working with String version of jonnin and some functions & techniques of JLBorges and others and also using my C++ skills.

I am resolving issues with the C++ cross compiler, microcontroller etc.

I will let you all know as soon as I am successful in compiling and running this program.
Thanks again a bunch.

Best regards,
Hi jonnin,

In your following program, how to get binary string s from hex string hx please?

Thanks,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{
  string hx ={"0123456789ABCDEF"};  //the hex digits, [value] = digit eg [15] = 'F'
  string s{"111100001111111111000011"}; //your binary string. 
  string s2 = "000"s + s.substr(1,16); //pad leading zeros because I am lazy.
  //cout << s2 << endl; //the desired substring with leading zeros, ok. 
  //cout << "12345678901234567890" << endl; //19 digits, correct (easy way to count the digits in output)
  string s3; //the result
  
  for(int i = s2.length()-1; i>4; i-=4) //gonna take 4 binary digits and spew out 1 hex digit now. 
  {	
    int dx = s2[i]=='1';
    dx += 2*(s2[i-1]=='1');	
	dx += 4*(s2[i-2]=='1');	
	dx += 8*(s2[i-3]=='1');	
	s3+=hx[dx];	
  }   
  cout << s3 << endl; 
}
In JL Borges following code:
Arm Mbed C++ compiler is giving error by saying:
exceptions, throw are not allowed.

Case statement returning char array is crashing the program.
I think memory allocation is not happening for binary digits array?

hex_str_to_bin_str function is also not working. Crashing the microcontroller program.

Any help in rewrite of these please?

Looks like, writing a one function using C char arrays is only way,
by converting 12 hex chars (+ 1 null char) i.e. 48 binary chars array to
40 binary chars (+1 null char) array after ignoring left 1 bit and right 7 bits?





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <bitset>
#include <string>
#include <climits>

const char* hex_char_to_bin_str( char ch )
{
    switch(ch)
    {
        case '0': return "0000";
        case '1': return "0001";
        case '2': return "0010";
        case '3': return "0011";
        case '4': return "0100";
        case '5': return "0101";
        case '6': return "0110";
        case '7': return "0111";
        case '8': return "1000";
        case '9': return "1001";
        case 'A': case 'a' : return "1010";
        case 'B': case 'b' : return "1011";
        case 'C': case 'c' : return "1100";
        case 'D': case 'd' : return "1101";
        case 'E': case 'e' : return "1110";
        case 'F': case 'f' : return "1111";
        default: throw std::invalid_argument( "bad hex digit" ) ;
    }
}

std::string hex_str_to_bin_str( const std::string& hex_str )
{
    std::string bin_str ;
    for( char ch : hex_str ) bin_str += hex_char_to_bin_str(ch) ;
    return bin_str ;
}

Last edited on
> Arm Mbed C++ compiler is giving error by saying: exceptions, throw are not allowed.

Remove the throw, indicate the error by some other means. For example:

1
2
3
4
5
6
7
8
9
10
11
12
const char* hex_char_to_bin_str( char ch )
{
    switch(ch)
    {
        case '0': return "0000";
        // ...
        case 'F': case 'f' : return "1111";

        // default: throw std::invalid_argument( "bad hex digit" ) ;
        default: return "" ; // bad hex digit; return an empty string
    }
}
Many, many thanks for your great help.
I can't use malloc etc.
I can't return char * etc.

I only need 12 hex chars input array (that is 48 binary digits),
and 10 output hex chars (40 binary digits).

I have to declare in my calling function, 12 + 1 fixed array size hex array and pass to the function as input parameter.
And called function creates 40 + 1 digits/chars fixed size array. Then in this function I will send the 40 chars array to Serial/USB port.

All I need is compact C code lines to ignore 8 bits and regroup 40 digits to 10 hex chars array please.

Thanks and best regards
Last edited on
AlexCantor wrote:
I can't use malloc etc.
I can't return char * etc.

Simple C/C++ is way too advanced for that embedded system? Your compiler is seriously brain-dead.

Maybe you should try the Stone Knives and Bear Skins edition. Fire is optional.
Caveat: untested

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <limits>
#include <cstdio>

using input_hex_str = char[12+1] ; // 12 hex chars (48 bits) input array
using output_hex_str = char[10+1] ; // 10 output hex chars (40 bits) output array

// remove left most 1 bit and right most 7 bits
bool extract( const input_hex_str& input, output_hex_str& output )
{
    // 0. preliminary stuff
    constexpr std::size_t NBITSULL = std::numeric_limits<unsigned long long>::digits ;
    static_assert( NBITSULL >= 48, "we need at least 48 bits " ) ; // sanity check
    constexpr std::size_t EXTRA_BITS = NBITSULL - 48 ; // bits in excess of 48

    // 1. convert the input hex string into an unsigned long long integer
    unsigned long long value = std::strtoull( input, nullptr, 16 ) ;

    value <<= ( 1 + EXTRA_BITS ) ; value >>= ( 1 + EXTRA_BITS ) ; // 2. knock off the leftmost bit of the 48 bits

    value >>= 7U ; // 3. knock off the rightmost 7 bits

    // convert the resultant 40-bit value to 10 hex digits
    std::sprintf( output, "%010llX", value ) ;

    return true ; // TO DO: add validation, return false on failure
}

int main() // usage example
{
    const input_hex_str input = "FF00123456";
    output_hex_str output {} ;
    extract( input, output ) ;
    std::printf( "'%s'\n", output ) ;
}
Your compiler is seriously brain-dead.


It's not the compiler. malloc etc have got nothing to do with the compiler. They're all about the provided library functions. It is quite possible that an environment doesn't have any available RAM - hence no heap and hence no dynamic memory functions.

Writing for embedded systems is not the same as writing for say Windows/Linux et al.

Beautiful & most elegant bool extract function by JLBorges.

It worked, It worked and It worked on Arm Mbed C++ microcontroller board.

Thank you, Thank you, ........... and Thank you JLBorges.

I can never thank you enough.
God bless you for your help.

Super perfect bool extract function. Nothing more. Nothing less. Superb.

bool extract function is the C++ Gem and C++ Gold.

Best regards,
Last edited on

Many thanks to lastchance for the following function and main program:
However, the stoi function call is causing Arm Mbed embedded microcontroller to give following abnormal termination error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
using namespace std;

void extract( const string &str, int &x, int &y )
{
   int i = stoi( str.substr( 4, 2 ), 0, 16 );
   x = ( i >> 6 ) & 1;
   y = i & 63;
}

int main()
{
   int x, y;
   extract( "F0FFC3", x, y );
   cout << x << '\n' << y << '\n';
}
1
3
 Edit & Run


Last edited on
Is it possible to provide alternate code for the following stoi fucntion call please?

Thanks and best regards,


 
   int i = stoi( str.substr( 4, 2 ), 0, 16 );


Last edited on
@AlexCantor,
Is there any web-based interface where we can simulate these ARM embedded systems? Failing that ... some documentation.

It is difficult for a PC-user to see how much C++ your "C++" compiler can actually cope with. It looks like most of the code that you have accepted is C, not C++. At best it is C++98. You seem to be able to use std::string (so, not C), but not many of its functions.

The nearest that I could find online is
https://os.mbed.com/handbook/mbed-Compiler
and that is stated to be severely "deprecated".


The following reverts back to C++98: that's not a good way to go. Are you sure that you are using an up-to-date compiler?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

void extract( const string &str, unsigned long &x, unsigned long &y )
{
   unsigned long i = strtoul( str.substr( 4, 2 ).c_str(), 0, 16 );
   x = ( i >> 6 ) & 1;
   y = i & 63;
}

int main()
{
   unsigned long x, y;
   extract( "F0FFC3", x, y );
   cout << x << '\n' << y << '\n';
}
Last edited on
Many, many thanks lastchance,

Your following code line is not giving abnormal termination:

 
   unsigned long i = strtoul( str.substr( 4, 2 ).c_str(), 0, 16 );


I will find more information about the documentation, on-line emulator etc and post such information here.

I was using Texas Instruments & micron micro controllers for about ten years.
But I am new to Arm Mbed processor. I will find more information.

Again, many, many thanks for your excellent information and help.

Best regards,


Your following code line is not giving abnormal termination:


Well, that's nice to know ... but does it give the intended answer?

It appears that you are currently restricting yourself to C++98, which is workable, but restrictive.

What are you actually compiling with?
Topic archived. No new replies allowed.
Pages: 12