将字符串转换为十六进制、十进制和八进制

converting string to hex, decimal, and octal

初学C,需要将一串字符转换为整数、十六进制、八进制。

我知道我可以使用 char *var_name 指向字符串的基数,但我不知道如何将字符串中的每个字符转换为十六进制、八进制或十进制。

例如:

"my name is Whosebug"

程序应将字符串的 ASCII 值转换为十六进制、八进制和十进制。

我尝试使用 atoi 但无法正常工作。

我也尝试过类型转换,但我也无法让它工作。我想到了sprintf但是不知道怎么用

用户应该能够输入任意长度的字符串,只有当有换行符时才应该结束。

我该怎么做?

int main(){
    char *string;
    printf("Enter string: ");
    scanf("%s", string);
    int d = (int) string;
    printf("%d\n",d);
    return 0;
}

输入:

Whosebug

输出:

-535030240

关于转换问题,不需要转换,字符串字符已经定义了编码,你只需要能够在不同的基础上正确打印它们,为此printf已经提供了您需要的说明符:

#include <string.h>

//...

for(size_t i = 0; i < strlen(string); i++){ //printing hex codes
    printf("%3x ", string[i]);
}
putchar('\n');
for(size_t i = 0; i < strlen(string); i++){ //printing decimal codes
    printf("%3d ", string[i]);
}
putchar('\n');
for(size_t i = 0; i < strlen(string); i++){ //printing octal codes
    printf("%3o ", string[i]);
}

关于你的代码,有一些问题:

scanf("%s", string);

string 是一个未初始化的指针,它没有为它保留任何内存,试图在其中存储任何东西会导致未定义的行为,你需要为它分配内存或以其他方式使它指向一个有效的、可写的内存位置。

例如:

char *string = calloc(2048, sizeof *string); //space for 2047 characters + null byte

此外,使用 %s 说明符的 scanf 将在找到 space 时停止读取,因此如果您输入 my name is Whosebug ,只有 my 会被解析。它也很不安全,因为它很容易溢出目标缓冲区,我的建议是您使用 fgets(前面提供了一个示例)。

之后当你使用:

 int d = (int) string;

在您的代码中,由于 string 未初始化,因此行为仍未定义。

如果你像上面的例子一样初始化它,会发生什么情况是你正在将 string 指向的内存地址转换为 int.

这仍然是一个问题,因为在今天的 64 位机器中,地址的大小通常为 8 个字节,而 int 通常为 4 个字节,因此您可能会在转换中丢失数据.

当你打印它时,你打印的是 string 指针指向的截断内存地址。

不用说,代码没有按照您的意愿执行,使用 atoi 或类似的东西也不起作用,因为这些函数在尝试解析 non-digit 他们失败了,但正如我所说,不需要转换。


至于不确定数量的字符的解析,我认为这是不必要的,而且开销太大,因为随着字符串的增长,你需要重新分配内存。给它一个大尺寸应该可以解决问题。

然而,如果你真的想那样做,你可以使用以下策略:

Online demo

#include <stdio.h>
#include <stdlib.h>

#define MIN_SIZE 50 //size above 50, memory will be reallocated

int main(){

    char *string = calloc(MIN_SIZE, sizeof *string);

    if(string == NULL){
        return EXIT_FAILURE;
    }

    int ind = 0; //string index

    if(string == NULL){
        return EXIT_FAILURE;
    }
    while((string[ind] = getchar()) != '\n'){ //parse till '\n'
        //removing '\n' or EOF
        if(string[ind] == EOF || string[ind] == '\n'){
            string[ind] = '[=14=]';
            break;
        }
        ind++;
        if(ind >= MIN_SIZE){ //if size is more than 50, reallocate
           string = realloc(string, ind + 1);
           if(string == NULL){
               return EXIT_FAILURE;
           }
        }
    }
    //...
}

在我将要使用的下面的示例中,我们有一个 2047 个字符串,它非常大并且只使用 2Kb 的内存,按照今天的标准,这是非常小的,这是字符串的限制大小, 上面的字符将不会被解析:

Online demo

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

#define SIZE 2048

//...

char *string = calloc(SIZE, sizeof *string); 

if(string == NULL){
    return EXIT_FAILURE;
}

fgets(string, SIZE, stdin); //parse with fgets
string[strcspn(string, "\n")] = '[=15=]'; //removing '\n'

示例输入:

my name is Whosebug

输出:

 6d  79  20  6e  61  6d  65  20  69  73  20  73  74  61  63  6b  6f  76  65 
109 121  32 110  97 109 101  32 105 115  32 115 116  97  99 107 111 118 101 
155 171  40 156 141 155 145  40 151 163  40 163 164 141 143 153 157 166 145