5 Replies - 1557 Views - Last Post: 18 February 2010 - 05:06 AM Rate Topic: -----

#1 sbromley  Icon User is offline

  • D.I.C Head

Reputation: 21
  • View blog
  • Posts: 127
  • Joined: 20-May 09

Array of char* Problem

Posted 17 February 2010 - 09:22 PM

I'm having trouble with an array of char*. When ever I set args[0] to something then make another substr call its sets the args[0] to whatever that is.

  int index = command.find_first_of(' ');
  
  int previous = 0;
  int numArgs = 0;
  while(index != -1){
  		previous = index + 1;
  		index = command.find_first_of(' ', previous);
  		numArgs++;
  }
 numArgs = numArgs + 2;
 index = command.find_first_of(' ');
 previous = 0;
 int count = 0;
 char *args[numArgs];
 while(index != -1){
 		char* temp = (char*)command.substr(previous, index - previous).c_str();
 		args[count] = temp;
		cout<<args[0]<<"\n";
 		previous = index + 1;
  		count++;
  		index = command.find_first_of(' ', previous);
  }
	  cout<<args[0]<<"\n";
  if(numArgs > 2){
       char *last = (char*)command.substr(previous, command.size() - 1).c_str();
  }				  }
	  cout<<args[0]<<"\n";
 args[numArgs - 1] = (char*)0;



Its probably some pointer issue.

Is This A Good Question/Topic? 0
  • +

Replies To: Array of char* Problem

#2 PlasticineGuy  Icon User is offline

  • mov dword[esp+eax],0
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,436
  • Joined: 03-January 10

Re: Array of char* Problem

Posted 17 February 2010 - 10:05 PM

1. Since you are using C++, use its cast operators instead of C casting:
char *last = const_cast<char*>(command.substr(previous, command.size() - 1).c_str());

2. Can't you use an array of std::strings?
Was This Post Helpful? 0
  • +
  • -

#3 bodom658  Icon User is offline

  • Villiage Idiom
  • member icon

Reputation: 114
  • View blog
  • Posts: 1,123
  • Joined: 22-February 08

Re: Array of char* Problem

Posted 17 February 2010 - 10:13 PM

You are trying to set a single character to a character array. Try changing the line args[count] = temp so that you are assigning a member of temp, or turn args into a multidimensional array to store each temp array.
Was This Post Helpful? 0
  • +
  • -

#4 sbromley  Icon User is offline

  • D.I.C Head

Reputation: 21
  • View blog
  • Posts: 127
  • Joined: 20-May 09

Re: Array of char* Problem

Posted 17 February 2010 - 10:17 PM

View PostPlasticineGuy, on 17 February 2010 - 09:05 PM, said:

1. Since you are using C++, use its cast operators instead of C casting:
char *last = const_cast<char*>(command.substr(previous, command.size() - 1).c_str());

2. Can't you use an array of std::strings?



I just found this and I think this is the answer I'm looking for. Its good to see it again on here though. I wish I could use an array of strings but I'm passing it to the syscall execvp and it requires a char**
Was This Post Helpful? 0
  • +
  • -

#5 PlasticineGuy  Icon User is offline

  • mov dword[esp+eax],0
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,436
  • Joined: 03-January 10

Re: Array of char* Problem

Posted 17 February 2010 - 10:19 PM

Can't you just use:
std::string mystrings[500];
//do operations
execvp(&const_cast<char*>(mystrings.c_str()));


EDIT: No, that doesn't work.

This post has been edited by PlasticineGuy: 17 February 2010 - 10:20 PM

Was This Post Helpful? 0
  • +
  • -

#6 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 944
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Array of char* Problem

Posted 18 February 2010 - 05:06 AM

Note that you cannot modify a std::string by casting your way around the 'const' from c_str() its undefined behaviour, because the const char* returned by c_str() may not point to the same underlying representation which is ordinarily used by std::string.

With this in mind, the way to pass a std::string to a function which requires a mutable char* is to first copy that string into a char array and pass that copy instead; then copy the char array back into the C string. You can wrap this behaviour up in a class to keep things tidy and use a type conversion operator to allow direct access to the array.

e.g. this example using 'printf' on a std::string would normally cause a compiler error, but with the c_string wrapper class its perfectly legal. (of course, printf accepts a const char* so you would use c_str() normally - the code in main is just for illustration of a conversion operator)
#include <string>
#include <cstring>
#include <cstdio>

class c_string
{
    std::string& cpp_str;
    char* mutable_str;
    c_string(const c_string&);
    c_string& operator=(const c_string&);
public:
    c_string(std::string& s)
        : cpp_str(s)
        , mutable_str( new char[s.size()+1] ) 
    {
        std::strncpy(mutable_str, s.c_str(), s.size()+1);
    }
    operator char*&() { return mutable_str; }
    ~c_string() 
    { 
        cpp_str = mutable_str;
        delete [] mutable_str; 
    }
};

int main()
{
    std::string s = "hello, world";
    printf( c_string(s) );
} 




You could extend that idea to create a wrapper for an array of strings
#include <vector>
#include <string>
#include <cstring>

class c_string_array
{
    std::vector<std::string>& str_vec;
    char** array;
    c_string_array(const c_string_array&);
    c_string& operator=(const c_string_array&);
public:
    c_string_array(std::vector<std::string>& v)
        : str_vec(v)
        , array( new char*[v.size()] )
    {
        for(size_t n(0); n!=v.size(); ++n)
        {
            std::string& s(v.at(0));
            array[n] = new char[s.size()+1];
            std::strncpy(array[n], s.c_str(), s.size()+1);
        }
    }
    operator char**&() { return array; }
    ~c_string_array()
    {
        for(size_t n(0); n!=str_vec.size(); ++n)
        {
            str_vec.at(n) = array[n];
            delete [] array[n];
        }
        delete [] array;
    }
}; 
void fill_array(char** arr)
{
    for(size_t n(0); n!= 10; ++n)
    {
        strncpy(arr[n], "hello", 10);
    }
}

int main()
{
    std::vector<std::string> v(10, std::string(10, ' '));
    std::vector<std::string>::const_iterator i;

    for(i = v.begin() ; i != v.end(); ++i)
        std::cout << *i << '!' << std::endl;
    
    fill_array( c_string_array(v) );

    for(i = v.begin() ; i != v.end(); ++i)
        std::cout << *i << '!' << std::endl;
}  


using the c_string_array wrapper class, you could call execvp with a std::vector<std::string>
int main(int argc, char* argv[])
{
    std::vector<std::string> args(argv, argv+argc);
    execvp( c_string_array( args ) ); 
}

This post has been edited by Bench: 18 February 2010 - 05:08 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1