code question

B

Bill Cunningham

I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);
if ((fp = fopen(argv[4], "a")) == NULL) {
puts("fopen error");
exit(-1);
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
puts("fclose error");
exit(-1);
}
return 0;
}

If the program is run with no arguments I get a seg fault. If it is run with
4, no problem. If it is run with less than four (that includes argv[0]) then
the program doesn't want to run right. How would I be able to use this
program with say one or two argvs ?

Bill
 
I

Ian Collins

Bill said:
I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);
if ((fp = fopen(argv[4], "a")) == NULL) {
puts("fopen error");
exit(-1);
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
puts("fclose error");
exit(-1);
}
return 0;
}

If the program is run with no arguments I get a seg fault. If it is run with
4, no problem. If it is run with less than four (that includes argv[0]) then
the program doesn't want to run right. How would I be able to use this
program with say one or two argvs ?
Your requirements are incomplete.

What should happen if there are less than four arguments? Should a file
be opened? Should an error message be output?

Without these details, there a number of conflicting possible solutions.
 
B

Bill Cunningham

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

#define DEFAULT_FILE_NAME "foo.bar"

int main(int argc, char *argv[])
{
double x = 0.0, y = 0.0, a = 0.0, b = 0.0;
const char *filename = DEFAULT_FILE_NAME;

FILE *fp = NULL;
if(argc > 1)
{
x = strtod(argv[1], NULL);
}
if(argc > 2)
{
y = strtod(argv[2], NULL);
}
if(argc > 3)
{
a = strtod(argv[3], NULL);
}
if(argc > 4)
{
b = strtod(argv[4], NULL);
filename = argv[4];
}
if ((fp = fopen(filename, "a")) == NULL) {
puts("fopen error");
exit(EXIT_FAILURE);
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
puts("fclose error");
exit(EXIT_FAILURE);
}
return 0;
}

Thanks Richard I know I can always count on you. I wondered about argc
and its uses.

Bill
 
M

Martin Ambuhl

Bill said:
I have this code I would like to clean up.

Well, it certainly needs cleaning up, so you have got this part right.
See below.
If the program is run with no arguments I get a seg fault. If it is run with
4, no problem. If it is run with less than four (that includes argv[0]) then
the program doesn't want to run right. How would I be able to use this
program with say one or two argvs ?

There are many ways to hand differing numbers of arguments to a program.
Here is one way to start on yours, except that making your filename
argv[4] makes the exercise pointless.

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

