code question

K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:
Richard Heathfield said:
argv[0] is guaranteed *either* to represent the program name or to be
NULL (and argc to be 0), and the scanning sequence works fine whichever
of these is the case.
[...]

argv[0] is also allowed to point to an empty string if the program
name is not available.

In which case the "scanning sequence" still works just fine.
Yes.
But the requirement that the string pointed to by argv[0][0]

ITYM argv[0].

D'oh!
 
R

Richard

Default User said:
I'll freely admit that I still read through the threads, even though I
have Bill killfiled. Indeed, there's sometimes a useful nugget. Each
will have to make a decision on how to approach it.

That's nice of you Brian. I'm sure we all appreciate the "go ahead" from
such a c.l.c luminary as yourself.

You need to try and get a decent news reader. If you killfile Bill
surely you have no desire to read his questions or the replies? Or are
you hunting for "off topicality"?
 
L

lovecreatesbea...

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 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 ?

#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;

}

The error check upon strtod is missed four times freely.
 
L

lovecreatesbea...

(e-mail address removed) said:



Then insert it

Yeah, how about this:

$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main (int argc, char *argv[])
{
double d;
char *end;

for (; *++argv; ){
errno = 0;
d = strtod(*argv, &end);
if (errno){
perror(*argv);
continue;
}
if (d == 0 && *argv == end){
fprintf(stderr, "%s: Cant be converted\n",
*argv);
continue;
}
fprintf(stdout, "%f\n", d);
}
return EXIT_SUCCESS;
}
$
$ make && ./a.out 11
gcc -Wall -W -g -pedantic -ansi -c -o a.o a.c
a.c:5: warning: unused parameter ‘argc’
gcc a.o -o a.out
11.000000
$ make && ./a.out aa
make: `a.out' is up to date.
aa: Cant be converted
$ make && ./a.out
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.99
make: `a.out' is up to date.
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999.99:
Numerical result out of range
$
 
B

Barry Schwarz

(e-mail address removed) said:



Then insert it

Yeah, how about this:

