-1

I'm working on an assignment for my programming I class. I'm brand new to C++. What we're trying to do is take year, month, and day arguments provided by the user at the time of execution and calculate the difference between them and the current date.

In my main function, I have the following code to grab those arguments from the user:

int main(int argc, char** argv)

My understanding is that this creates a character array and stores the user's arguments in it. Next, I am assigning the arguments stored in this array to new char variables so that I can pass them to a function, like so:

int main(int argc, char** argv)
{
    int year, month, day;
    char arg1 = argv[1];
    string arg2 = argv[2];
    char arg3 = argv[3];

    argumentChange(argc, arg1, arg2, arg3, year, month, day);

blablabla other code
}

Where argumentChange is the function I'm sending them to. The issue is when I try to compile this, I receive the following errors:

Error: invalid conversion from 'char*' to 'char' [-fpermissive]

charArg1 = argv[1];

Error: invalid conversion from 'char*' to 'char' [-fpermissive]

charArg3 = argv[3];

I've tried searching this issue, and I can't really make heads or tails of the explanations given elsewhere. I've seen a lot of people mention "pointers", which we haven't yet covered in class and which I know nothing about. What have I done wrong? How do I make this work?

Here is the complete code for my entire program:

#include <iostream>
#include <ctime>
#include <string>

using namespace std;

void argumentChange(int numArg, char chArg1, string sArg2, char chArg3, int year, int month, int day)
{
    cout << "Starting birth date: " << chArg1 << " " << sArg2 << " " << chArg3
         << endl;
    if (numArg < 4 || numArg > 4)
    {
        cout << "Correct Usage: ./cl <birth_year><birth_month><birth_day>" << endl;
        cout << "Try again, dude." << endl;
    }
    else if (numArg == 4)
    {
        year = chArg1 - '0';
        day = chArg3 - '0';
        if ((sArg2 == "january") || (sArg2 == "January"))
        {
        month = 0;
        }
        else if ((sArg2 == "february") || (sArg2 == "February"))
        {
            month = 1;
        }
        else if ((sArg2 == "march") || (sArg2 == "March"))
        {
            month = 2;
        }
        else if ((sArg2 == "april") || (sArg2 == "April"))
        {
            month = 3;
        }
        else if ((sArg2 == "may") || (sArg2 == "May"))
        {
            month = 4;
        }
        else if ((sArg2 == "june") || (sArg2 == "June"))
        {
            month = 5;
        }
        else if ((sArg2 == "july") || (sArg2 == "July"))
        {
            month = 6;
        }
        else if ((sArg2 == "august") || (sArg2 == "August"))
        {
            month = 7;
        }
        else if ((sArg2 == "september") || (sArg2 == "September"))
        {
            month = 8;
        }
        else if ((sArg2 == "october") || (sArg2 == "October"))
        {
            month = 9;
        }
        else if ((sArg2 == "november") || (sArg2 == "November"))
        {
            month = 10;
        }
        else if ((sArg2 == "december") || (sArg2 == "December"))
        {
            month = 11;
        }
        else
        {
                cout << "Error: You have entered an invalid term for month.  Please type ";
                cout << "the complete name of a valid month." << endl;
        }
    }
}

struct tm bday(int year, int month, int day)
    {
        struct tm r {0};
    
        r.tm_year = year - 1900;
        r.tm_mon = month;
        r.tm_mday = day;
    
        return r;
    }

int main(int argc, char** argv)
{
    int year, month, day;
    char arg1 = argv[1];
    string arg2 = argv[2];
    char arg3 = argv[3];

    argumentChange(argc, arg1, arg2, arg3, year, month, day);

    struct tm a = bday(year, month, day);
    time_t x = mktime(&a);
    time_t y = time(0);
    if ( x != (time_t)(-1) && y != (time_t)(-1) )
    {
        double difference = difftime(y, x) / (60 * 60 * 24);
        cout << ctime(&x);
        cout << ctime(&y);
        cout << "difference = " << difference << " days" << endl;
    }
    return 0;
}
Community
  • 1
  • 1
  • You have misunderstood `argv`: `argv[1]` is not a single `char`, it's a `char*`, and `argv` is a `char**`. If it helps you understand, you can also declare `argv` as `char* argv[]` – Tas Mar 16 '18 at 03:23
  • FWIW, you should always endeavour to have a [mcve] in your question. The first snippet of code is all you really need to reproduce the problem, so you can probably get rid of the full thing. – Tas Mar 16 '18 at 03:27
  • Thanks for the tips. What exactly are `char*` and `char**` and how are they different from `char`? – KingKenny04 Mar 16 '18 at 03:28
  • 1
    `*` means pointer. `char*` is a pointer to a `char`. `char**` is a pointer to another pointer (a `char*`). Has your class not explained this? You may wish to look at our [C++ Book Guide](https://stackoverflow.com/q/388242/103167) if you aren't learning the necessary concepts in lecture. – Ben Voigt Mar 16 '18 at 03:31
  • 1
    Oh I see, your professor is one of those who has confused "teach C++ style, not C style" with "use it before you teach it". Unfortunate. Getting a good book is probably the best way to combat that. – Ben Voigt Mar 16 '18 at 03:34
  • Although equivalent, you may want to replace the argument `char** argv` to `char* argv[]`. I think you are stuck on the char** but the later can be easier to visualize as a pointer to a char array. – Eat at Joes Mar 16 '18 at 03:34
  • And you want `char* arg1 = argv[1]` you get the idea. Also, you should guard against indexing into out of bounds arguments by using `argc`. – Eat at Joes Mar 16 '18 at 03:36
  • 1
    Also, naming your program `cl` is a very bad idea, if only because it's the command for a very popular C++ compiler. – Ben Voigt Mar 16 '18 at 03:36

2 Answers2

1

As pointed out, the type of argv[x] is a char*, which is a pointer to an array of chars. So char** is a pointer to an array of arrays. (Really * doesn't automatically mean it's a pointer to an array, it just does in this case)

//  argv is an array of char*'s
int main(int argc, char** argv)

// firstParam is an array of char's 
char* firstParam = argv[1];

// firstLetter is the first char of the array
char firstLetter = firstParam[0]

Really, you should skip all the char arrays and just use std::string's. eg

int main(int argc, char** argv) {
    std::string param = argv[1];

    if (param == "january") {
        // Something ...
    }

}

You should also really check how many arguments are being passed in, so you don't access outside the range of the array. That's what argc is for.

dempzorz
  • 1,019
  • 13
  • 28
0

When storing an bunch of variables in type T, we may have a dynamic array to store it. Usually we use the pointer to the array, its type will be T*

For int as example:

int* ary1 = new int[3];
ary1[0] = 10; // ary1 + 0 store 10, a int
ary1[1] = 11; // ary1 + 1 store 11, a int 
ary1[2] = 12; // ary1 + 2 store i2, a int

Same as char* string

char** argv= new char*[4];
argv[0] = "cl.exe" // ary2 + 0 stores "cl.exe", a `char*` string
argv[1] = "2018""  // ary2 + 1 stores "2018"  , a `char*` string
argv[2] = "3"      // ary2 + 2 stores "3"     , a `char*` string
argv[3] = "16"     // ary2 + 3 stores "16"    , a `char*` string

So this is why you cannot assign the argv[1], (a char* string), to arg1, (a char character).

Chen OT
  • 3,486
  • 2
  • 24
  • 46
  • Don't introduce things without fully explaining them. That's what got OP into this mess in the first place. – Ben Voigt Mar 16 '18 at 04:06