joining args ?

B

benoit.lefebvre

How can I join args from a function ?

Here is what I've done so far but I'm getting weird results

code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;

if (argv[1]) {
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}
------------------------------------------

execution:
------------8<--------------------------
[mox@home (/home/mox)]: ./cnsudo Hi this is a test
2) Adding: "this"
3) Adding: "is"
4) Adding: "a"
5) Adding: "test"
All: "Hi is a test"
------------------------------------------

How come I am missing the second argument ? But the strcat works ???

Thanks,
--Benoit Lefebvre
(e-mail address removed)
 
W

Walter Roberson

#include<stdio.h>
int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {
allchars = argv[1];

Here you are setting the pointer allchars to point to the same place
that argv[1] does. But you don't know how much space is allocated
at that location, so writing anything further at that location
is a bad idea.

You need to find a way to allocate as much memory as will be
required to put all of the arguments together, and then to copy
the arguments into that allocated block of memory.
 
S

santosh

How can I join args from a function ?

Here is what I've done so far but I'm getting weird results

code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;

if (argv[1]) {

argv[1] points to the first argument after the program's invocation name,
which is in argv[0]. In some cases, the program may not receive an
invocation name.
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");


allchars points to the first argument, i.e. argv[1]. You should not assume
that this array has enough space for you to concactenate the remaining
arguments. It has just enough elements to hold the first argument, plus one
more for a null character, no more.

You must initialise allchars to point to an array of chars that is
sufficient in length to hold a linear series of all the command-line
arguments. The total length of the arguments can be calculated by using
strlen on each one. Then allocate an array using malloc.
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}
 
B

Benoit Lefebvre

#include<stdio.h>
int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {
allchars = argv[1];

Here you are setting the pointer allchars to point to the same place
that argv[1] does. But you don't know how much space is allocated
at that location, so writing anything further at that location
is a bad idea.

You need to find a way to allocate as much memory as will be
required to put all of the arguments together, and then to copy
the arguments into that allocated block of memory.
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton

I'm not quite sure to understand at 100%..

How can I allocate the memory ?

Sorry for being a newbie ;)

--Benoit Lefebvre
(e-mail address removed)
 
B

Benoit Lefebvre

How can I join args from a function ?
Here is what I've done so far but I'm getting weird results
code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {

argv[1] points to the first argument after the program's invocation name,
which is in argv[0]. In some cases, the program may not receive an
invocation name.
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");


allchars points to the first argument, i.e. argv[1]. You should not assume
that this array has enough space for you to concactenate the remaining
arguments. It has just enough elements to hold the first argument, plus one
more for a null character, no more.

You must initialise allchars to point to an array of chars that is
sufficient in length to hold a linear series of all the command-line
arguments. The total length of the arguments can be calculated by using
strlen on each one. Then allocate an array using malloc.
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}


Oh.. I think I found how to fix it finally

--------8<----------------
if (argv[1]) {
strcat(allchars, argv[1]); <---------------------------
Here is the correction
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
printf("%i) Adding: \"%s\"\n",i, argv);
}
}
}
--------------------------
 
S

santosh

Benoit said:
#include<stdio.h>
int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {
allchars = argv[1];

Here you are setting the pointer allchars to point to the same place
that argv[1] does. But you don't know how much space is allocated
at that location, so writing anything further at that location
is a bad idea.

You need to find a way to allocate as much memory as will be
required to put all of the arguments together, and then to copy
the arguments into that allocated block of memory.
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton

I'm not quite sure to understand at 100%..

How can I allocate the memory ?

Sorry for being a newbie ;)

No problem. To allocate memory during the runtime of the program, you can
use malloc or calloc or realloc. To start with malloc is simplest.

For example to allocate an array of 100 char objects you can do:

#include <stdlib.h>

#define ARR_SIZE 100

/* ... */

char *arr = NULL;
arr = malloc(ARR_SIZE);
if (arr == NULL) deal_with_failure();
else continue_program();

To allocate an array of 200 doubles, you can do:

/* ditto */
double *arr = NULL;
arr = malloc(ARR_SIZE * sizeof *arr);
/* ditto */

Notice that in C a char is 1 byte by definition, so in that char example a
size expression need not be included. The sizes of other C types can be
found by applying the sizeof operator to them.

Be sure to read this group's FAQ,

<http://www.c-faq.com/>

and wiki,

<http://www.clc-wiki.net/>
 
S

santosh

Benoit said:
How can I join args from a function ?
Here is what I've done so far but I'm getting weird results
code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {

argv[1] points to the first argument after the program's invocation name,
which is in argv[0]. In some cases, the program may not receive an
invocation name.
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");


allchars points to the first argument, i.e. argv[1]. You should not
assume that this array has enough space for you to concactenate the
remaining arguments. It has just enough elements to hold the first
argument, plus one more for a null character, no more.

You must initialise allchars to point to an array of chars that is
sufficient in length to hold a linear series of all the command-line
arguments. The total length of the arguments can be calculated by using
strlen on each one. Then allocate an array using malloc.
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}


Oh.. I think I found how to fix it finally

--------8<----------------
if (argv[1]) {
strcat(allchars, argv[1]); <---------------------------
Here is the correction
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
printf("%i) Adding: \"%s\"\n",i, argv);
}
}
}
--------------------------


Your correction has failed to correct anything. You still do not indicate
what allchars is pointing to.

In future, please post compilable code. Otherwise it becomes more difficult,
though not impossible, for us to help you.
 
B

Benoit Lefebvre

Benoit said:
(e-mail address removed) wrote:
How can I join args from a function ?
Here is what I've done so far but I'm getting weird results
code:
------------8<--------------------------
#include<stdio.h>
int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {
argv[1] points to the first argument after the program's invocation name,
which is in argv[0]. In some cases, the program may not receive an
invocation name.
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
allchars points to the first argument, i.e. argv[1]. You should not
assume that this array has enough space for you to concactenate the
remaining arguments. It has just enough elements to hold the first
argument, plus one more for a null character, no more.
You must initialise allchars to point to an array of chars that is
sufficient in length to hold a linear series of all the command-line
arguments. The total length of the arguments can be calculated by using
strlen on each one. Then allocate an array using malloc.
strcat(allchars, argv);
}
}
}
printf("All: \"%s\"\n", allchars);
return 0;
}

Oh.. I think I found how to fix it finally
--------8<----------------
if (argv[1]) {
strcat(allchars, argv[1]); <---------------------------
Here is the correction
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
printf("%i) Adding: \"%s\"\n",i, argv);
}
}
}
--------------------------


Your correction has failed to correct anything. You still do not indicate
what allchars is pointing to.

In future, please post compilable code. Otherwise it becomes more difficult,
though not impossible, for us to help you.


Sorry.. Here is what I compiled when it worked.

--------- 8< ------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char * allchars;

allchars = (char*) malloc (1024);

if (argv[1]) {
strcat(allchars, argv[1]);
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}
-------------------------------
 
S

santosh

Benoit said:
Benoit said:
(e-mail address removed) wrote:
How can I join args from a function ?
Here is what I've done so far but I'm getting weird results
code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;
if (argv[1]) {
argv[1] points to the first argument after the program's invocation
name, which is in argv[0]. In some cases, the program may not receive
an invocation name.
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");

allchars points to the first argument, i.e. argv[1]. You should not
assume that this array has enough space for you to concactenate the
remaining arguments. It has just enough elements to hold the first
argument, plus one more for a null character, no more.
You must initialise allchars to point to an array of chars that is
sufficient in length to hold a linear series of all the command-line
arguments. The total length of the arguments can be calculated by
using strlen on each one. Then allocate an array using malloc.
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}
Oh.. I think I found how to fix it finally
--------8<----------------
if (argv[1]) {
strcat(allchars, argv[1]); <---------------------------
Here is the correction
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
printf("%i) Adding: \"%s\"\n",i, argv);
}
}
}
--------------------------


Your correction has failed to correct anything. You still do not indicate
what allchars is pointing to.

In future, please post compilable code. Otherwise it becomes more
difficult, though not impossible, for us to help you.


Sorry.. Here is what I compiled when it worked.

--------- 8< ------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char * allchars;

allchars = (char*) malloc (1024);


In C you need not, and probably should not, cast the return value of malloc
and family. Doing so can prevent the compiler from warning you when you
fail to include stdlib.h, which is needed for the correct declaration of
malloc.

Indeed you _have_ failed to include stdlib.h, and thus calling a function
with no prototype in scope, you've invoked undefined behaviour.

Also instead of hard-coding a value for the array allocation, you might run
strlen over each program argument and add them all up to allocate just the
space you want. Don't forget to adjust the final length for any whitespace
you need and for the final null character.
if (argv[1]) {
strcat(allchars, argv[1]);

strcat and other string functions are declared in string.h, which you've not
included above.
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}


The two IFs are not needed. Just loop from argv[1] to argv[argc-1].
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}
-------------------------------

Also you never use the variable 'j'.
 
D

Default User

Benoit Lefebvre wrote:

Sorry.. Here is what I compiled when it worked.

--------- 8< ------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char * allchars;

allchars = (char*) malloc (1024);

The cast is unnecessary in any circumstance, and in this case it covers
up a serious error. You didn't include the correct header or other
mechanism to provide a declaration for malloc().

For this particular case, you could just as well have made this:

char allchars[1024];

if (argv[1]) {
strcat(allchars, argv[1]);
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;
}