int main(int argc, char *argv[])
{
double x = 0, y = 0, a = 0, b = 0;
FILE *fp;
switch (argc) {
case 5:
b = strtod(argv[4], NULL);
case 4:
a = strtod(argv[3], NULL);
case 3:
y = strtod(argv[2], NULL);
case 2:
x = strtod(argv[1], NULL);
case 1:
break;
default:
fputs("I don't know how to handle that many arguments.\n",
stderr);
exit(EXIT_FAILURE);
}
if (argc < 5) {
fprintf(stderr, "%s",
"I just wasted some time assigning values to x, y, a, &"
"b\nsince the fourth argument (argv[4]) is needed for a"
" filename\nand you didn't supply it.\n");
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[4] /* this is nonsense, of course, if
argv < 5 */ , "a")) == NULL) {
fputs("fopen error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
fputs("fclose error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
return 0;
}
 
B

Bill Cunningham

Martin Ambuhl said:
Well, it certainly needs cleaning up, so you have got this part right. See
below.


There are many ways to hand differing numbers of arguments to a program.
Here is one way to start on yours, except that making your filename
argv[4] makes the exercise pointless.

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

int main(int argc, char *argv[])
{
double x = 0, y = 0, a = 0, b = 0;
FILE *fp;

Great. Switch. I've never used it before.
switch (argc) {
case 5:
b = strtod(argv[4], NULL);
case 4:
a = strtod(argv[3], NULL);
case 3:
y = strtod(argv[2], NULL);
case 2:
x = strtod(argv[1], NULL);
case 1:
break;
default:
fputs("I don't know how to handle that many arguments.\n",
stderr);

What's going on here? Is the default for more than the number of argv's
that the program calls for ? Why is there a break and not just default?
exit(EXIT_FAILURE);
}
if (argc < 5) {
fprintf(stderr, "%s",
"I just wasted some time assigning values to x, y, a, &"
"b\nsince the fourth argument (argv[4]) is needed for a"
" filename\nand you didn't supply it.\n");
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[4] /* this is nonsense, of course, if
argv < 5 */ , "a")) == NULL) {
fputs("fopen error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
fputs("fclose error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
return 0;
}

If exit(-1) is non -portable. Which I was afraid of what about exit(1)?
Or does the standard only allow exit(EXIT_FAILURE);

Bill
 
B

Bill Cunningham

Your requirements are incomplete.

What should happen if there are less than four arguments? Should a file
be opened? Should an error message be output?

Without these details, there a number of conflicting possible solutions.
Yes if there are less than four arguments a file should be opened. There
must be a way to only write the fprintf stuff once though.

Bill
 
I

Ian Collins

Bill said:
Yes if there are less than four arguments a file should be opened. There
must be a way to only write the fprintf stuff once though.
The how about

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

int main( int argc, char **argv )
{
double data[4] = {0.0};

if ( argc > 5 ) {
puts("Too many arguments");
exit(EXIT_FAILURE);
}

unsigned n = 1;

while ( n < argc ) {
data[n-1] = strtod(argv[n], NULL);
++n;
}

FILE *fp = fopen(argv[n-1], "a");

if ( fp == NULL ) {
puts("fopen error");
exit(EXIT_FAILURE);
}

fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", data[0], data[1], data[2],
data[3]);

if (fclose(fp) == EOF ) {
puts("fclose error");
exit(EXIT_FAILURE);
}

return 0;
}
 
A

Andrew Poelstra

Thanks Richard I know I can always count on you. I wondered about argc
and its uses.

In addition to argc, argv is also NULL terminated (IIRC!), so
you can loop through it without needed argc to find out when
to stop.

while(*argv)
{
process(*argv);
++argv;
}
 
A

Andrew Poelstra

Martin Ambuhl said:
Well, it certainly needs cleaning up, so you have got this part right. See
below.


There are many ways to hand differing numbers of arguments to a program.
Here is one way to start on yours, except that making your filename
argv[4] makes the exercise pointless.

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

int main(int argc, char *argv[])
{
double x = 0, y = 0, a = 0, b = 0;
FILE *fp;

Great. Switch. I've never used it before.
switch (argc) {
case 5:
b = strtod(argv[4], NULL);
case 4:
a = strtod(argv[3], NULL);
case 3:
y = strtod(argv[2], NULL);
case 2:
x = strtod(argv[1], NULL);
case 1:
break;
default:
fputs("I don't know how to handle that many arguments.\n",
stderr);

What's going on here? Is the default for more than the number of argv's
that the program calls for ? Why is there a break and not just default?

Without a break, each case statement falls through to the
next one. This code relies on this behavior: if argc is 5,
the case statements for argc = 5, 4, 3, 2, 1 are reached,
in that order.

Without the break, it would also fall through to the
default: code, and would then /always/ output an
error message.
exit(EXIT_FAILURE);
}
if (argc < 5) {
fprintf(stderr, "%s",
"I just wasted some time assigning values to x, y, a, &"
"b\nsince the fourth argument (argv[4]) is needed for a"
" filename\nand you didn't supply it.\n");
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[4] /* this is nonsense, of course, if
argv < 5 */ , "a")) == NULL) {
fputs("fopen error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
fputs("fclose error\n", stderr);
exit(EXIT_FAILURE); /* fixed non-portable 'exit(-1)' */
}
return 0;
}

If exit(-1) is non -portable. Which I was afraid of what about exit(1)?
Or does the standard only allow exit(EXIT_FAILURE);

The standard allows EXIT_FAILURE and EXIT_SUCCESS, which are
both defined in <stdlib.h>, or just 0.
 
R

Richard

Bill Cunningham said:
I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);
if ((fp = fopen(argv[4], "a")) == NULL) {
puts("fopen error");
exit(-1);
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
puts("fclose error");
exit(-1);
}
return 0;
}

If the program is run with no arguments I get a seg fault. If it is
run with

Did you try it with a debugger? No? Then give up. Not that you need one
to spot the error. 10/10 for persistence. O/10 for originality. These
posts are getting a tad tiresome.
4, no problem. If it is run with less than four (that includes argv[0]) then
the program doesn't want to run right. How would I be able to use this
program with say one or two argvs ?

Bill

--
 
R

Richard

Bill Cunningham said:
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_FILE_NAME "foo.bar"

int main(int argc, char *argv[])
{
double x = 0.0, y = 0.0, a = 0.0, b = 0.0;
const char *filename = DEFAULT_FILE_NAME;

FILE *fp = NULL;
if(argc > 1)
{
x = strtod(argv[1], NULL);
}
if(argc > 2)
{
y = strtod(argv[2], NULL);
}
if(argc > 3)
{
a = strtod(argv[3], NULL);
}
if(argc > 4)
{
b = strtod(argv[4], NULL);
filename = argv[4];
}
if ((fp = fopen(filename, "a")) == NULL) {
puts("fopen error");
exit(EXIT_FAILURE);
}
fprintf(fp, "%.2f\t%.2f\t%.2f\t%.2f\n", x, y, a, b);
if (fclose(fp) == EOF) {
puts("fclose error");
exit(EXIT_FAILURE);
}
return 0;
}

