help needed with filnames as command line arguments

D

David Bernier

I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

I haven't done any C programming with command line arguments so far.

I'm familiar with fopen, ascii mode, binary mode. What I'm doing
now is specifying the filenames in the source code.
So I give different names to each source code file
and recompile each time.

The data in the files is signed ints and I read from files in ascii mode,
not binary.

Also, I'd be glad to have some references about
command line argument programming or simple examples.

I have K&R, Harbison and Steele's ``C A Reference Manual" and
I know where to find the FAQ for comp.lang.c

thanks

Dvid Bernier
 
J

Jonas

David Bernier said:
I'd like to pass on the command line two filenames.

Also, I'd be glad to have some references about
command line argument programming or simple examples.

One specification for main() is:
int main(int argc, char *argv[])

With that, you can receive command line args, argv[0] to argv[argc - 1]. Try
this for instance:
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
puts(argv);
return 0;
}

Hope it helps.
 
D

Duncan Bayne

David Bernier said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

I haven't done any C programming with command line arguments so far.

#include <stdio.h>
#include <stdlib.h>

/* this will print out all command line arguments, then exit */
int main(int argc, char[] *argv)
{
int n;

for (n = 0; n < argc; n ++)
{
printf("argument %d: %s\n", n, argv[n]);
}

return 0;
}

The above code is untested & uncompiled. YMMV :)
 
R

Rama Krishna

In your source code, define main with this prototype.

main(int args, char *argv[])
{
int i;
printf("executable file : %s", argv[0]);
printf("Number of arguments is : %d", args);
for(i=1;i<args;i++)
{
printf("Argument %d is : %s\n", i, argv);
}
}

Hope this helps.

Regards,
Rama Krishna.
 
C

Craigb

David Bernier said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

/* -------- start cut here ------------- */
#include<stdio.h>

int printargstuff(int aa, char *bb[]);


int main(int argc, char *argv[]) //NOTE - passing in command line argc/argv
{
printargstuff(argc, *argv[0]);
return(0);
}

int printargstuff(int aa, char *bb[])
{
int i1 = 1;
printf("%d argument(s) passed to the command \n", aa-1);
if (bb[1] != NULL)
{
while (i1 < aa)
{
printf ("%s, \n",bb[i1++]);
}
}
return(0);
}
/* --------------end cut here ------------------------*/
hope it helps.
 
I

Irrwahn Grausewitz

David Bernier said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

I haven't done any C programming with command line arguments so far.

#include <stdio.h>
#include <stdlib.h>

/* this will print out all command line arguments, then exit */
int main(int argc, char[] *argv)
Parse error. Make it:

int main(int argc, char *argv[] )
or
int main(int argc, char **argv )
{
int n;

for (n = 0; n < argc; n ++)
{
printf("argument %d: %s\n", n, argv[n]);
}

return 0;
}

The above code is untested & uncompiled. YMMV :)

The corrected version is. :)

Regards
 
I

Irrwahn Grausewitz

(e-mail address removed) (Rama Krishna) wrote:

First off, you forgot about this:

#include said:
In your source code, define main with this prototype.
main(int args, char *argv[])

No. define main as:

int main(int args, char *argv[])

or, alternatively:

