-2

I'm currently doing the CS50 course, and I'm stuck on the credit problem. The idea is to make a program to verify cards due to their inbuilt checksum. The first step is to take every second digit and multiply it by 2, then add all the digits of the products together.

My code isn't finished, but I've set it up to print some intermediary steps just so I can see what's going on.

#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;
    }
  }
}

I know the first part is far from perfect but it's the checksum function I'm concerned with at the moment. When it takes the second digit(5) everything is fine. But then when it's multiplied by 2 according to the next line, somehow the result is 106(?)

Can someone explain what's going on here?

terminal output

dandan78
  • 13,328
  • 13
  • 64
  • 78
colossal
  • 11
  • 4
  • 1
    You are multiplying ascii characters (ie, text). Convert to a numeric value first. – kaylum Jun 08 '17 at 20:50
  • Possible duplicate of [How to convert a single char into an int](https://stackoverflow.com/questions/439573/how-to-convert-a-single-char-into-an-int) – kaylum Jun 08 '17 at 20:52
  • 1
    First, replace `char *card; scanf("%s", card);` with `char card[20]; scanf("%s", card);` – Stephan Lechner Jun 08 '17 at 20:54

2 Answers2

0

A couple of things:

  1. char *card; scanf("%s", card); is not going to work. You need to either declare card as an array of fixed size (i.e. char card[20]), or use malloc to allocate memory for the pointer char *card;. If you choose the latter option you also need to use free on the memory when you're done with it.
  2. In your function checksum, you need to convert the characters you read in the string card into numbers. If the character set on your system is ASCII, you can achieve this by subtracting the value 0x30 (i.e. the numeric value of the character '0') from each character in the string before performing arithmetic on it.
  3. char number[20] in a function signature is pointless; see this question for more information. Since the array decays to a pointer to its first element when passed as a function argument, you may as well have char *number in the function signature.
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
0

You read in a string, i.e. a sequence of characters, probably in ASCII format. So your input "1500150015001500" is actually a sequence of characters terminated by string terminating character 0x0, e.g. like { '1', '5', '0', .... '\0' }. A single character value like '1', when interpreted as an integral value, is represented by its ASCII code, which is 48 for '0', 49 for '1', ... , and 53 for '5'. Hence, an expression like char c = '5'; int digit = c*2 actually yields 106 for digit. To take character '5' as integral value 5, you could write int digit = (c - '0'), which is the same as if you wrote (53 - 48).

Without modifying your code to much, test what happens:

#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;
    }
  }
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58