Thanks Richard I know I can always count on you. I wondered about argc
and its uses.

Bill

You wondered about argc?

You never thought to

(a) see where it crashed using a debugger?
(b) examine the values of argc and argv in a debugger?

or

(c) read up about them in your copy of K&R2? Heathfield must really need
some soul cleansing if he responded to you with a total clean up with
no admonitions.
 
B

Bill Cunningham

Did you try it with a debugger? No? Then give up. Not that you need one
to spot the error. 10/10 for persistence. O/10 for originality. These
posts are getting a tad tiresome.

So are yours Richard Good God so are yours.

Have a nice life..
 
B

Bill Cunningham

Someone pointed out to me Richard that an answer to a question I raised
about bitwise operators was on page 49 or kandr2. I read, and re-read, and
re-read page 49 about 3 times and strained to keep my focus on reading and
the text. The question was why is the unary operator ~ shown like this:

x~34;
and not x=x~34;

Is the question indeed answered on that page?

Bill
 
B

Barry Schwarz

I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);

So the fourth command line argument should be a number.
if ((fp = fopen(argv[4], "a")) == NULL) {

At the same time, it should be a file name.

That doesn't strike you as slightly odd?
 
I

Ian Collins

Barry said:
I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);

So the fourth command line argument should be a number.
if ((fp = fopen(argv[4], "a")) == NULL) {

At the same time, it should be a file name.

That doesn't strike you as slightly odd?
Most things "Bill" posts are at least slightly odd...
 
R

Richard

Bill Cunningham said:
So are yours Richard Good God so are yours.

Have a nice life..

So, did you use the debugger to show you were it was segment faulting?
No? Then give up. You are totally useless as a programmer and will never
make it. Why? Because you refuse to use the tools there to help you do a
job I offer this advise to you to save you a lot of hurt and pain in the
future. If it's any consolation I could never be a high wire trapeze
artist no matter how much I practised.

And while I am at it, please stop spamming the application development
groups telling them you are trying to write a printer driver when you
could not even tell them the type of printer you are using.
 
B

Bill Cunningham

Ian Collins said:
The how about

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

int main( int argc, char **argv )
{
double data[4] = {0.0};

if ( argc > 5 ) {
puts("Too many arguments");
exit(EXIT_FAILURE);
}

unsigned n = 1;

while ( n < argc ) {
data[n-1] = strtod(argv[n], NULL);
++n;

[snip]

What's above is a bit of a different method than I would think of. Is that n
minus 1 in the brackets?
Why set n to 1?

Bill
 
R

Richard

Barry Schwarz said:
I have this code I would like to clean up.

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

int main(int argc, char *argv[])
{
double x, y, a, b;
FILE *fp;
x = strtod(argv[1], NULL);
y = strtod(argv[2], NULL);
a = strtod(argv[3], NULL);
b = strtod(argv[4], NULL);

So the fourth command line argument should be a number.
if ((fp = fopen(argv[4], "a")) == NULL) {

At the same time, it should be a file name.

That doesn't strike you as slightly odd?

Not it doesn't because he never reads his own code. He refused to use a
debugger or debugging methods to see his data in action. In short he is
either a troll or the worst programmer of all time. And I mean *ALL*
time.
 
I

Ian Collins

Bill said:
Ian Collins said:
The how about

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

int main( int argc, char **argv )
{
double data[4] = {0.0};

if ( argc > 5 ) {
puts("Too many arguments");
exit(EXIT_FAILURE);
}

unsigned n = 1;

while ( n < argc ) {
data[n-1] = strtod(argv[n], NULL);
++n;

[snip]

What's above is a bit of a different method than I would think of. Is that n
minus 1 in the brackets?
Why set n to 1?
What's argv[1]?
 
R

Richard

Bill Cunningham said:
Ian Collins said:
The how about

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

int main( int argc, char **argv )
{
double data[4] = {0.0};

if ( argc > 5 ) {
puts("Too many arguments");
exit(EXIT_FAILURE);
}

unsigned n = 1;

while ( n < argc ) {
data[n-1] = strtod(argv[n], NULL);
++n;

[snip]

What's above is a bit of a different method than I would think of. Is that n
minus 1 in the brackets?
Why set n to 1?

Bill

To confuse you I assume. Its not a very C way of doing it IMO. Not
tested for ISO C correctness or whether it even works but this is much
clearer if you (and you must as a c programmer) understand for
loops. You should get the idea.

for(int n=0;n<argc;n++)
data[n] = strtod(argv[n+1], NULL);
 

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

Similar Threads

code 50
sh?tpile of errors 82
seg fault 76
How to fix this code? 1
code 34
pow type problem 6
URGENT 1
How can I view / open / render / display a pdf file with c code? 0

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top