Hi guys,

I need to write a piece of code which takes two strings (char arrays) containing hex values and perform an AND operation on them. (The aim is to mask bits from the first value). A Mask value of all Fs means that we don't want to mask any bits.

E.g., for these values:

| MemoryAddress | Mask |
------------------------
| 1006 | FFFF |

I would need to simply read the memory address 1006.

For these values:

| MemoryAddress | Mask |
------------------------
| 1006 | FFF0 |

I would need to read memory address 1000.

Really what I think I need to do is to first convert the hex into binary, then perform the AND operation, then convert that back to hex. Any suggestions as to how this could be implemented quickly and easily?

I have made a start with the code below, but it's not going to work because it's converting each char individually, which is of no use to me (1006 in hex is represented as (1 x(16x4)) + (0 x(16x3)) + (0 x(16x2)) + (6 x(16x1)

int TSL1_Convert(char inputData)
/*******************************************************************************

	Name:		TSL1_Convert
					
	Description:	Converts the input char from hex to dec as int 
	Inputs:         inputData:  The char to be converted

	Outputs:        
*******************************************************************************/
{
	iErrorCode = 0;
	int i;
	const char *hexDigits = "0123456789ABCDEF";

	for (i = 0; hexDigits[i] != '\0'; i++)
	{		
		if (toupper ((unsigned char)inputData) == hexDigits[i])
		{
			iErrorCode = 0;
			break;
		}
		else 
			iErrorCode = -108;	// Invalid value in hex string
	}

	return hexDigits[i] != '\0' ? i : -1;	
}


unsigned TSL1_htoi (const char *s)
/*******************************************************************************

	Name:		TSL1_htoi
					
	Description:	Converts the input string from hex to dec as int 
	Inputs:         *s:  The string to be converted

	Outputs:        
*******************************************************************************/
{
	unsigned result = 0;

	while ( *s != '\0' )
	{
		result = TSL1_Convert(*s++);
		if (result != -108)
			result = 16 * result;
	}
	return result;
}

Any help appreciated.

Dani AI

Generated

A couple of safe ways to do this in plain ANSI C.

If both hex strings fit in the machine integer width you control, parse them once and AND the numeric values. The standard C function strtoul handles optional 0x prefixes and accepts base 16; check errno/endptr for invalid input or overflow. For short addresses this is the simplest and fastest approach (this is the same idea behind 's numeric suggestion, but using C library calls instead of C++ streams). See strtoul docs for details: strtoul.

For arbitrary-length hex strings (long addresses or masks longer than the native integer size) do a right-aligned nibble-wise AND: walk both strings from their least-significant hex digit, convert each hex char to a 4-bit value, AND the nibble with the corresponding mask nibble (treat a missing mask nibble as 0xF), and write out the result digits. This approach matches the examples in the thread (e.g. 0x1006 & 0xFFF0 == 0x1000) and avoids converting to a full binary string.

Example ANSI C implementation (handles optional "0x", upper/lower case, trims leading zeros):

#include <stdio.h>
#include <string.h>
#include <ctype.h>

static int hexval(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    c = toupper((unsigned char)c);
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return -1;
}

/* out must be big enough: at least max(strlen(addr),strlen(mask))+1 */
int hex_and(const char *addr_s, const char *mask_s, char *out, size_t out_sz) {
    const char *a = addr_s, *m = mask_s;
    size_t la = strlen(a), lm = strlen(m), i;
    if (la >= 2 && a[0]=='0' && (a[1]=='x' || a[1]=='X')) { a += 2; la -= 2; }
    if (lm >= 2 && m[0]=='0' && (m[1]=='x' || m[1]=='X')) { m += 2; lm -= 2; }
    size_t L = la > lm ? la : lm;
    if (out_sz < L + 1) return -1; /* insufficient space */
    for (i = 0; i < L; ++i) {
        int av = (i < la) ? hexval(a[la - 1 - i]) : 0;
        int mv = (i < lm) ? hexval(m[lm - 1 - i]) : 0xF;
        if (av < 0 || mv < 0) return -2; /* invalid hex digit */
        out[L - 1 - i] = "0123456789ABCDEF"[av & mv];
    }
    out[L] = '\0';
    /* trim leading zeros but leave single '0' */
    for (i = 0; i + 1 < L && out[i] == '0'; ++i) {}
    if (i) memmove(out, out + i, L - i + 1);
    return 0;
}

Notes: right-align the operands (LSB-to-LSB), treat missing mask digits as F (no masking), and check return codes for invalid input or buffer size. This addresses the original concern from about per-character conversion: per-nibble conversion is the correct strategy for arbitrary-length hex masking.

Recommended Answers

All 2 Replies

int num1, num2;
std::cin>>std::hex>>num1;
std::cin>>std::hex>>num2;
int result = num1 & num2;
std::cout<<std::hex<<result;

Sorry I should have mentioned that I can only use standard (ANSI C) library functions in the solution.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.