设想
我遇到了一个奇怪的错误,当我向代码中添加一个随机变量时,它会改变输出。我弄清楚了导致问题的原因,但我并不完全确定它为什么会导致问题。
该代码旨在使用Luhns 算法验证信用卡号。它是 edX CS50 课程的一部分,但我决定尝试不使用他们定制的库,以便尽可能多地学习。
我遇到的问题是,如果我按原样运行下面的代码,那么答案就会出错(即在整数输出后附加“9”)。现在,如果我取消注释int random_integer = 0;
或 char random_character = 'M';
,则输出将完全按预期工作。
- 错误的输出(留下那些随机变量的注释):
209
- 正确的输出(取消注释其中一个(或两个)随机变量):
20
奇怪的是,我注意到如果我改为char sum_to_str[3];
,char sum_to_str[10];
问题就完全消失了。
请让我知道您的想法,因为我对 C 还不太熟悉,并且有兴趣了解其中的细微差别。
代码
#include <stdio.h> // For Standard Input/Output
#include <stdlib.h> // For the atoi() function
#include <string.h> // For the strchr() and strlen() functions
// This value is the length plus one
#define MAX_INPUT_LENGTH 255
int main(void) {
char user_input[MAX_INPUT_LENGTH];
char *p;
// Output CLI instructions
printf("Welcome to the Credit Card Validator!!\n");
printf("INSTRUCTIONS: At the prompt, please provide a CC number.\n");
printf("NOTES ON LENGTH: Visa -> 13 || 16, AmEx -> 15 and MC -> 16\n");
// Algorithm
char example_card_num[] = "4003600000000014";
// Check the length
int card_num_length = strlen(example_card_num);
int skip_flag = 0;
int sum_of_values = 0;
char value_at_index;
char str_of_evens[20];
for (int i = card_num_length - 1; i >= 0; i--) {
char sum_to_str[3];
switch (skip_flag) {
case 0:
// Add 'odd' values together
value_at_index = example_card_num[i];
sum_of_values = sum_of_values + atoi(&value_at_index);
// Toggle flag
skip_flag = 1;
break;
case 1:
// Add 'even' values together (with multiplier)
value_at_index = example_card_num[i];
// 1. Convert each str to int
// 2. Multiply by two
// 3. Convert back to str in new variable
sprintf(sum_to_str, "%d", (atoi(&value_at_index) *2));
// Concatenate each substring to a new string
strcat(str_of_evens, sum_to_str);
// Toggle flag
skip_flag = 0;
break;
}
}
// int random_integer = 0;
// char random_character = 'M';
char value_at_index_two;
for (int i = 0; i < strlen(str_of_evens); i++) {
value_at_index_two = str_of_evens[i];
sum_of_values = sum_of_values + atoi(&value_at_index_two);
}
printf("~~~~~~~~~~~\n");
printf("Sum of Values 01: %d\n", sum_of_values);
// Terminate the program
return 0;
}
我尝试了以下操作:
- 注释/取消注释
int random_integer = 0;
然后重新编译 - 添加
char random_character = 'M';
然后将其切换为注释并重新编译 - 修改
char sum_to_str[3];
为char sum_to_str[3];
我还尝试稍微改变输入(即example_card_num[]
),以确定是否有东西抛出了任意的“9”或附加的数字是否发生了变化,事实确实如此。
您不应该在非字符串数组 char 变量上使用 atoi,因为无法保证它以空值终止,因此 atoi 会产生不可预测的结果。
您的问题是由于内存使用不当导致的未定义行为引起的:
str_of_evens
→ 它包含垃圾数据,导致strcat()
行为不可预测atoi()
单个字符 →atoi()
期望以空字符结尾的字符串,但您传递的是一个字符sum_to_str
→中的缓冲区溢出char sum_to_str[3];
太小,无法安全存储两位数我附上了修正后的版本: