我需要取一个只包含十六进制数字的字符串并将其转换为40的int数组,其中每个空格包含字符串中的一个数字,该数组需要向后填充,因此最低有效数字是第一个数字数组。
如果字符串不包含40个数字,则需要将适量的零填充到数组的末尾。
以下是我正在使用的代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
char *str = "0123456789aBcdef0123456";
printf("%s\n", str);
char *s = strdup(str);
int i = 0;
while (s[i]) {
if (s[i] >= 97 && s[i] <= 122)
s[i] -= 32;
i++;
}
int amount = 40 - i, under40 = 0, k = 39;
printf("%s\n amount:%d\n", s, amount);
int *digits = malloc(sizeof(int) * 40);
for (i = 0; i < 40; i++) {
if (amount > 0) {
digits[k] = 0;
under40 = 1;
amount--;
i--;
} else {
switch (s[i]) {
case 'A':
digits[k] = 10;
break;
case 'B':
digits[k] = 11;
break;
case 'C':
digits[k] = 12;
break;
case 'D':
digits[k] = 13;
break;
case 'E':
digits[k] = 14;
break;
case 'F':
digits[k] = 15;
break;
default:
digits[k] = s[i] - 48;
}
}
k--;
}
for (i = 0; i < 40; i++)
printf("%i ", digits[i]);
if (under40 == 1) {
fprintf(stderr, "\nUnder 40 digits passed\n");
}
return 0;
}
使用当前字符串,在main的第一行,程序崩溃,但任何字符串大于此,它很好,我真的不知道为什么。还有一些具有较短字符串的实例不会崩溃。
这真是令人困惑,因为我不知道为什么有些长度有效,有些长度。例如0123456789aBcdef0123456789869679866896AAAAdddd很好,01234很好。
答案 0 :(得分:1)
当字符串的长度小于40时,您的循环实际运行超过40次,因为i
只要amount
为正,就会递减。结果,k
变为负数,您最终会在digits
数组开始之前写入。在数组范围之外读取和写入会调用undefined behavior。
您的循环需要检查k
的值,以确保它仍为非负数:
for (i = 0; i < 40 && k >= 0; i++) {
更好的方法是在循环中递减k
并仅在需要时递增i
。
for (i = 0, k = 39; k >= 0; k--) {
if (amount > 0) {
digits[k] = 0;
under40 = 1;
amount--;
// don't decrement i here
} else {
switch (s[i]) {
...
}
i++; // increment here instead
}
// no need to decrement k here
}
此外,您可以将switch
简化为单个条件(假设ASCII编码,其中'A' - 'F'是顺序的):
digits[k] = (s[i] >= 10) ? s[i] - 'A' + 10 : s[i] - '0';