int main(int args, char **argv)
{
int i;
printf("executable file : %s", argv[0]);

It's not required by the standard for an implementation to provide the
name of the executable in argv[0] (IOW argv[0][0] may equal 0).
Moreover, if argc equals 0, argv[0] is required to be a NULL pointer
(Generally, argv[argc] is required to be a NULL pointer).
printf("Number of arguments is : %d", args);

Note that this count includes argv[0] as well.
for(i=1;i<args;i++)
{
printf("Argument %d is : %s\n", i, argv);
}


return 0;

BTW, please don't top-post, thank you.

Regards
 
I

Irrwahn Grausewitz

If the follwing compiles at all, it'll most certainly not work as
intended.
/* -------- start cut here ------------- */
#include<stdio.h>

int printargstuff(int aa, char *bb[]);


int main(int argc, char *argv[]) //NOTE - passing in command line argc/argv
{
printargstuff(argc, *argv[0]);

WARNING: passing arg 2 of `printargstuff' makes pointer from integer
without a cast

make it:

printargstuff(argc, argv);
return(0);
}

int printargstuff(int aa, char *bb[])
{
int i1 = 1;
printf("%d argument(s) passed to the command \n", aa-1);
if (bb[1] != NULL)
{
while (i1 < aa)
{
printf ("%s, \n",bb[i1++]);
}
}
return(0);
}
/* --------------end cut here ------------------------*/
hope it helps.

<meta rant>
I am impressed by the fact that only one out of four replies (so far)
contained correct code. Please, test your code before you post it.
Thank you.
</meta rant>

Regards
 
D

David Bernier

Craigb said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2


#include<stdio.h>

int printargstuff(int aa, char *bb[]);


int main(int argc, char *argv[]) //NOTE - passing in command line argc/argv
{
printargstuff(argc, *argv[0]); //DB: line 9: Warning issued about this line, see below...
return(0);
}

int printargstuff(int aa, char *bb[])
{
int i1 = 1;
printf("%d argument(s) passed to the command \n", aa-1);
if (bb[1] != NULL)
{
while (i1 < aa)
{
printf ("%s, \n",bb[i1++]);
}
}
return(0);
}
It didn't quite work. I got a warning about this line:

printargstuff(argc, *argv[0]); here it is:

``line 9: warning: improper pointer/integer combination: arg #2 "

Here's some sample output:

% ./a.out hello there
2 argument(s) passed to the command
Bus Error (core dumped)

thanks for your help,

David Bernier
 
D

David Bernier

Duncan said:
#include <stdio.h>
#include <stdlib.h>

/* this will print out all command line arguments, then exit */
[...]

Following the reply by Irrwahn Grausewitz, I edited your code, and I'm
happy that the
edited version compiles and does what it's supposed to do.

thanks again,

David Bernier
------------------------------------

Edited code follows:
----------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

/* this will print out all command line arguments, then exit */

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

for (n = 0; n < argc; n ++)
{
printf("argument %d: %s\n", n, argv[n]);
}

return 0;
}
-------------------------------------------------------------------------------------------------
 
I

Irrwahn Grausewitz

David Bernier said:
/*** NOTE: I added #include <string.h> here ***/

You don't use anything defined in string.h, so why include it?
int printargstuff(int aa, char *bb[]);

int main(int argc, char *argv[]) //NOTE - passing in command line argc/argv
{
printargstuff(argc, *argv[0]); //DB: line 9: Warning issued about this line, see below...

Make it match the prototype:

printargstuff(argc, argv);

It didn't quite work. I got a warning about this line:

printargstuff(argc, *argv[0]); here it is:

See above.

<snip>

Regards
 
D

Dan Pop

In said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

I haven't done any C programming with command line arguments so far.

I'm familiar with fopen, ascii mode, binary mode. What I'm doing
now is specifying the filenames in the source code.
So I give different names to each source code file
and recompile each time.

The data in the files is signed ints and I read from files in ascii mode,
not binary.

Also, I'd be glad to have some references about
command line argument programming or simple examples.

I have K&R, Harbison and Steele's ``C A Reference Manual" and
I know where to find the FAQ for comp.lang.c

What's the point in having C books if you can't be bothered to read them?
K&R explains the issue in great detail.

You also need to know that you have to read the FAQ *before* posting.
But your question is far too basic to be worth addressing in the FAQ:
any good tutorial C book will describe the parameters of the main
function and their usage.

#include <stdio.h>

int main(int argc, char **argv)
{
while (*argv) puts(*argv++);
return 0;
}

Couldn't be any easier.

Dan
 
C

Craigb

I am impressed by the fact that only one out of four replies (so far)
contained correct code. Please, test your code before you post it.
Thank you.
</meta rant>

Regards

Tested... *still* works fine for me, however.. appreciate the
feedback. Tested on Bloodshed gcc and Cygwins gcc also in case you're
wondering.
/cb
 
I

Irrwahn Grausewitz

Tested... *still* works fine for me, however.. appreciate the
feedback. Tested on Bloodshed gcc and Cygwins gcc also in case you're
wondering.

Really? Let's see...

Output generated by MingW32 (gcc 3.2, the version that comes with
Bloodshed DevCpp, so probably the same you use):

[...]
gcc.exe "D:\Temp\CraigB_1.c" -o "D:\Temp\CraigB_1.exe" -W -Wall
-std=c99 -O3 -I[...] -L[...]
[...]
D:/Temp/CraigB_1.c:8: warning: passing arg 2 of `printargstuff'
makes pointer from integer without a cast [1]

OK, now let's review your code:
....
003 int printargstuff(int aa, char *bb[]);
....
006 int main(int argc, char *argv[])
007 {
008 printargstuff(argc, *argv[0]);
....

The second argument of printargstuff() has to be a
pointer-to-pointer-to-character. You pass *argc[0] to it,
which is a character. Now please explain how this is
supposed to work without invoking undefined behaviour.


[1] You most probably didn't set your warning level to a
suitable amount. Warnings usually _are_ errors!

Regards
 
S

Simon Biber

David Bernier said:
I'd like to pass on the command line two filenames.

As for example:

my_executable filename_1 filename_2

I haven't done any C programming with command line arguments so far.

I'm familiar with fopen, ascii mode, binary mode. What I'm doing
now is specifying the filenames in the source code.
So I give different names to each source code file
and recompile each time.

The data in the files is signed ints and I read from files in ascii mode,
not binary.

I think you mean text mode. There is no "ascii mode" in C.

C:\docs\prog\c>type dbernier.c
#include <stdio.h>

int main(int argc, char **argv)
{
int i;
for(i = 1; i < argc; i++)
{
int value = 0;
FILE *fp = fopen(argv, "r");
if(fp)
{
if(fscanf(fp, "%d", &value) == 1)
{
printf("%s: %d\n", argv, value);
}
fclose(fp);
}
}
return 0;
}

C:\docs\prog\c>gcc -std=c99 -pedantic -Wall -W -O2 dbernier.c -o dbernier

C:\docs\prog\c>dbernier *
42.txt: 69
comb.txt: 0
fig.out: 2147483647
input.raw: 6
lotto.diff: 1781
tmp2: 9

These files just happened to have a number at the beginning.
 
C

CBFalconer

Simon Biber wrote (minisculy edited):
.... snip ...

#include <stdio.h>
int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
int value = 0;
FILE *fp = fopen(argv, "r");
if (fp) {
if (fscanf(fp, "%d", &value) == 1)) {
printf("%s: %d\n", argv, value);
}
fclose(fp);
}
}
return 0;
}


