Cenário
Tenho um bug estranho em que, quando adiciono uma variável aleatória ao código, ele altera a saída. Descobri o que estava causando o problema, mas não tenho certeza do porquê.
O código tem a intenção de validar números de cartão de crédito usando o Algoritmo de Luhns . Ele faz parte do curso edX CS50, no entanto, decidi experimentá-lo sem suas bibliotecas personalizadas em uma tentativa de aprender o máximo possível.
O problema que estou enfrentando é que, se eu executar o código abaixo como está, a resposta sai errada (ou seja, um '9' anexado à saída inteira). Agora, se eu descomentar ou int random_integer = 0;
, char random_character = 'M';
a saída funciona inteiramente como o esperado.
- Saída errada (deixando essas variáveis aleatórias comentadas):
209
- Saída correta (descomentar uma (ou ambas) dessas variáveis aleatórias):
20
Estranhamente, notei que se eu mudar char sum_to_str[3];
para char sum_to_str[10];
, o problema desaparece completamente.
Por favor, deixe-me saber o que você pensa, pois sou novato em C e estou interessado em entender as nuances.
Código
#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;
}
Eu tentei o seguinte:
- Comentando/descomentar e
int random_integer = 0;
depois recompilando - Adicionando
char random_character = 'M';
e alternando como um comentário e recompilando - Modificou o
char sum_to_str[3];
parachar sum_to_str[3];
Também tentei alterar a entrada (ou seja, example_card_num[]
) ligeiramente para determinar se havia algo gerando um "9" arbitrário ou se o número anexado mudou, o que aconteceu.
Você não deve usar atoi em uma variável char que não seja uma matriz de strings porque não há garantia de que ela seja terminada em nulo, então atoi produziria resultados imprevisíveis.
Seu problema é causado por comportamento indefinido devido ao uso inadequado da memória:
str_of_evens
→ Contém dados inúteis, o que faz comstrcat()
que se comporte de forma imprevisívelatoi()
um único caractere →atoi()
espera uma string terminada em nulo, mas você está passando um único caracteresum_to_str
→char sum_to_str[3];
é muito pequeno para armazenar números de dois dígitos com segurançaEstou anexando a versão corrigida: