混淆字符串交互

Confusing Character String Interaction

我目前正在学习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%c\n", number[i]);
    digits = (number[i] * 2);
    printf("D%i\n", digits);
    while (digits > 0) {
      check += digits % 10;
      printf("C%i\n", check);
      digits = digits / 10;
    }
  }
}

我知道第一部分远非完美,但我目前关心的是校验和函数。当它需要第二个数字(5)时,一切都很好。但是当它根据下一行乘以 2 时,不知何故结果是 106(?)

谁能解释一下这是怎么回事?

terminal output

几件事:

  1. char *card; scanf("%s", card); 是行不通的。您需要将 card 声明为固定大小的数组(即 char card[20]),或者使用 malloc 为指针 char *card; 分配内存。如果您选择后一个选项,您还需要在完成后对内存使用 free
  2. 在你的函数checksum中,你需要将你在字符串card中读取的个字符转换成个数字.如果您系统上的字符集是 ASCII,您可以通过在对字符串执行算术运算之前从字符串中的每个字符中减去值 0x30(即字符 '0' 的数值)来实现。
  3. 函数签名中的
  4. char number[20] 毫无意义;有关详细信息,请参阅 this question。由于数组在作为函数参数传递时会衰减为指向其第一个元素的指针,因此您也可以在函数签名中包含 char *number

你读入了一个字符串,即一个字符序列,可能是 ASCII 格式。所以你的输入 "1500150015001500" 实际上是由字符串终止字符 0x0 终止的字符序列,例如喜欢 { '1', '5', '0', .... '[=12=]' }。像 '1' 这样的单个字符值,当解释为整数值时,由其 ASCII 码表示,对于 '0' 为 48,对于 '1' 为 49,...,对于 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%c\n", number[i]);
    digits = ((number[i]-'0') * 2);
    printf("D%i\n", digits);
    while (digits > 0) {
      check += digits % 10;
      printf("C%i\n", check);
      digits = digits / 10;
    }
  }
}