The problem here is that you don't take any steps to make sure that you
don't overrun that buffer you declared. What happens when the total
length of your argv[] entries and the spacers exceeds 1024?

You should check the length of each before doing the strcat() to make
sure there is room remaining. What to do if there isn't is a design
decision. Either make more space with realloc() or stop.



Brian
 
E

Eric Sosman

Benoit Lefebvre wrote On 07/27/07 16:50,:
[...]
char * allchars;

allchars = (char*) malloc (1024);

if (argv[1]) {
strcat(allchars, argv[1]);

Here's another problem, in addition to those that
santosh and Default User have pointed out. Both arguments
to strcat() must be strings, and a string is an array of
characters terminated by a char with the value zero. But
memory obtained from malloc() has unpredictable content:
it might be full of zeroes, it might be full of something
left over from an earlier use, it might be full of random
garbage. So you can't be sure that allchars is pointing
to a properly-formed string, as required by strcat().

Solution #1:

allchars[0] = '\0'; /* now allchars holds string */
strcat(allchars, argv[1]);

Solution #2 (better):

strcpy(allchars, argv[1]); /* different function */
 
D

Default User

Eric said:
Benoit Lefebvre wrote On 07/27/07 16:50,:
[...]
char * allchars;

allchars = (char*) malloc (1024);

if (argv[1]) {
strcat(allchars, argv[1]);

Here's another problem, in addition to those that
santosh and Default User have pointed out. Both arguments
to strcat() must be strings, and a string is an array of
characters terminated by a char with the value zero.


Yeah, good catch.




Brian
 
H

Harvey

How can I join args from a function ?

Here is what I've done so far but I'm getting weird results

code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;

if (argv[1]) {
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;}

------------------------------------------

execution:
------------8<--------------------------
[mox@home (/home/mox)]: ./cnsudo Hi this is a test
2) Adding: "this"
3) Adding: "is"
4) Adding: "a"
5) Adding: "test"
All: "Hi is a test"
------------------------------------------

How come I am missing the second argument ? But the strcat works ???

Thanks,
--Benoit Lefebvre
(e-mail address removed)


I suppose that all these args are stored in a consequentive memory,
which is, in this example,
the memory is something like this:
'H' 'i' '\0' 't' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
and arg[1] is pointed to 'H', and arg[2] is pointed to 't', and so
on...

so when you encounted the statement: strcat(arg[1], " ");
we get
'H' 'i' ' ' '\0' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
which now arg[2] is empty string now

I think this can explain the result.

-- L.H.
 
S

santosh

Harvey said:
How can I join args from a function ?

Here is what I've done so far but I'm getting weird results

code:
------------8<--------------------------
#include<stdio.h>

int main (int argc, char *argv[])
{
int i;
int j;
char *allchars;

if (argv[1]) {
allchars = argv[1];
if (argv[2]) {
for (i = 2; i < argc; i++) {
printf("%i) Adding: \"%s\"\n",i, argv);
strcat(allchars, " ");
strcat(allchars, argv);
}
}
}

printf("All: \"%s\"\n", allchars);
return 0;}

------------------------------------------

execution:
------------8<--------------------------
[mox@home (/home/mox)]: ./cnsudo Hi this is a test
2) Adding: "this"
3) Adding: "is"
4) Adding: "a"
5) Adding: "test"
All: "Hi is a test"


I suppose that all these args are stored in a consequentive memory,
which is, in this example,
the memory is something like this:
'H' 'i' '\0' 't' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
and arg[1] is pointed to 'H', and arg[2] is pointed to 't', and so
on...


This is not guaranteed in the C Standard. The memory layout is
implementation dependant. Also the idiomatic names are argv[0], argv[1]
etc.
so when you encounted the statement: strcat(arg[1], " ");
we get
'H' 'i' ' ' '\0' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
which now arg[2] is empty string now

No we don't. argv[2] does not become an empty string.
 
M

Malcolm McLean

Harvey said:
I suppose that all these args are stored in a consequentive memory,
which is, in this example,
the memory is something like this:
'H' 'i' '\0' 't' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
and arg[1] is pointed to 'H', and arg[2] is pointed to 't', and so
on...

so when you encounted the statement: strcat(arg[1], " ");
we get
'H' 'i' ' ' '\0' 'h' 'i' 's' '\0' 'i' 's' '\0' 'a' '\0' 't' 'e' 's'
't' '\0'.
which now arg[2] is empty string now

I think this can explain the result.
Putting the command line args in a contiguous block of memory is an obvious
thing to do. However you can't rely on this.

By calling strcat() you'd shift the characters down one - strictly it would
be undefined behaviour becuse the buffers are overlapping, but probably the
function is a simply byte copying loop. So argv[2] now points to "is", and
there is a double nul terminating it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,049
Members
48,769
Latest member
Clifft

Latest Threads

Top