您的代码中有几个问题。 @MarkSolus 已经指出,您访问letters 越界,因为您使用i 作为索引,而i 在您执行memmove 时可以超过1。
在这个答案中,我将解决其他一些问题。
字符串大小和终止
C 中的字符串需要一个零终止符。因此,数组必须比您希望存储在数组中的字符串大 1。所以
char nums[4]; // Can only hold a 3 char string
char letters[2]; // Can only hold a 1 char string
您很可能希望将两个数组都增加 1。
此外,您的代码从不添加零终止符。所以你的字符串是无效的。
你需要这样的代码:
nums[some_index] = '\0'; // Add zero-termination
或者,您可以从将整个数组初始化为零开始。喜欢:
char nums[5] = {0};
char letters[3] = {0};
缺少边界检查
您的循环是使用strlen 作为停止条件的for 循环。现在如果我输入 "123456789BBBBBBBB" 会发生什么?好吧,循环将继续,i 将递增到值 ..., 5, 6, 7, ... 然后您将索引具有大于数组大小的值的数组,即越界访问(这真的很糟糕)。
您需要确保永远不会越界访问数组。
无格式检查
现在如果我输入一个没有任何数字的输入,例如“你好世界” ?在这种情况下,不会向nums 写入任何内容,因此在atoi(nums) 中使用时将不会对其进行初始化。再次 - 真的很糟糕。
此外,应该检查以确保非数字输入是 B、kB、mB 或 gB 之一。
性能
这并不重要,但是...使用memmove 复制单个字符很慢。直接赋值即可。
memmove(&nums[i], &input[i], 1); ---> nums[i] = input[i];
如何解决
修复代码的方法有很多种。下面是一个简单的解决方案。这不是最好的方法,但这样做是为了保持代码简单:
#define DIGIT_LEN 4
#define FORMAT_LEN 2
int bitLength(char *input)
{
char nums[DIGIT_LEN + 1] = {0}; // Max allowed number is 9999
char letters[FORMAT_LEN + 1] = {0}; // Allow at max two non-digit chars
if (input == NULL) exit(1); // error - illegal input
if (!isdigit(input[0])) exit(1); // error - input must start with a digit
// parse digits (at max 4 digits)
int i = 0;
while(i < DIGITS && isdigit(input[i]))
{
nums[i] = input[i];
++i;
}
// parse memory format, i.e. rest of strin must be of of B, kB, mB, gB
if ((strcmp(&input[i], "B") != 0) &&
(strcmp(&input[i], "kB") != 0) &&
(strcmp(&input[i], "mB") != 0) &&
(strcmp(&input[i], "gB") != 0))
{
// error - illegal input
exit(1);
}
strcpy(letters, &input[i]);
// Now nums and letter are ready for further processing
...
...
}
}