Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > How to use input arguments?

Reply
Thread Tools

How to use input arguments?

 
 
MM
Guest
Posts: n/a
 
      07-10-2003
Hi there,

How can I change my code (below) so that I use an "input argument" to
specify the file name of the input file? For example, if I compile the code
and that the application then gets the name "splitdata", then I want to be
able to call my application with something like this (datafile.txt will then
be the name of the input file):

splitdata datafile.txt

In the code as I have it now, the name of the input file is specified in
line 13:

char tname[] = "Example.txt";

So, I want to skip this "hard coded" name specification. (The length of the
input file name is not known.)

Thanks in advance,

MM

================================================== ===
=== Code, including line numbers (without line numbers is below this one)
===
================================================== ===

1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4:
5: #define DATASTART "\\Data:"
6: #define BLOCKSTART "Time"
7:
8: int main()
9: {
10: FILE *fh, *fp, *fq;
11: char hname[] = "header.dat"; // name of header output file
12: char fname[6+2+4+1]; // name of data block output files,
dblockNN.dat
13: char tname[] = "Example.txt"; // name of input file to split
14: char buf[1001]; // max line length is 1000 characters
15: char numdb[] = "NumDataBlocks=";
16: int i = 0;
17:
18: // open input file for reading
19: if((fq=fopen(tname, "r")) == 0) {
20: perror(tname);
21: exit(EXIT_FAILURE);
22: }
23:
24: // open header output file
25: if((fh=fopen(hname, "w")) == 0) {
26: perror(fname);
27: exit(EXIT_FAILURE);
28: }
29:
30: // print data to header file
31: // if start of data segment is found then close header file
32: while(fgets(buf, sizeof buf, fq) != 0) {
33: if(strncmp(DATASTART, buf, 6) == 0) {
34: fclose(fh);
35: break;
36: }
37: fputs(buf, fh);
38: }
39:
40: // write data block output files
41: while(fgets(buf, sizeof buf, fq) != 0) {
42: // lines starting with '#' and blank lines are skipped
43: if(buf[0] == '#' || buf[0] == '\n')
44: continue;
45:
46: // write each block to a separate file
47: if(strncmp(BLOCKSTART, buf, 4) == 0) {
48: if(i > 0)
49: fclose(fp);
50: sprintf(fname, "dblock%02d.dat", ++i);
51: if((fp=fopen(fname, "w")) == 0) {
52: perror(fname);
53: exit(EXIT_FAILURE);
54: }
55: }
56: fputs(buf, fp);
57: }
58:
59: // close files
60: fclose(fp);
61: fclose(fq);
62:
63: // open header output file again and print the number of data blocks
found last in the file
64: if((fh=fopen(hname, "a")) == 0) {
65: perror(fname);
66: exit(EXIT_FAILURE);
67: }
68: sprintf(numdb, "%s%d%s", numdb, i, "\n");
69: fputs(numdb, fh);
70: fclose(fh);
71:
72: return 0;
73: }

=========================
=== Code without line numbers ===
=========================

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

#define DATASTART "\\Data:"
#define BLOCKSTART "Time"

int main()
{
FILE *fh, *fp, *fq;
char hname[] = "header.dat"; // name of header output file
char fname[6+2+4+1]; // name of data block output files,
dblockNN.dat
char tname[] = "Example.txt"; // name of input file to split
char buf[1001]; // max line length is 1000 characters
char numdb[] = "NumDataBlocks=";
int i = 0;

// open input file for reading
if((fq=fopen(tname, "r")) == 0) {
perror(tname);
exit(EXIT_FAILURE);
}

// open header output file
if((fh=fopen(hname, "w")) == 0) {
perror(fname);
exit(EXIT_FAILURE);
}

// print data to header file
// if start of data segment is found then close header file
while(fgets(buf, sizeof buf, fq) != 0) {
if(strncmp(DATASTART, buf, 6) == 0) {
fclose(fh);
break;
}
fputs(buf, fh);
}

// write data block output files
while(fgets(buf, sizeof buf, fq) != 0) {
// lines starting with '#' and blank lines are skipped
if(buf[0] == '#' || buf[0] == '\n')
continue;

// write each block to a separate file
if(strncmp(BLOCKSTART, buf, 4) == 0) {
if(i > 0)
fclose(fp);
sprintf(fname, "dblock%02d.dat", ++i);
if((fp=fopen(fname, "w")) == 0) {
perror(fname);
exit(EXIT_FAILURE);
}
}
fputs(buf, fp);
}

// close files
fclose(fp);
fclose(fq);

// open header output file again and print the number of data blocks
found last in the file
if((fh=fopen(hname, "a")) == 0) {
perror(fname);
exit(EXIT_FAILURE);
}
sprintf(numdb, "%s%d%s", numdb, i, "\n");
fputs(numdb, fh);
fclose(fh);

return 0;
}



 
Reply With Quote
 
 
 
 
Derk Gwen
Guest
Posts: n/a
 
      07-10-2003
