Check if a String is a Valid Hexadecimal Number in C

A valid hexadecimal string in C is one that may optionally start with “0x” or “0X” and contains only the digits 0-9 and letters A-F (or a-f).

In this tutorial, we will explore multiple approaches to check if a string is a valid hexadecimal number, providing clear examples and explanations for beginners.


Example 1: Using strtol Function

In this example, we will use the standard library function strtol to convert the string to a long integer with base 16 and check whether the conversion consumed the entire string, indicating a valid hexadecimal number.

Explanation:

</>
Copy
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int isValidHex(const char *str) {
    // Check for optional "0x" or "0X" prefix
    if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
        str += 2;
    }
    if (*str == '\0') return 0; // Empty string after prefix is invalid

    char *endptr;
    // Convert string to long with base 16
    strtol(str, &endptr, 16);

    // If endptr points to the end of the string, it is valid
    return (*endptr == '\0');
}

int main() {
    const char *hex1 = "0x1A3F";
    const char *hex2 = "1A3G";
    
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex1, isValidHex(hex1) ? "Yes" : "No");
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex2, isValidHex(hex2) ? "Yes" : "No");
    
    return 0;
}

Explanation:

  1. The function isValidHex checks if the string is a valid hexadecimal number.
  2. If the string starts with “0x” or “0X”, it skips these characters.
  3. strtol is used with base 16 to attempt conversion; endptr will point to the first invalid character.
  4. If *endptr equals the null terminator, the entire string is valid.
  5. In main, two test strings (hex1 and hex2) are evaluated and the results are printed.

Output:

Is "0x1A3F" a valid hexadecimal? Yes
Is "1A3G" a valid hexadecimal? No

Example 2: Manual Character Check

In this example, we manually iterate through each character of the string to verify that every character (after an optional “0x”/”0X” prefix) is a valid hexadecimal digit. This approach does not use any conversion functions.

Explanation:

</>
Copy
#include <stdio.h>
#include <ctype.h>

int isValidHexManual(const char *str) {
    // Skip optional "0x" or "0X" prefix
    if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
        str += 2;
    }
    if (*str == '\0') return 0; // No digits found

    // Iterate over each character
    while (*str) {
        // Check if character is a digit or a-f or A-F
        if (!(isdigit(*str) || (*str >= 'a' && *str <= 'f') || (*str >= 'A' && *str <= 'F'))) {
            return 0;
        }
        str++;
    }
    return 1;
}

int main() {
    const char *hex1 = "1a2b3c";
    const char *hex2 = "1a2b3z";
    
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex1, isValidHexManual(hex1) ? "Yes" : "No");
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex2, isValidHexManual(hex2) ? "Yes" : "No");
    
    return 0;
}

Explanation:

  1. The function isValidHexManual skips the optional prefix (“0x” or “0X”).
  2. It checks if the string is empty after the prefix; if so, it returns 0 (invalid).
  3. The loop iterates through each character, using isdigit to check for numeric digits.
  4. It also verifies that the character is within the ranges ‘a’–’f’ or ‘A’–’F’.
  5. If any character does not match these conditions, the function returns 0 (invalid); otherwise, it returns 1 (valid).
  6. The main function tests two strings (hex1 and hex2) and prints the result.

Output:

Is "1a2b3c" a valid hexadecimal? Yes
Is "1a2b3z" a valid hexadecimal? No

Example 3: Using sscanf for Validation

In this example, we use the sscanf function to scan the string for a hexadecimal value. We also use the %n format specifier to ensure the entire string is a valid hexadecimal number.

Explanation:

</>
Copy
#include <stdio.h>

int isValidHexSSCANF(const char *str) {
    int value;
    int numChars = 0;
    // Attempt to scan the string as a hexadecimal number
    if (sscanf(str, "%x%n", &value, &numChars) == 1) {
        // Check if the whole string was consumed
        return str[numChars] == '\0';
    }
    return 0;
}

int main() {
    const char *hex1 = "0XABC123";
    const char *hex2 = "XYZ123";
    
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex1, isValidHexSSCANF(hex1) ? "Yes" : "No");
    printf("Is \"%s\" a valid hexadecimal? %s\n", hex2, isValidHexSSCANF(hex2) ? "Yes" : "No");
    
    return 0;
}

Explanation:

  1. The function isValidHexSSCANF uses sscanf with the format specifier %x to read a hexadecimal number from the string.
  2. The %n specifier records the number of characters processed in numChars.
  3. If sscanf successfully reads one hexadecimal number (returning 1) and numChars equals the length of the string, the entire string is valid.
  4. If any extra characters remain, or the conversion fails, the function returns 0 (invalid).
  5. The main function tests two strings (hex1 and hex2) and outputs whether each string is a valid hexadecimal number.

Output:

Is "0XABC123" a valid hexadecimal? Yes
Is "XYZ123" a valid hexadecimal? No

Conclusion

In this tutorial, we demonstrated three different approaches to verify if a string is a valid hexadecimal number in C. Whether using strtol, manual character checking, or sscanf, each method has its own merits. Choose the approach that best fits your needs based on simplicity, performance, and your specific requirements.