While C has, for some time, allowed this sort of declaration
within a block, I see very little use for it. The code is much
more flexible if broken into a separate routine. The only cost is
(possibly) the time to call and return, which would be vanishingly
small here compared with the actual routine action. Thus I would
recommend:

#include <stdio.h>
static void tryfile(const char *fn)
{
int value;
FILE *fp;
if (fp = fopen(fn, "r"))
if (fscanf(fp, "%d", &value) == 1) {
printf("%s: %d\n", fn, value);
}
fclose(fp);
}
}

int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
tryfile(argv);
}
return 0;
}

which, at least to me, is clearer in that each routine has one
simple responsibility. With C99 you can also have all the
benefits of the single routine method by using the inline
directive. YMMV.

With this organization it is easier (to me) to see that one should
worry about the action of fopen on an empty string, and trivial to
avoid it. We can also easily see that initialization during
declaration is not needed anywhere.

There is no need to agree with me :) but at least you can
evaluate my preference after seeing the reasons.
 
I

Irrwahn Grausewitz

CBFalconer said:
Simon Biber wrote (minisculy edited):
... snip ...

#include <stdio.h>
int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
int value = 0;
FILE *fp = fopen(argv, "r");
if (fp) {
if (fscanf(fp, "%d", &value) == 1)) {
printf("%s: %d\n", argv, value);
}
fclose(fp);
}
}
return 0;
}


While C has, for some time, allowed this sort of declaration
within a block, I see very little use for it.


Alas, I sometimes use initialization within a block in switch
statements, e.g. where a helper variable is needed in only one
special case and I want to have it declared where it's used:

/*...*/
int foo, bar;

switch( whatever )
{
case CASE_X:
/* do something */
break;

case CASE_SWAP:
{
int tmp = foo;
foo = bar;
bar = tmp;
}
break;

case CASE_Y:
/* do something else */
break;

default:
/* perform default action */
}


Regards
 
C

CBFalconer

Irrwahn said:
.... snip ...

Alas, I sometimes use initialization within a block in switch
statements, e.g. where a helper variable is needed in only one
special case and I want to have it declared where it's used:

You snipped my point, which was that such usage often indicates
the need to repartition the code.
 
I

Irrwahn Grausewitz

CBFalconer said:
You snipped my point, which was that such usage often indicates
the need to repartition the code.

I snipped it because your point remains valid and I support it, but in
special cases I ignore it, when I don't want to repartition the code.

Admittedly my actual example was a rather silly one. A more realistic
example would've been a message handler routine, but I didn't want to
clutter my post with ugly OT windowish code.

Regards
 
C

Craigb

The second argument of printargstuff() has to be a
pointer-to-pointer-to-character. You pass *argc[0] to it,
which is a character. Now please explain how this is
supposed to work without invoking undefined behaviour.


[1] You most probably didn't set your warning level to a
suitable amount. Warnings usually _are_ errors!

Regards

There you go, now I learned something!..
I re-did it in the ide and of course found what you are saying. I
won't go too far off topic, but the reason I was in the threads at all
was to find out exactly that sort of thing, so no-bad from my point of
view. Of course now I'll be doing searches on your login to find out
what other tips I can glean.
/cb.
 

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
473,777
Messages
2,569,604
Members
45,229
Latest member
GloryAngul

Latest Threads

Top