# splitdata datafile.txt
#
# In the code as I have it now, the name of the input file is specified in
# line 13:
#
# char tname[] = "Example.txt";
#
# So, I want to skip this "hard coded" name specification. (The length of the
# input file name is not known.)

# 8: int main()

int main(int argc,char **argv) {...}

On systems that provide a command line interface, if you call the program with
'splitdata datafile.txt', usually it will set
argc = 2
argv[0] = "splitdata"
argv[1] = "datafile.txt"
argv[2] = 0

So you can do something like
char *tname = argc>=2 ? argv[1] : "Example.txt";

--
Derk Gwen http://derkgwen.250free.com/html/index.html
GERBILS
GERBILS
GERBILS
 
Reply With Quote
 
 
 
 
MM
Guest
Posts: n/a
 
      07-10-2003

"Derk Gwen" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> int main(int argc,char **argv) {...}
>
> On systems that provide a command line interface, if you call the program

with
> 'splitdata datafile.txt', usually it will set
> argc = 2
> argv[0] = "splitdata"
> argv[1] = "datafile.txt"
> argv[2] = 0
>
> So you can do something like
> char *tname = argc>=2 ? argv[1] : "Example.txt";
>


Yes, that works just fine! Many thanks for the help.

MM



 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      07-10-2003
"MM" <(E-Mail Removed)> wrote:

> How can I change my code (below) so that I use an "input argument" to
> specify the file name of the input file? For example, if I compile the code
> and that the application then gets the name "splitdata", then I want to be
> able to call my application with something like this (datafile.txt will then
> be the name of the input file):
>
> splitdata datafile.txt


That's called "command line arguments" in C, not "input arguments". To
use them, you define main() as

int main(int argc, char argv**)

and read your C book for a complete explanation of these arguments. In a
nutshell, though:

- argc contains the number of arguments plus one.
- If argc>0, then argv[0] contains the name of the program (though not
necessarily in a format that's useful to you, especially if you need
directory information).
- If argc>1, then argv[1] through argv[argc-1] are the command line
parameters.
- argv[argc] is a null pointer.

Richard
 
Reply With Quote
 
MM
Guest
Posts: n/a
 
      07-10-2003

