我是 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
或类似的东西也不起作用,因为这些函数在尝试解析一个数字时仅转换数字非数字它们会失败,但正如我所说,不需要转换。
对于不确定数量的字符的解析,我认为这是不必要的,而且开销太大,因为随着字符串的增长,你需要重新分配内存。给它一个大的尺寸应该可以解决问题。
但是,如果您确实想这样做,您可以使用以下策略:
#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 的内存,按照今天的标准来看,这是非常小的,这是字符串的限制大小,上面字符将不会被解析:
#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/