0

Okay, I admit I have no business doing the "hacker edition" problems, but I am having so much fun with this that I want to do ALL THE PROBLEMS!

Anyway. I'm working on pset1 hacker edition "credit."

In my "main" function, I start by calling "getLikeCC" to grab a long long unsigned variable that has 16 digits (excluding a number consisting of all 0s).

...I just realized that not all CC numbers have 16 digits. I didn't read that part carefully enough. That's okay! I'll rework that. It doesn't affect my question.

long long unsigned getLikeCC();
int checkCC();

int main(){
  unsigned long long ccInput = getLikeCC();

This works, and I double-checked the variable type with a printf statement:

printf("When the main function got ahold of ccInput, it now looked like this: %llu\n",ccInput);

And got

After running 'getLikeCC', the value of ccInput was 1234123412341234

(which is what I typed in).

So I now have a 16-digit number in a variable of type "long long unsigned".

Next, I pass ccInput to a second function, called checkCC:

  int result = checkCC(ccInput);

The goal of checkCC is to evaluate whether the number is invalid, Amex, Visa, or Mastercard. It returns either 0, 1, 2, or 3, and these results will be used by the main function to spit out the result.

CheckCC takes successively higher (by 10-fold) modulus of CC along with some subtraction to zero out the end values, and division to get the result to single digits, and stores each number of checkCC into an array of integers. This works just fine, as I have found by using test numbers and printing the results from within the sub-function.

However, when I pass ccInput to checkCC, the complier suddenly thinks that ccInput is an integer. Thus it evaluates it as some long crazy occasionally negative number, and when I used printf to debug, the compiler tells me it's an int, not an llu.

int checkCC(ccInput){

    printf("When we started running the checkCC program, ccInput looked more like this: %llu",ccInput);

Here's what the compiler thinks about that!:

credit.c:61:95: error: format specifies type 'unsigned long long' but the argument has type 'int' [-Werror,-Wformat]

My only kind of guess is that "getLongLong()" gets a signed rather than unsigned integer, and somehow that is throwing things off... I don't know the real relevance of signed vs unsigned, but I figured I'll never need a negative number and that making it signed would just introduce the potential for error, so I typed the variable as unsigned.

Thanks for any help you can offer!

UPDATE:

I decided to un-abstract that step, and move on with life for now.

In my very next step, though, I abstracted away the function that doubles alternating numbers and sums their digits...

And I'm having a similar problem; an undeclared argument type is treated as an integer (instead of taking the array I wanted it to take.)

So an update on my problem would be: how can I force an argument to take a variable as a desired type?

ADDENDUM: #########################################################

This is the version of the code that I was using when I submitted this question. Since then, I have removed all abstraction and made some modifications, and my final code passes all the "check" tests. However, my question remains: what would it take to properly pass a long long as an argument to a function?

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

long long unsigned getLikeCC();
int checkCC();

int main(){
  unsigned long long ccInput = getLikeCC();
  //continues prompting for CC number until user inputs 16-digit number with no dashes that isn't all zeroes.
  //if the user won't cooperate, returns 100000000000 instead.
  printf("When the main function got ahold of ccInput, it now looked like this: %llu\n",ccInput); //throws error: format specifies type "unsigned long long" but the argument has type "int"

  if (ccInput > 100000000000){
      printf("Just to be thorough, in the main function within the \'if\' condition, ccInput looked like this: %llu\n",ccInput);
    int result = checkCC(ccInput);
    //the spec says to put only AMEX, INVALID, etc on the last line of output, which made me think if I started a new line, it would satisfy the spec. Obviously when I ran the check I found out I was wrong, and modified these.
    if(result == 0){printf("It looks like you made a mistake, or else you are trying to enter a fake number.\nINVALID\n");}
    if(result == 1){printf("Purchasing various products on Amazon.com using your American Express number %llu.\nAMEX\n",ccInput);}
    if(result == 2){printf("Purchasing various products on Amazon.com using your Mastercard number %llu.\nMASTERCARD\n",ccInput);}
    if(result == 3){printf("Purchasing various products on Amazon.com using your Visa number %llu.\nVISA\n",ccInput);}
   // printf("%llu\n",ccInput);
  }
  else {printf("That's not even the right number of digits. Either you don't have a credit card, or you shouldn't be trusted with one.\nINVALID\n");}
return 0;

}

long long unsigned getLikeCC(){
   int i = 0;
    printf("Enter your credit card number.\n...I prooooomise nothing bad will happen.\n\n\n...no, really!\nTrust us! Type it in riiiight here-->");

    long long unsigned ccInput = GetLongLong();
    while (ccInput < 1000000000000000 || ccInput > 9999999999999999){
        if(i < 10){
            if (i>4 && i<7){printf("\nAre you sure you're looking at the rectangle plastic thing? Perhaps you should ask someone to help you.\n");}
            if (i > 6){printf("\nMaybe this will help... try copying this URL into your browser. It's totally not a virus.\nhttp://us.123rf.com/450wm/tombaky/tombaky0903/tombaky090300287/4577555-credit-card-with-black-arrow-computer-cursor.jpg\n");}
        printf("Not to be rude... but that's actually not a credit card number. Would you mind trying again, please: ");
        ccInput = GetLongLong();
        i++;
        }
        else {return 100000000000;}
    }
    printf("After running \'getLikeCC\', the value of ccInput was %llu.\n",ccInput);
    return ccInput;

}

int checkCC(ccInput){
//if I enter a test cc into this sub-function, the output returns to the main function and everything works. But when I pass in ccInput, it fails. 
//after some bug-checking using printf, I realized that ccInput is converted
//to an integer when being passed to this function.

    //by taking successivly larger (by 10x) modulus of the credit card number and dividing,
    //we get digits of credit card number one at a time and store them in a new array of integers.
    printf("When we started running the checkCC program, ccInput looked more like this: %llu",ccInput);
    //long long unsigned testNumber = 4444555533332222;
    long long unsigned subtractThis = 0;
    long long unsigned bigNumber = ccInput;
   // printf("But SOMEHOW, after taking bigNumber = ccInput, even though ccInput is %llu, BigNumber is %llu!\n",ccInput, bigNumber);
    int arrayCC[16];
   printf("\n");
   long long unsigned j = 1;
    for(int i=0; i<16; i++){
    long long unsigned k = j * 10;
    int arraySpot = 15 - i;

    printf("j = %llu. Big Number: %llu; subtractThis: %llu.",j, bigNumber, subtractThis);
    bigNumber = bigNumber - subtractThis;
    printf(" Big Number minus SubtractThis: %llu.,", bigNumber);
    subtractThis = bigNumber % k;
    printf(" Result modulo %llu: %llu.",k, subtractThis);
    arrayCC[arraySpot] = subtractThis / j;
    printf(" So we take subtractThis divided by %llu to get the value we store in the array, %i.\n", j, arrayCC[arraySpot]);
    j *= 10;
    //printf("%llu, %llu, %i\n",bigNumber, subtractThis,arrayCC[arraySpot]);
    }

    printf("\n");

    return 0;
}
  • I think this SO is relevant, but I'm still puzzling it together... it looks like I will have to find out how to tell it to call the function specifically treating the argument as a long long unsigned, but just calling checkCC(long long unsigned ccInput) isn't the way to do it... but that's the first thing I tried, so I don't expect it to work. stackoverflow.com/questions/1314060/… – Dr.Queso Feb 11 '16 at 20:51
  • please tell me I do not have to do something crazy like "pass the value in 2 adjacent registers, the first being an even number..." because that is far, far beyond me. stackoverflow.com/questions/15609622/… – Dr.Queso Feb 11 '16 at 21:01
  • Neither of the two functions you wrote in the code snippet above take any arguments. This is what you typed: long long unsigned getLikeCC(); int checkCC(); This means that you can't call the function as "int checkCC(ccInput);" The error you're posting makes me thing you might have written something wrong here. Please write the functions exactly as they are. Same goes if you want to pass an array. Post the code from what you tried, and the exact issue. GetLongLong() does return a long long which, by default, is signed. – Irene Feb 12 '16 at 4:21
  • Thanks for the response! Soon I will return and post the whole (now working and correct) un-abstracted code, as well as the abstracted but not working version. It may be a day or two, as I am on a busy overnight shift right now! In the meantime, you mention that my prototype function calls can't pass arguments. I do want to say that prototyping "int checkCC() and then calling int checkCC(ccInput) seemed to work fine, such that checkCC performed operations on ccInput and returned an integer. This may be due to scoping? I tried prototyping as in checkCC(long long); and it got mad. – Dr.Queso Feb 12 '16 at 10:05
  • ...but I'll try checkCC(ccInput) next... – Dr.Queso Feb 12 '16 at 10:06
1

You ask: "However, my question remains: what would it take to properly pass a long long as an argument to a function?"

Pass the argument to the funcion. Pass it with the correct type. Your function doesn't have a type in the prototype and it doesn't have it in the definition. The prototype is this:

int checkCC();

That's an empty argument list. In C, because it's such an old languages, you can get away with putting and empty prototype and then adding arguments in the definition. You wouldn't be able to do that in c++, for example.

Then, the definition is:

int checkCC(ccInput){// code here }

Again, you're not telling what type the argument is. "ccInput" is nothing, just a placeholder for a variable that doesn't have a type. If you don't put a type for the argument, the compiler will make a guess, and the guess is int. That's why you get the compiler error. Declare and define your function including the argument with the type. :)

| improve this answer | |
  • Thanks for pointing me in the right direction. It did occur to me to declare the argument type in the prototype, but when I did so, I was also declaring it in the function call, and since it wasn't working, I decided that wasn't the problem after all... especially since other parts were working without declaring. Now it's clear: DO declare argument types in the prototype and in the definition; DO NOT declare them in the function call. Thanks again. – Dr.Queso Feb 15 '16 at 7:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .