1823470 Members
2467 Online
109660 Solutions
New Discussion юеВ

language and scripting

 
SOLVED
Go to solution
Soumya Poddar
Advisor

language and scripting

I am new in Unix
please forgive me if my question looks
very simple to you.


I am writing this

program in c
.....
while((c=getopt(..,..,..))!=-1)
{
...
...
......
}

but my two of my options in my program need more than two arguments
how do I do it please help.
22 REPLIES 22
Laurent Menase
Honored Contributor
Solution

Re: language and scripting


#include
#include
main (int argc, char *argv[])
{
int c;
int bflg, aflg=0, errflg=0;
extern char *optarg;
char *ifile,*ofile;

extern int optind, optopt;
while ((c = getopt(argc, argv, ":abf:o:")) != -1)
switch (c) {
case 'a':
aflg++;
break;
case 'f':
ifile = optarg++;
if (optarg[0]=='-')
errflg++;
else
{
ofile = ++optarg;
optind++;
}
break;
case ':': /* -f or -o without arguments */
fprintf(stderr, "Option -%c requires an argument\n",
optopt);
errflg++;
break;
case '?':
fprintf(stderr, "Unrecognized option: - %c\n",
optopt);
errflg++;
}
if (errflg) {
fprintf(stderr, "usage: . . . ");
exit (2);
}
printf("f= %s..%s..%d\n",ifile,ofile,aflg);
for ( ; optind < argc; optind++)
printf("%d %s\n",optind,argv[optind]);
}
Soumya Poddar
Advisor

Re: language and scripting

Thank you
Soumya Poddar
Advisor

Re: language and scripting

sir
your program is not taking two arguments
i takes first arguments properly but for the second one the program takes it as a string except the first two charecters of the first argument..
I want to mean that

if input is

./a.out -f 4567 7890

the output gets
f= 4567..67..0

so it does not taking the second argument


please help sir
Laurent Menase
Honored Contributor

Re: language and scripting

indeed it is
case 'f':
ifile = optarg;
if (optarg[0]=='-')
errflg++;
else
{
ofile = argv[ optind++];
}
break;


sorry
Soumya Poddar
Advisor

Re: language and scripting

thank you
sir
it helps me a lot
Soumya Poddar
Advisor

Re: language and scripting

actually here the getopt does not parse the argument by it-self fully
but our intervention is needed there
is there any way to avoid this
is there any function of technique is there

plese help me sir
Laurent Menase
Honored Contributor

Re: language and scripting

can you clarify?
I am not sure I understand what you are trying to do.

just an example could help

Soumya Poddar
Advisor

Re: language and scripting

actually

we write
while((c=getopt(...,...,":abc:")!=-1)
{
....
....
....
}

here the getopt can easily understand that the option c should need a argument with it
hence, it searchs for the argument when it sees the option -c in the string of one of it's strings stored in argv[] vector.

just like that do we have any other kind of option where the function it self searches for the two arguments or the argument list.


please help
sir

if u need any more clarification please reply me
Laurent Menase
Honored Contributor

Re: language and scripting

I am sorry I don't follow

./a.out -f toto tata -c arg1 arg2 arg3 arg4 ... -z
you want to get the list of -c args?

Soumya Poddar
Advisor

Re: language and scripting

yes
but using the function getopt itself

as using the getopt
for single argument we can get it using oparg

for the same thing using a list og arguments
can we get it using some standard syntax

plese reply sir
Bill Hassell
Honored Contributor

Re: language and scripting

> ./a.out -f toto tata -c arg1 arg2 arg3 arg4 ... -z
> you want to get the list of -c args?

The shell is separating each space-delimited string as a separate item for getopt. To supply multiple arguments to a single option, keep the arguments together. I like to use commas (more readable) or use quotes:

./a.out -f toto,tata -c arg1,arg2,arg3,arg4 ... -z

or

./a.out -f "toto tata" -c "arg1 arg2 arg3 arg4" ... -z


Bill Hassell, sysadmin
Soumya Poddar
Advisor

Re: language and scripting

in that case is my program need to parse them
or these list of arguments will be passed to me through some standard external variable
like optagr


plese reply
sir
Laurent Menase
Honored Contributor

Re: language and scripting

getopt stop to the first identified -x
now if optarg points to the first string after the identified option if there is a : in the description
optind points to the next arg

so to get a variable number of params you can do for instance:

char * v2;
char *allcparms[256];
int indexcparms=0;
......
case 'c':
allcparms[indexcparms++]=optarg;
while(v2=argv[optind])
{
if ( v2[0]=='-' ) break;
allcparms[indexcparms++]=v2;
optind++;
}
break;

so
./a.out -c 1 2 3 4 5 6 -f xx yy
will put 1 2 3 4 5 6 in allcparms[0..5]
./a.out -c 1 2 3 4 5 6
also
./a.out -c 1 2 3 4 5 6 -- xx yy
also

is it what you are trying to make?
Laurent Menase
Honored Contributor

Re: language and scripting

in one of my previous answer I wrote:
if (optarg[0]=='-')
in fact it is if (argv[optind][0]=='-')
Soumya Poddar
Advisor

Re: language and scripting

yes

but here in that case i parse those arguments using my programs

but i am asking that is there any standard function is there like getopt using which
i get my varriable number of arguments using some standard varriable like optarg in getopt

plese reply sir
Laurent Menase
Honored Contributor

Re: language and scripting

please give an example
I don't follow what you are trying to get and how?

are you trying to do it in script?
Soumya Poddar
Advisor

Re: language and scripting


like
in C

while((c=getopt(...,...,":abf:"))!=-1)
{
.....
.....
.....
}

now if my input is
./a.out -f Mandoc.doc
we can get it like

ifile=optagr

but if we want to give the input like
./a.out -f Mandoc.doc Relese.doc .....

then is there any standard function which will
give same oppurtunity access those argument list

like
arguments=optargarr;

where
arguments is declared like

char* arguments[];

and optagr declared as

extern char* optarg[];

i want to use it in simple C program

James R. Ferguson
Acclaimed Contributor

Re: language and scripting

Hi:

> but if we want to give the input like
./a.out -f Mandoc.doc Relese.doc .....

As Bill said, quote the argument and 'getopt()' will see it as one. I suspect that you come from Windows environments where spaces are common in filenames. Spaces (whitespace) in Unix separates arguments when the shell parses a command line/

Hence:

# ./a.out -f "Mandoc.doc Relese.doc"

...will leave you with *one* argument to the '-f' option.

Regards!

...JRF...
Soumya Poddar
Advisor

Re: language and scripting

ya
I am a fresher i am new in company and i am new in unix i came from windows enviourment

so hence
we have make our program in such a way that it can parse the arguments by it self

and there is no way to parse multiple arguments uning getopt() in c

ok sir thank you
for helping me
and shareing your knowladge with me

thank you
Laurent Menase
Honored Contributor

Re: language and scripting

the only way I see is using getopt with the while loop I gave you just above.

char * v2;
char *allcparms[256]; /* if we suppose the max param is 256.
int indexcparms=0;
......
case 'c':
if (indexcparms==256) errflg++;
else
allcparms[indexcparms++]=optarg;
while(indexcparms<256 && (v2=argv[optind]))
{
if ( v2[0]=='-' ) break;
allcparms[indexcparms++]=v2;
optind++;
}
break;

my allcparms is your optargs.

Now there is an other way which overload the argv
case 'c':
argv[optind-1]=optarg;
params=&argv[optind-1];
while((v2=argv[optind]) && (v2[0]!='-')) optind++;

break;

but then your argv will be changed.

optarg is always a pointer in argv[optind-1] string
but depends on if the option is like
getopt("c:x") will give:
-c arg1 -> optarg=optarg[optind-1]
or
-carg1 -> optarg=optarg[optind-1]+1
-xcarg1 -> optarg=optarg[optind-1]+2

So all getopt() is based on pointing in argv to avoid any other allocations.

The only problem of my last proposition is it modifies argv[] string array, so you can't parse it again.

now If you really want dynamic allocation
it can also be made .
but there is no std api.


Dennis Handly
Acclaimed Contributor

Re: language and scripting

>that is there any standard function is there like getopt using which get my variable number of arguments using some standard variable like optarg in getopt

No, you'll have to design your own. Or take Bill's and JRF's suggestion to merge the argument components into just one. Splitting those on spaces, commas or colons is easy, you could use strtok(3).

Also, I don't think Laurent's example where he changes optind will work on Linux?

I recently tried to port a HP-UX program that used getopt(3) to Linux that allowed files and options to be in any order and I wasn't successful.

>Laurent:
extern char *optarg;
extern int optind, optopt;

You really should NOT declare these but take them from their header .
But perhaps you copied this bad code from the man page. :-)
Laurent Menase
Honored Contributor

Re: language and scripting

yes indeed you guess well , I took the skleton, without reading at it from the manpage.
here is the full example tested on
hpux & debian 5 ia64
- I fixed the test I made a little quickly on -f option.
$ ./a.out -afaa bb -c aa bb cc -o 1 2 3 4 5555 -- z t u
f= aa..bb..1
allcparms:aa
allcparms:bb
allcparms:cc
parms:1
parms:2
parms:3
parms:4
parms:5555
14 z
15 t
16 u
#include
#include
int i;
main (int argc, char *argv[])
{
int c;
int bflg, aflg=0, errflg=0;
char *t;
char *ifile,*ofile;
char *allcparms[256];
char **parms=0;
int nparms=0;
int icparms=0;
while ((c = getopt(argc, argv,
":abf:o:c:")) != -1)
switch (c) {
case 'a':
aflg++;
break;
case 'f':
ifile = optarg;
if (optind+1>argc)
errflg++;/*not enough parms with -f ( 2 parms) */
else
ofile = argv[ optind++];
break;

case 'c':
if(icparms==256)
{
errflg++; break;
}
allcparms[icparms++]=optarg;
while ( icparms<256 &&
(t=argv[optind]))
{
if (t[0] == '-' ) break;
allcparms[icparms++]=t;
optind++;
}
break;
case 'o':
argv[optind-1]=optarg;
parms=&argv[optind-1];
nparms=1;
while ((t=argv[optind]) &&
(t[0]!='-'))
{
optind++; nparms++;
}
break;

case ':':
fprintf(stderr, "Option -%c requires an argument\n", optopt);
errflg++;
break;
case '?':
fprintf(stderr, "Unrecognized option: - %c\n", optopt);
errflg++;
}
if (errflg) {
fprintf(stderr, "usage: . . . ");
exit (2);
}
printf("f=%s..%s..%d\n",ifile,ofile,aflg);
for (i=0;i printf("allcparms:%s\n",allcparms[i]);
while (nparms--)
printf("parms:%s\n",parms++[0]);
for ( ; optind < argc; optind++)
printf("%d %s\n",optind,argv[optind]);
}