Corellis
Corellis

Reputation: 73

(C++) Very Basic Questions Regarding Syntax

C++ novice here. I have some basic questions. In int main( int argc, char *argv[] )

  1. How is char *argv[] supposed to be read (or spoken out to humans)?
  2. Is it possible to clear/erase specific content(s), character(s) in this case, of such array? If yes, how?
  3. Can arrays be resized? If yes, how?
  4. How can I copy the entire content of argv[] to a single std::string variable?
  5. Are there other ways of determining the number of words / parameters in argv[] without argc? If yes, how? (*)

I'd appreciate explanations (not code) for numbers 2-5. I'll figure out the code myself (I learn faster this way).

Thanks in advance.

(*) I know that main(char *argv[]) is illegal. What I mean is whether there's at least a way that does not involve argcat all, like in the following expressions:

for( int i = 0; i < argc; ++i ) {
    std::cout << argv[i] << std::endl;
}

and

int i = 0;    
while( i < argc ) {
    std::cout << argv[i] << std::endl;
    ++i;
}

Or

int i = 0;
do { 
     std::cout << argv[i] << std::endl;
     ++i; } while( i < argc );

Upvotes: 7

Views: 450

Answers (7)

Mark B
Mark B

Reputation: 96233

  1. Several options: array of pointer to char OR array of C-string.

  2. You can assign to particular characters to clear them, or you can shift the rest of the array forwards to "erase" characters/elements.

  3. Normal C-style arrays cannot be resized. If you need a resizable array in C++ you should use std::vector.

  4. You'll have to iterate over each of the items and append them to a string. This can be accomplished with C++ algorithms such as copy in conjunction with an ostream_iterator used on an ostringstream.

  5. No. If there was such a way, there wouldn't be any need for argc. EDIT: Apparently for argv only the final element of the array is a null pointer.

Upvotes: 1

Chad
Chad

Reputation: 19609

1) It is supposed to be char **argv or char *argv[] which is a pointer to an array of characters more commonly known as an array of strings

2) CString is the std library to manipulate C strings (arrays of characters). You cannot resize an array without reallocating, but you can change the contents of elements by referencing it by index:

for(int i = 0; i < argc; ++i)
{
   //set all the strings to have a null character in the
   //first slot so all Cstring operations on this array, 
   //will consider it a null (empty) string
   argv[i] = 0;
}


3) Technically no, however they can be deleted then reallocated:

int *array = new int[15]; //array of size 15
delete[] array;
array = new int[50]; //array of size 50

4) This is one way:

string *myString;
if(argc > 0)
{
   myString = new string(argv[0]);
   for(int i = 1; i < argc; ++i)
      myString->append(argv[i]);
}

5) Yes, according to Cubbi:

POSIX specifies the final null pointer for argv, see for example "The application shall ensure that the last member of this array is a null pointer." at pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html

Which means you can do:

char *val = NULL;
int i = 0;
do
{
   val = argv[i++]; //access argv[i], store it in val, then increment i
   //do something with val
} while(val != NULL); //loop until end of argv array

Upvotes: 0

Xeo
Xeo

Reputation: 131789

char **argv[]

Is wrong. It should be either char **argv or char *argv[], not a mixture of both. And then it becomes a pointer-to-pointer to characters, or rather a pointer to c-strings, i.e., an array of c-strings. :) cdecl.org is also quite helpful at thing like this.
Then, for the access, sure. Just, well, access it. :) argv[0] would be the first string, argv[3] would be the 4th string. But I totally wouldn't recommend replacing stuff in an array that isn't yours or that you know the internals of.
On array resize, since you're writing C++, use std::vector, which does all the complicated allocation stuff for you and is really safe. Generally, it depends on the array type. Dynamically allocated arrays (int* int_arr = new int[20]) can, static arrays (int int_arr[20]) can't.
To copy everything in argv into a single std::string, loop through the array and append every c-string to your std::string. I wouldn't recommend that though, rather have a std::vector<std::string>, i.e., an array of std::strings, each holding one of the arguments.

std::vector<std::string> args;
for(int i=0; i < argc; ++i){
  args.push_back(argv[i]);
}

On your last point, since the standard demands argv to be terminated by a NULL pointer, it's quite easy.

int myargc = 0;
char** argv_copy = argv;
while(++argv_copy)
  ++myargc;

The while(++argv_copy) will first increment the pointer of the array, letting it point to the next element (e.g., after the first iteration it will point at c-string #2 (argv[1])). After that, if the pointer evaluates to false (if it is NULL), then the loop brakes and you have your myargc. :)

Upvotes: 1

imax
imax

Reputation: 238

Array in C/C++ is not an object, but just a pointer to first element of array, so you cannot simply delete or insert values.

Answering your questions:

  1. char *argv[] can be read as 'array of pointers to char'
  2. It's possible, but involves direct manipulations with data in memory, such as copying and/or moving bytes around.
  3. No. But you may allocate new array and copy necesary data
  4. By manually copying each element into std::string object
  5. No.

As a summary: C++ is much more low-level language that you think.

Upvotes: -1

Trent
Trent

Reputation: 13477

  1. char *argv[] can be read as: "an array of pointers to char"

    char **argv can be read as: "a pointer to a pointer to char"

  2. Yes, you may modify the argv array. For example, argv[0][0] = 'H' will modify the first character of the first parameter. If by "erase/clear" you mean remove a character from the array and everything automatically shift over: there is no automatic way to do that - you will need to copy all the characters one-by-one over to the left (including the NULL termination)

  3. No, arrays cannot be resized. You will need to create a new one and copy the contents

  4. How do you want to represent ALL the parameter strings as 1 std::string? It would make more sense to copy it to an array of std::strings

  5. No, there is no special indication of the last entry in the array. you need to use argc

Upvotes: 0

Simon Richter
Simon Richter

Reputation: 29586

  1. It is spoken as "array of pointers to pointers to character" (note that this is not the signature of the main function, which is either int argc, char **argv or int argc, char *argv[] -- which is equivalent).
  2. The argv array is modifiable (lack of const). It is illegal to write beyond the end of one of the strings though or extend the array; if you need to extend a string, create a copy of it and store a pointer in the array; if you need to extend the array, create a copy of the array.
  3. They cannot be resized per se, but reinterpreted as a smaller array (which sort of explains the answer to the last question).
  4. You will be losing information this way -- argv is an array of arrays, because the individual arguments have already been separated for you. You could create a list of strings using std::list<std::string> args(&argv[1], &argv[argc]);.
  5. Not really. Most systems have argv NULL terminated, but that is not a guarantee.

Upvotes: 0

user2100815
user2100815

Reputation:

  1. It's an array of pointers to char.

  2. Sort of - you can overwrite them.

  3. Only by copying to a new array.

  4. Write a loop and append each argv[i] to a C++ string.

  5. Most implementations terminate the array with a NULL pointer. I can't remember if this is standard or not.

Upvotes: 2

Related Questions