"David Rubin" <(E-Mail Removed)> wrote in message
news:mdcPa.23369$(E-Mail Removed)...
> MM wrote:
>
> [snip]
> > int main()
> > {

> [snip]
> > char numdb[] = "NumDataBlocks=";

> [snip]
> > sprintf(numdb, "%s%d%s", numdb, i, "\n");

>
> This yields undefined behavior since you're trying to write more bytes

than
> you've allocated for numdb.
>
> /david
>


Ok, then is this a better way to do it?

[snip]
char numdb[4+2+1+1];
[snip]
sprintf(numdb, "%s%02d%s", "NDB=", i, "\n");

Also, maybe you have a nice way to (platform independently!) remove/delete a
file in C?
Using for example
system("del filename.txt");
doesn't work, of course, since "del" is not OK in UNIX...

Thanks again, David!

MM



 
Reply With Quote
 
Finny Merrill
Guest
Posts: n/a
 
      07-10-2003
"MM" <(E-Mail Removed)> wrote in
news:e5ePa.1075$(E-Mail Removed):

> Ok, then is this a better way to do it?
>
> [snip]
> char numdb[4+2+1+1];
> [snip]
> sprintf(numdb, "%s%02d%s", "NDB=", i, "\n");
>


Probably.

> Also, maybe you have a nice way to (platform independently!)
> remove/delete a file in C?
> Using for example
> system("del filename.txt");
> doesn't work, of course, since "del" is not OK in UNIX...
>


remove()

 
Reply With Quote
 
Mark McIntyre
Guest
Posts: n/a
 
      07-10-2003
On Thu, 10 Jul 2003 15:44:43 +0200, in comp.lang.c , "MM"
<(E-Mail Removed)> wrote:

>
>"David Rubin" <(E-Mail Removed)> wrote in message
>news:mdcPa.23369$(E-Mail Removed)...
>> MM wrote:
>>
>> [snip]
>> > int main()
>> > {

>> [snip]
>> > char numdb[] = "NumDataBlocks=";

>> [snip]
>> > sprintf(numdb, "%s%d%s", numdb, i, "\n");

>>
>> This yields undefined behavior since you're trying to write more bytes than
>> you've allocated for numdb.

>
>Ok, then is this a better way to do it?


make numdb big enough (malloc sounds like a useful method), and don't
copy it into itself which ISTR is also undefined behaviour.

bigenough = strlen("NumDataBlocks=") + aslongas_i_could_be +2);
char* numdb = malloc(bigenough);
sprintf(numdb, "NumDataBlocks=%d\n", i);


>Also, maybe you have a nice way to (platform independently!) remove/delete a
>file in C?


remove();

RTFM !!

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
 
Reply With Quote
 
Dave Thompson
Guest
Posts: n/a
 
      07-15-2003
On Thu, 10 Jul 2003 15:44:43 +0200, "MM" <(E-Mail Removed)> wrote:

>
> "David Rubin" <(E-Mail Removed)> wrote in message
> news:mdcPa.23369$(E-Mail Removed)...
> > MM wrote:
> > [snip]
> > > char numdb[] = "NumDataBlocks=";

> > [snip]
> > > sprintf(numdb, "%s%d%s", numdb, i, "\n");

> >
> > This yields undefined behavior since you're trying to write more bytes

> than
> > you've allocated for numdb.
> >

Plus the (total) overlap, as noted elsethread.

> Ok, then is this a better way to do it?
>
> [snip]
> char numdb[4+2+1+1];
> [snip]
> sprintf(numdb, "%s%02d%s", "NDB=", i, "\n");
>

As long as the value of i fits in two digits this is valid; if it is
larger, *printf will expand the field, and for sprintf overflow.
Using snprintf as of C99, or in many C89s as an extension possibly
under a variant name like _snprintf, you can prevent overflow and UB,
but (instead) get incomplete output you must check for and deal with.

If the string NDB is constant, it is simpler and IMO preferable to
include it in the format string:
snprintf (numdb, sizeof numdb, "NDB=%02d\n", i);

and if the string varies I would consider something like:
char numdb[sizeof("NDB=") -1 +2+1+1] = "NDB=";
...
snprintf (numdb+4, 2+1+1, "%02d\n", i);

In either case, the %02d forces a _minimum_ two digits; if you don't
need this, and your format would be unambiguous and legible without,
%d is sufficient and simpler.

But, in your original code, the only thing you do with this output is
write it to a file. You could accomplish that with fprintf and not
need to worry about ensuring or checking that your line buffer is (at
least) the right size; output files are as large as necessary, at
least up to platform limits you probably cannot exceed anyway.

- David.Thompson1 at worldnet.att.net
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
can I use scanf to get input (some times user enters input sometimes not, just hit keyboard)? santa19992000@yahoo.com C Programming 4 09-09-2005 03:38 AM
Which is faster in ASIC: 2-input AND gate or a 2-input multiplexer Weng Tianxiang VHDL 12 08-11-2005 10:50 AM
hide the input box or change the color of input box in html ashutosh Java 3 06-16-2005 02:21 PM
Input Drops With An Empty Input Queue Spiz Cisco 12 05-18-2005 05:28 PM



Advertisments