八进制和六进制的stringTOint转换

时间:2018-11-28 11:10:13

标签: c arrays string hex octal

我实现了一种将给定字符数组转换为十进制整数的方法。该方法将从数组中取出每个字符,计算其十进制值,然后将其乘以10 ^ n,其中n在每次迭代时都会递增。

  

因此,例如数组4711将像这样转换。   1 * 10 ^ 0 + 1 * 10 ^ 1 + 7 * 10 ^ 2 + 4 * 10 ^ 3 = 4711作为十进制值。

我现在的问题是如何扩展功能,以便stringTOint方法还能够处理八进制和六进制值,例如023或0x1A。

/** Converts the given array of characters into a decimal integer */
int stringTOint(char str[]) {
int i, flag, offset, n,base;
flag = 0;
base = 10;
char c = '0';
/*if the first char in the array is '-', the minus flag gets set */
if (str[0] == '-') {
    flag = -1;
}
if (flag == -1) {
    offset = 1;
} else {
    offset = 0;
}
if(offset == 0) {
    if (str[0] == '0' && (str[1] != 'x' && str[1] != 'X') ) {
        base = 8;  // Octal
    } else if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
        base = 16; // Hexadecimal
        offset = offset + 2;
    }
}else if(offset == 1) {
    if (str[1] == '0' && (str[2] != 'x' && str[2] != 'X') ) {
        base = 8;  // Octal
    } else if (str[1] == '0' && (str[2] == 'x' || str[2] == 'X')) {
        base = 16; // Hexadecimal
        offset = offset + 2;
    }
}
n = 0;
/*Loop runs until terminating NULL gets found in array */
for (i = offset; str[i] != '\0'; i++) {
    n = n * base + str[i] - c;
}
/*value becomes negative if the negative flag was set */
if (flag == -1) {
    n = -n;
}
/* n gets returned */
return n;
}

3 个答案:

答案 0 :(得分:0)

您不处理十六进制值从AF的情况。

   for (i = offset; str[i] != '\0'; i++) {
       int value = (str[i] > ='A' && stri[i]<='F')? (str[i]-'A'+10):(str[i]-'0');
       n = n * base + value;
    }

也就是说,如果char是AF,只需从A中减去char并加上10就可以得到十六进制表示形式。

注意:您需要使用%X%x以十六进制表示法打印。

答案 1 :(得分:0)

另一种方法是使用有效数字数组。使用strchr检查数字是否有效。如果有效,则指针之间的差就是无需减去字符常量即可添加的值。

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

int stringTOint(char *str, int *number) {
    char *digits = "0123456789";//pointer to string literal
    char *valid = NULL;
    char add = 0;
    int sign = 1;
    int base = 10;

    *number = 0;
    while ( ' ' == *str || '\t' == *str) {
        str++;//skip leading spaces tabs
    }
    if ( '-' == *str || '+' == *str) {
        if ( '-' == *str) {
            sign = -1;
        }
        str++;
    }
    if ( '0' == *str) {
        digits = "01234567";//assign pointer to different string literal
        base = 8;
        str++;
        if ( 'x' == *str) {//lowercase
            digits = "0123456789abcdef";
            base = 16;
            str++;
        }
        if ( 'X' == *str && '0' == *(str - 1)) {//uppercase
            digits = "0123456789ABCDEF";
            base = 16;
            str++;
        }
    }
    while (*str) {//not at terminating zero
        if ( ( valid = strchr ( digits, *str))) {//is a valid digit
            add = valid - digits;//value to add is difference between pointers
            *number = *number * base + add;
            str++;
        }
        else {
            *number = 0;
            return 0;//not a valid digit
        }
    }

    *number = *number * sign;
    return 1;
}

int main ( void) {
    char text[100] = "";
    int value = 0;

    do {
        printf ( "enter an integer\n\t(leading 0 octal or leading 0x hexal)\n\tor enter done\n");
        if ( fgets ( text, sizeof text, stdin)) {
            if ( '\n' == text[0]) {
                break;//exit on empty line
            }
            text[strcspn ( text, "\n")] = 0;//remove newline
            if ( stringTOint ( text, &value)) {
                printf ( "decimal value = %d\n", value);
            }
            else {
                printf ( "\n\tinput problem [%s]\n\n", text);
            }
        }
        else {
            fprintf ( stderr, "fgets EOF\n");
            return 0;
        }
    } while ( strcmp ( text, "done"));//exit if input is done
    return 0;
}

添加

    if ( 'b' == *str) {
        digits = "01";//assign pointer to different string literal
        base = 2;
        str++;
    }

之前

    while (*str) {//not at terminating zero

,可以使用诸如b1101

之类的输入来处理二进制值

要在十六进制值中混合使用大写和小写,请删除整个if的大写字母,包括ctype.h并更改

if ( 'x' == *str) {

if ( 'x' == *str || 'X' == *str) {

并更改

if ( ( valid = strchr ( digits, *str))) {

if ( ( valid = strchr ( digits, tolower ( *str)))) {

答案 2 :(得分:-1)

我的想法是检查数组中的当前char是否为十进制(因此为0-9),或者是否为字母(因此为AF),然后将-'0'更改为-'A',然后如果是字母,则为十进制数字。

for (i = offset; str[i] != '\0'; i++) {
    if(str[i]==/*ABCDEF*/) {
     c = 'A';
} else if( str[i]==/*0123456789*/) {
        c = '0';
    }
    n = n * base + str[i] - c;
}

但是我不确定如何检查当前字符,因为它只需要是其中的一个,并且应该有一个更好的方法来执行9 if语句并将其与逻辑或组合。