我目前正在学习CS50课程,但我被困在学分问题上。这个想法是制作一个程序来验证卡,因为它们内置了校验和。第一步是取每两位数字并将其乘以 2,然后将产品的所有数字相加。
我的代码尚未完成,但我已经将其设置为打印一些中间步骤,以便我可以看到发生了什么。
#include <stdio.h>
#include <string.h>
void checksum (char number[20]);
int main (void){
char *card;
printf("Please enter a card number:");
scanf("%s", card);
if (strlen(card) == 13 || strlen(card) == 16 || strlen(card) == 15) {
checksum(card);
}
else{
printf("Not a number. Please try again.n");
main();
}
}
void checksum (char *number) {
int check = 0;
int digits = 0;
for(int i = 1; i < 17; i += 2){
printf("No%cn", number[i]);
digits = (number[i] * 2);
printf("D%in", digits);
while (digits > 0) {
check += digits % 10;
printf("C%in", check);
digits = digits / 10;
}
}
}
我知道第一部分远非完美,但这是我目前关心的校验和函数。当它需要第二个数字(5(时,一切都很好。但是当它根据下一行乘以 2 时,不知何故结果是 106(?
有人可以解释一下这里发生了什么吗?
端子输出
你读一个字符串,即一个字符序列,可能是 ASCII 格式。因此,您的输入"1500150015001500"
实际上是由字符串终止字符0x0终止的字符序列,例如 { '1', '5', '0', .... ' ' }
.像 '1'
这样的单个字符值,当解释为整数值时,由其 ASCII 码表示,该码为 48 表示'0'
,49 表示 '1'
、... 和 53 表示'5'
。因此,像 char c = '5'; int digit = c*2
这样的表达式实际上为 digit
产生 106 个。要把字符'5'
作为整数值5
,你可以写int digit = (c - '0')
,这和你写(53 - 48)
一样。
在不修改代码的情况下,测试发生的情况:
#include <stdio.h>
#include <string.h>
void checksum (char *number);
int main (void){
char card[30];
printf("Please enter a card number:");
scanf("%s", card);
if (strlen(card) == 13 || strlen(card) == 16 || strlen(card) == 15) {
checksum(card);
}
else{
printf("Not a number. Please try again.n");
main();
}
}
void checksum (char *number) {
int check = 0;
int digits = 0;
for(int i = 1; i < strlen(number); i += 2){
printf("No%cn", number[i]);
digits = ((number[i]-'0') * 2);
printf("D%in", digits);
while (digits > 0) {
check += digits % 10;
printf("C%in", check);
digits = digits / 10;
}
}
}
有几件事:
-
char *card; scanf("%s", card);
是行不通的。您需要将card
声明为固定大小的数组(即char card[20]
(,或使用malloc
为指针分配内存char *card;
。 如果选择后一个选项,则还需要在完成内存后使用内存上的free
。 - 在你的函数
checksum
中,你需要将你在字符串card
中读取的字符转换为数字。如果系统上的字符集是 ASCII,则可以通过在对字符串执行算术之前从字符串中的每个字符中减去值0x30
(即字符'0'
的数值(来实现此目的。 - 函数签名中的
char number[20]
毫无意义;有关更多信息,请参阅此问题。由于数组在作为函数参数传递时衰减为指向其第一个元素的指针,因此您也可以在函数签名中char *number
。