Sign in to follow this  
TheBinaryMan

Double pointer to argv

Recommended Posts

Hello. Im still not comfortable working with pointers when arrays and strings are involved, so hopefully clarification will help. If I have the following code:


char **p_argv;

int main(int argc, char *argv[])
{
p_argv = argv;

for(int i=0;i<argc;i++)
cout << (*p_argv[i]) << endl;
}



If I use "(*p_argv[i])" to dereference one level, I get the beginning char for each string in argv. How do I access the rest of the chars for each of the strings?

Share this post


Link to post
Share on other sites
There are a couple way about doing this. Since you are using C++, I'd say go the "safe" route below. But if you want to do this the classic C way to learn how C style strings are used, go the "unsafe" way.


#include <string>
#include <iostream>

#include <cstring>

int main(int argc, char *argv[])
{
// The safe way
for(int i=0; i < argc; ++i)
{
const std::string arg = argv[i];
std::cout << arg << std::endl;

//this
const std::string::size_type length = arg.length();
for( int j = 0; j < length; ++j )
std::cout << arg[j] << std::endl;

//or better yet, this:
for( std::string::const_iterator itr = arg.begin(); itr != arg.end(); ++itr )
std::cout << *itr << std::endl;
}

// The unsafe way
for(int i=0; i < argc; ++i)
{
const char *arg = argv[i];
std::cout << arg << std::endl;
const size_t length = strlen(arg);
for( int j = 0; j < length; ++j )
std::cout << arg[j] << std::endl;
}
}






I say one is safe and the other isn't because direct pointer manipulation can quickly lead to bugs if you are unsure what you are doing. Try not to use C style strings in C++ code. Use std::string whereever you can.

Share this post


Link to post
Share on other sites
Quote:
Original post by TheBinaryMan
If I use "(*p_argv[i])" to dereference one level, I get the beginning char for each string in argv. How do I access the rest of the chars for each of the strings?

You are "dereferencing" two levels. one with x[i] and one with *x.

x[0] is the same as *x

(*p_argv[i]) is the same as p_argv[i][0]

Just write p_argv[i] to get the whole string

Share this post


Link to post
Share on other sites
char* argv[] is a variable named argv of type char* [].*

What is that type? It's an array (hence []) of char*.

So, argv[i] gives us element #i of the array. Each element is a char*.

Supplying a char* to std::cout::operator<< prints the pointed-at string.

Now, how about *argv[i]? That is taking argv[i], which is a char*, and dereferencing it, using the '*'. Dereferencing a char* gives us a char - the one that the pointer is pointing at.

When a char* is used to represent a string, it points at the beginning of the string (which is assumed to just run until the next zero byte). Thus, dereferencing the char* yields the beginning character of the string.

Supplying a char to std::cout::operator<< prints the character.

* This is actually a lie. Because the array size isn't known before we run the program, we can't specify it, and therefore this isn't really an array. The type is actually char**. But we will be using it the same way.

Incidentally, "the array size isn't known before we run the program" is why we need the argc parameter. :)




As for KulSeran's advice, I'd take it a little further:


#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <ostream>

int main(int argc, char* argv[]) {
// First, since both arrays and C-style strings cause problems, let's
// replace both with real first-class types:
std::vector<std::string> args(argv, argv + argc);

// Let's use the standard library to display the strings on separate lines:
std::copy(args.begin(), args.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

// And just for show: we can, of course, feed the input directly to std::copy:
std::copy(argv, argv + argc, std::ostream_iterator<char*>(std::cout, "\n"));
}



C++ is a very different language from C. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this