user2993456
user2993456

Reputation:

Converting *argv[] to int using atoi

I am trying to convert a char stored in the argv array to int, using the atoi function, I am new to C++ and passing arguments, so please bear with me.

Every time I attempt to set the value stored at atoi[1] to a const char, and print the char, it doesn't print anything at all. If I am doing this wrong it should still print a memory address, right?

I am setting it to a const char because the atoi function needs a const char as it's argument. (Please correct me if I am wrong)

I have been doing this via ideone.com, so my argv array isn't really set at runtime, since ideone doesn't allow that.

Here is my code so far:

#include <iostream>
#include<string>
#include <stdlib.h>
using namespace std;

int main() {
    int argc;
    char *argv[4]; 

    *argv[0] = 'x';
    *argv[1] = '5';//this will be the length of our first array for testing
    *argv[2] = '3';//this will be the length of our second array for testing
    *argv[3] = '4';//this will be the length of our third array for testing
    argc = 4;

    const char  * argv1 = argv[1];

    cout << "*argv[1]: " <<  *argv[1] << endl;
    cout << "argv[1]: " <<  argv[1] << endl;
    cout << *argv1;

    //int x = atoi(argv1);

    return 0;
}

UPDATED CODE: Now featuring the ability to compile!

#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

int main() {
    char nullGuy = NULL;
    char * nullptr1 = &nullGuy;//Null ptr

    int argc;
    const char * argv[5]; 

    argv[0] = "x";
    argv[1] = "5";
    argv[2] = "3";
    argv[3] = "4";
    argv[4] = nullptr1;

    argc = 4;

    int x = atoi(argv[1]);

    cout << "argv[1]: " <<  argv[1] << endl;
    cout << "x: " << x << endl;

    return 0;
}

Upvotes: 1

Views: 12926

Answers (3)

Crowman
Crowman

Reputation: 25908

None of your pointers point to valid memory. You're getting undefined behavior when you deference them. Even if this weren't true, you're not null-terminating them, so they're not strings.

Change to:

#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

int main() {
    int argc;
    const char * argv[5]; 

    argv[0] = "x";
    argv[1] = "5";
    argv[2] = "3";
    argv[3] = "4";
    argv[4] = nullptr;
    argc = 4;

    int x = atoi(argv[1]);

    cout << "argv[1]: " <<  argv[1] << endl;
    cout << "x: " << x << endl;

    return 0;
}

As explanation, this from your original code:

*argv[0] = 'x';

is the same as:

*(argv[0]) = 'x';

which is the same as:

argv[0][0] = 'x';

which means "take the address stored at argv[0], and store the value 'x' there". Since you never initialize argv[0], or any of your argv members, none of these addresses are valid, and they are highly unlikely to point to any memory that you're allowed to write to.

If you'd declared argv as, say, char argv[4][20];, then this would be OK, since argv[0] is no longer an uninitialized pointer, but an array of 20 characters which you can write to.

However, even if you did that, you'd want to do something like:

argv[1][0] = 'x';
argv[1][1] = '\0';

because the thing you pass to atoi() must be an actual (C-style) string, not a pointer to a single character, and strings must be terminated with the null character.

Instead, in the code I gave:

const char * argv[5];
argv[1] = "5";  //  <-- Note use of double, not single, quotes

does make argv[1] a pointer to char, but points it to the string literal "5", which is null-terminated, is a C-style string, and is suitable for passing to functions like atoi(). You will not be able to modify that string, however, so if you want to do that, you'll need to either declare an actual array, or dynamically allocate some memory with the new operator.

You can also change nullptr to NULL if, as the comment to another answer suggests, you're not using C++11. I added that fifth member of argv set to nullptr because when you do start using actual command lines rather than manually setting it up, the argv that gets passed to main() is going to have that member.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

The main ptoblem is that you did not allocate memory that would be pointed to by the elements of the array and where you are going to write characters.

The valid code could look the following way

#include <iostream>

int main() 
{
    const size_t N = 4;
    int argc;
    char *argv[N];

    argv[0] = new char( 'x' );
    argv[1] = new char( '5' );//this will be the length of our first array for testing
    argv[2] = new char( '3' );//this will be the length of our second array for testing
    argv[3] = new char( '4' );//this will be the length of our third array for testing
    argc = N;

    const char *argv1 = argv[1];

    std::cout << "*argv[1]: " << *argv[1] << std::endl;
    std::cout << "argv[1]: "  << ( void * )argv[1]  << std::endl;
    std::cout << *argv1 << std::endl;;

    for ( char *p : argv ) delete p;

    return 0;
}

The output can look like

*argv[1]: 5
argv[1]: 0x9aeb018
5

Take into account using casting to void * in statement

    std::cout << "argv[1]: "  << ( void * )argv[1]  << std::endl;

Otherwise argv1[1] will be interpretated by operator << as the first character of a string terminated by zero.

Upvotes: 0

edmz
edmz

Reputation: 8494

In general, to convert a std::string to an integral type, you can use std::stoi.
Your code shows undefined behaviors as you're writing to pointers which point to unallocated memory; use std::string [] or a standard container of std::strings.

Upvotes: 0

Related Questions