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

标签 c character-encoding type-conversion

我是 C 语言新手,需要将字符串转换为整数、十六进制、八进制。

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

例如:

"my name is stackoverflow"

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

我尝试使用atoi但我无法让它工作。

我也尝试过类型转换,但也无法使其工作。我想到了sprintf但不明白如何使用它。

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

我该怎么做?

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

输入:

stackoverflow

输出:

-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 将在找到空格时停止读取,因此如果您输入我的名字是 stackoverflow ,只有 my 会被解析。它也非常不安全,因为它很容易溢出目标缓冲区,我的建议是您使用 fgets (前面提供了一个示例)。

之后当您使用时:

 int d = (int) string;

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

如果像上面的示例一样对其进行初始化,则会将 string 指向的内存地址转换为 int

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

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

不用说,代码不会做你想要它做的事情,并且使用 atoi 或类似的东西也不起作用,因为这些函数在尝试解析一个数字时仅转换数字非数字它们会失败,但正如我所说,不需要转换。


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

但是,如果您确实想这样做,您可以使用以下策略:

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] = '\0';
            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")] = '\0'; //removing '\n'

示例输入:

my name is stackoverflow

输出:

 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

关于将字符串转换为十六进制、十进制和八进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64115228/

相关文章:

c - GTK3 API : Replacement for deprecated gtk_text_freeze API?

c - c 中的奇怪结果

c - 向 printf() 添加换行符会更改代码行为

windows - Emacs 在进程缓冲区中显示 ^M

javascript - 在javascript中检测浏览器字符支持?

javascript - 将 html 文件重命名为 php 时编码错误

c++ - 对象切片和隐式类型转换

java - java中无法识别uint8_t的字符串转换

java - Struts2 xwork 类型转换与 hibernate

命令行参数计数