$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main (int argc, char *argv[])
{
double d;
char *end;

for (; *++argv; ){
errno = 0;
d = strtod(*argv, &end);
if (errno){
perror(*argv);
continue;
}
if (d == 0 && *argv == end){

If *argv == end, does it matter what d is?

This doesn't handle the situation where the input is "12xyz". You
really want to check the *end == '\0'.
 
L

lovecreatesbea...

Yeah, how about this:
$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main (int argc, char *argv[])
{
       double d;
       char *end;
       for (; *++argv; ){
               errno = 0;
               d = strtod(*argv, &end);
               if (errno){
                       perror(*argv);
                       continue;
               }
               if (d == 0 && *argv == end){

If *argv == end, does it matter what d is?

This doesn't handle the situation where the input is "12xyz".  You
really want to check the *end == '\0'.

Thank you for also pointed out this in my other post before. I add an
additional check same as before to let input like "12 " pass
through.

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

int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;

while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){
fprintf(stderr, "%s: Cant be converted\n",
*a);
continue;
}
while (*e){
if (!isspace(*e))
break;
e++;
}
if (!*e)
fprintf(stdout, "%f, %s\n\n", d, *a);
}
return EXIT_SUCCESS;
}
 
L

lovecreatesbea...

(e-mail address removed) said:
<snip>
The error check upon strtod is missed four times freely.
Then insert it
Yeah, how about this:
$ cat a.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main (int argc, char *argv[])
{
       double d;
       char *end;
       for (; *++argv; ){
               errno = 0;
               d = strtod(*argv, &end);
               if (errno){
                       perror(*argv);
                       continue;
               }
               if (d == 0 && *argv == end){
If *argv == end, does it matter what d is?
This doesn't handle the situation where the input is "12xyz".  You
really want to check the *end == '\0'.

Thank you for also pointed out this in my other post before. I add an
additional check same as before to let input like "12   " pass
through.



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

int main (int argc, char *argv[])
{
        double d;
        char **a = argv, *e;

        while (*++a){
                errno = 0;
                d = strtod(*a, &e);
                if (errno){
                        perror(*a);
                        continue;
                }
                if (d == 0 && *a == e){
                        fprintf(stderr, "%s: Cant be converted\n",
*a);
                        continue;
                }
                while (*e){
                        if (!isspace(*e))
                                break;
                        e++;
                }
                if (!*e)
                        fprintf(stdout, "%f, %s\n\n", d, *a);
        }
        return EXIT_SUCCESS;



}

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

int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;

while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){
fprintf(stderr, "%s: Cant be converted\n",
*a);
continue;
}
while (*e)
if (!isspace(*e++))
break;
if (*e){
fprintf(stderr, "%s: Invalid format\n", *a);
continue;
}
fprintf(stdout, "%f, %s\n\n", d, *a);
}
return EXIT_SUCCESS;
}
 
L

lovecreatesbea...

On Sep 23, 11:57 am, "(e-mail address removed)"
....



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

int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;

while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){
fprintf(stderr, "%s: Cant be converted\n",
*a);
continue;
}
while (*e)
if (!isspace(*e++))
break;

Sorry, the while loop needs to be changed back.

while (*e){
if (!isspace(*e))
break;
e++;
}
 
B

Ben Bacarisse

Sorry, the while loop needs to be changed back.

while (*e){
if (!isspace(*e))
break;
e++;
}

A detail (I've not looked at the rest): C's logical operators allw
this to be safely written with no if and no break:

while (*e && isspace(*e))
e++;
 
L

lovecreatesbeauty

A detail (I've not looked at the rest):  C's logical operators allw
this to be safely written with no if and no break:

  while (*e && isspace(*e))
      e++;

Yes, it's better.

- thanks
 
B

Barry Schwarz

On Mon, 22 Sep 2008 22:38:35 -0700 (PDT),

snip 100 lines of obsolete code

Please trim your posts.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;

while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){

The expression d==0 is still unnecessary.
fprintf(stderr, "%s: Cant be converted\n",
*a);
continue;
}
while (*e)
if (!isspace(*e++))
break;
if (*e){
fprintf(stderr, "%s: Invalid format\n", *a);
continue;
}

Why do you consider input of 12xy to be "better" (or even different)
than input of xy12?
 
L

lovecreatesbeauty

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;
while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){

The expression d==0 is still unnecessary.

The documents (the Standard, manpages) say:

If no conversion is performed, zero is returned and the value of
nptr
is stored in the location referenced by endptr.

So I checked those two.
Why do you consider input of 12xy to be "better" (or even different)
than input of xy12?

But my code issues error messages on both inputs already.

strtod can accept "12xyz" and "12 xyz" and return (double)12. Can I
also accept these inputs in some of my code?
 
C

Chris Dollin

Ben said:
A detail (I've not looked at the rest): C's logical operators allw
this to be safely written with no if and no break:

while (*e && isspace(*e))
e++;

Assuming isspace(0) is false:

while (isspace( *e )) e += 1;

(layout, braces, and increment-style to taste.)

[I was /sure/ that isspace(0) was false, but a quick skim doesn't
find me enough answers to be compelling. Anyone else have the
necessary clues?]
 
B

Ben Bacarisse

Chris Dollin said:
Ben said:
A detail (I've not looked at the rest): C's logical operators allw
this to be safely written with no if and no break:

while (*e && isspace(*e))
e++;

Assuming isspace(0) is false:

while (isspace( *e )) e += 1;

(layout, braces, and increment-style to taste.)

[I was /sure/ that isspace(0) was false, but a quick skim doesn't
find me enough answers to be compelling. Anyone else have the
necessary clues?]

I left it as a general pattern rather than going the whole hog.

I am pretty sure that isspace(0) is false because, to be true, it
would have to be "one of a locale-specific set of characters for which
isalnum is false" and I don't think any of these locale-specific
characters can also be in the basic execution character set (which
includes the null character).
 
B

Barry Schwarz

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main (int argc, char *argv[])
{
double d;
char **a = argv, *e;
while (*++a){
errno = 0;
d = strtod(*a, &e);
if (errno){
perror(*a);
continue;
}
if (d == 0 && *a == e){

The expression d==0 is still unnecessary.

The documents (the Standard, manpages) say:

If no conversion is performed, zero is returned and the value of
nptr
is stored in the location referenced by endptr.

So I checked those two.

If *a ==e, d must be 0. If d !=0, then *a == e must be false also.
The fact that zero is returned is just a simple way to guarantee that
the behavior is not undefined (as happens with ato.. functions).

Put another way, if d==0, you still must check *a and e. If d == 0 is
falser, then *a == e is also guaranteed to be false. The check on d
provides no additional information.
But my code issues error messages on both inputs already.

strtod can accept "12xyz" and "12 xyz" and return (double)12. Can I
also accept these inputs in some of my code?

You can do whatever you want with 12xy but, in my opinion, I don't
see why you would want to accept it as 12.0. A malformed input is
malformed whether the error is on the first or the last character or
any in between.
 

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

No members online now.

Forum statistics

Threads
473,955
Messages
2,570,117
Members
46,705
Latest member
v_darius

Latest Threads

Top