2

I'm trying to do the credit card exercise for cs50. Why is it that when I store the credit card number as a variable called 'number' and then immediately print that variable, a random number is printed and not my entered credit card number?

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    long number = get_long("Number: ");
    printf("%lo\n",number);
}

I am prompted to enter the number and put in 1234567890123

Number: 1234567890123

But the number below is what comes out

21756176602313
natalie889
  • 29
  • 2
  • 4
    `o` means octal (base 8). – interjay Jul 12 '22 at 13:30
  • 1
    If you've got a credit card number, it should not be stored as a number. You should have it as a string. Even though all the characters are digits, it's not really a "number". If you're not going to perform arithmetic operations on it, then store it as a string. This applies to other all-digit "numbers" like phone numbers, ZIP codes, etc. – Andy Lester Jul 12 '22 at 22:07

2 Answers2

3

The format specifier outputs in octal format:

printf("%lo\n",number);//%lo = unsigned long integer printed in octal digits.
         ^^

for base 10 it should be:

printf("%ld\n",number);//"%li" is also valid.
         ^^
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • You can use `%li` too. – Zakk Jul 12 '22 at 13:33
  • @natalie889 [1234 is correctly printed as 1234](https://godbolt.org/z/zTGKj3j14) - unless you have a bug in some part of the program that you haven't shown. – Ted Lyngmo Jul 12 '22 at 13:38
  • 2
    @ryyker Yes. It's not valid on its own – Ted Lyngmo Jul 12 '22 at 13:40
  • That result of inputting 1234 and getting 2322 was the same when using long and %li or long long and %lli, seems like this must be something wrong with my set up – natalie889 Jul 12 '22 at 13:41
  • 1
    @natalie889 2322 is base 8 for 1234, you obviously didn't change the `%lo`. – interjay Jul 12 '22 at 13:42
  • 2
    @ryyker The C standard specifies that a conversion specification (starting with `%`) must include a conversion specifier. `%l` doesn't include one. – interjay Jul 12 '22 at 13:45
  • 1
    @ryyker C18 (C23 draft) "7.21.6.1 The fprintf function" _"`l` (ell) Specifies that a following d, i, o, u, x, or X conversion specifier applies to a long int or unsigned long int argument; that a following n conversion specifier applies to a pointer to a long int argument; that a following c conversion specifier applies to a wint_t argument; that a following s conversion specifier applies to a pointer to a wchar_t argument; or has no effect on a following a, A, e, E, f, F, g, or G conversion specifier"_ - Nothing says the conversion specifier `l` can be used without that following char. – Ted Lyngmo Jul 12 '22 at 13:49
  • [n2310](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf) – Ted Lyngmo Jul 12 '22 at 13:50
  • Typo: I said _"Nothing says the conversion specifier..."_ - I meant _"length specifier_". And [the C99 standard](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) doesn't mention the length specifier `%l` being valid without a conversion specifier either. If your compiler accepts it, it's an extension. – Ted Lyngmo Jul 12 '22 at 14:00
  • Note that the three sources you list all have the same exact list in the same order. They must all have copied it from each other. They also all say that `%n` "prints nothing" but neglect to say that it writes into an output parameter. – interjay Jul 12 '22 at 14:12
  • 2
    @TedLyngmo: Re “If your compiler accepts it, it's an extension”: If the compiler documents that it accepts it, it is an extension. If the compiler accepts it but does not document it, it is just garbage. – Eric Postpischil Jul 12 '22 at 14:13
3

The correct format specifier to print long in decimal (base 10) is %ld or %li.

Zakk
  • 1,935
  • 1
  • 6
  • 17