将字符串转换为十六进制、十进制和八进制
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 他们失败了,但正如我所说,不需要转换。
至于不确定数量的字符的解析,我认为这是不必要的,而且开销太大,因为随着字符串的增长,你需要重新分配内存。给它一个大尺寸应该可以解决问题。
然而,如果你真的想那样做,你可以使用以下策略:
#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 的内存,按照今天的标准,这是非常小的,这是字符串的限制大小, 上面的字符将不会被解析:
#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
初学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 他们失败了,但正如我所说,不需要转换。
至于不确定数量的字符的解析,我认为这是不必要的,而且开销太大,因为随着字符串的增长,你需要重新分配内存。给它一个大尺寸应该可以解决问题。
然而,如果你真的想那样做,你可以使用以下策略:
#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 的内存,按照今天的标准,这是非常小的,这是字符串的限制大小, 上面的字符将不会被解析:
#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