detabbing again

B

Barry Schwarz

"Frank" <[email protected]> ha scritto nel messaggio
i rewrote the last code in your post with some comment

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

int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

// why not to do some test for input?
if(n<0||n>999||path==0||*path==0) return EXIT_FAILURE;
nc=strlen(path); if(nc<0||nc>999) return EXIT_FAILURE;

strlen returns a size_t which is guaranteed to be unsigned. What are
the odds it can ever be less than 0? On the other hand, you don't
consider nc equal to 0 to be a problem but I don't know of any system
which supports zero-length path names.
c =strlen(exp_suffix); if(c <0||c >999) return EXIT_FAILURE;
nc+=c;
path_exp = malloc(nc + 1);
if(!path_exp)
{fprintf(stderr, "%s: %s\n", "exptab", "malloc error");

Why bother with formats for hard coded strings?
return EXIT_FAILURE;
}
strcat(strcpy(path_exp, path), exp_suffix);
fout = fopen(path_exp, "w");
free(path_exp);
if(!fout){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__, "fopen");
return EXIT_FAILURE;
}

Your coding style makes finding the corresponding { a pain.
fin = fopen(path, "r");
if(!fin){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__, "fopen");
fclose(fout);
return EXIT_FAILURE;
}
while( (c=fgetc(fin)) != EOF )
{if(c == '\t')
{nc=n;
while(nc--)
fputc(' ', fout);
}
else fputc(c, fout);
}
c=0;
// why not see it there are problem in the files?
if( fclose(fin) ==EOF ) c=1;
if( fclose(fout)==EOF ) c=1;
return c==1?
(fprintf(stderr, "%s(%d): %s\n",
__FILE__, __LINE__,"other"),EXIT_FAILURE):
0;
}

/*test*/
#include <errno.h>
int main(int argc, char *argv[])
{long n;
char *endp;
int errnoStrtol;

if(argc != 3){fprintf(stderr, "%s: <num> <filename>\n", argv[0]);
return EXIT_FAILURE;
}
errno=0;
n=strtol(argv[1], &endp, 10);
errnoStrtol=errno;

// print some values
printf("argv1 is %ld\n" , n);
fprintf(stderr, "stderr has the following error %d\n ", errno);
printf(" errno is %d\n" , errnoStrtol);
printf(" endp is %p\n" , endp);
// printf(" endp points to %p\n" , (void*)*endp);
// have not mening: in strtol what is changed is the endp
// value, for this there is **endp, in the definition of
// strtol because for change char* endp; i have to
// pass to the function char** and so &endp
if(endp!=0)
printf(" the pointer to endp points to [%c]:[%d]\n" ,
endp[0], (int)endp[0]);
if ( // *endp!=0 || in general should be meanigless
errnoStrtol)
{perror("main"); return EXIT_FAILURE;}

return exptab( atoi(argv[1]), argv[2]);

Why convert argv again? The value is already in n.
 
B

Barry Schwarz

Frank said:





Pointer to pointer to char.


Struggling :(

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

int exptab(int n, const char *path)
{
FILE *fin, *fout;
char *path_exp, *exp_suffix = ".exp";
int c;
const int cn = n;

path_exp = malloc(strlen(path) + strlen(exp_suffix) + 1);
if (!path_exp){
fprintf(stderr, "%s: %s\n", __func__, "malloc error");
return EXIT_FAILURE;
}
strcat(strcpy(path_exp, path), exp_suffix);
fout = fopen(path_exp, "w");
free(path_exp);
if (!fout){
fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__, "fopen");
return EXIT_FAILURE;
}
fin = fopen(path, "r");
if (!fin){
fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__, "fopen");
fclose(fout);
return EXIT_FAILURE;
}
while ((c=fgetc(fin)) != EOF){
n = cn;
if (c == '\t') while (n--) fputc(' ', fout);
else fputc(c, fout);
}
fclose(fin);
fclose(fout);
return 0;

}

/*test*/
#include <errno.h>
int main(int argc, char *argv[])
{
long n;
char *endp;

if (argc != 3){
fprintf(stderr, "%s: <num> <filename>\n", argv[0]);
return -1;
}
errno = 0;
n = strtol(argv[1], &endp, 10);

// print some values
printf(" argv1 is %ld\n" , n);
fprintf(stderr, " stderr has the following error %d\n ", errno);
printf(" errno is %d\n" , errno);
printf(" endp is %p\n" , endp);

%p works better with void*. One of the more valid reasons for a cast.
printf(" endp points to %p\n" , &endp);

This is not what endp points. It happens to be the address of endp
itself and in this case the cast is not optional.
printf(" the char that the pointer to a pointer to char\
called endp points to is %d\n" , & (&endp));

The character endp points to is *endp. What you have is garbage (plus
undefined behavior).
if (*endp || errno){
perror(__func__);
return EXIT_FAILURE;
}

exptab(atoi(argv[1]), argv[2]);
return EXIT_SUCCESS;
}
 
B

Barry Schwarz

    errno = 0;
    n = strtol(argv[1], &endp, 10);
    if (endp == argv[1] || errno)
        /* there was an error */

I do not think that the doublepipe is decideable without knowing the
truth value of argv[1].

There are two possibilities: argv[1] is NULL or it is not. If it is
NULL, then the call to strtol invokes undefined behavior and your if
becomes irrelevant. If argv[1] is not NULL, the only time the left
operand will be true is if the first significant (non-white-space)
character in the string is not part of an integer.

As it stands, it will be false if argv[1] points to a string like
"123" or "2abc". Basically, the test tells you almost nothing. Your
previous test (*endp) made more sense.
 
K

Keith Thompson

Barry Schwarz said:
On Tue, 18 Aug 2009 19:10:13 -0700 (PDT), Frank


There was nothing wrong with returning -1 from exptab but there is
nothing wrong with returning EXIT_FAILURE either (except of course you
are not exiting)
[...]

Returning EXIT_FAILURE from a function that returns int is perfectly
legal, but IMHO it's poor style for a function other than main.

For one thing, the function returns either EXIT_FAILURE or 0. One
could argue that the standard guarantees EXIT_FAILURE != 0, but
I'm not entirely convinced that the guarantee is absolute.

Just as a matter of style if nothing else, EXIT_SUCCESS and
EXIT_FAILURE should generally be used only as values to return from
main or to pass to exit (or _Exit).
 
F

Frank

Barry Schwarz said:
On Tue, 18 Aug 2009 19:10:13 -0700 (PDT), Frank
There was nothing wrong with returning -1 from exptab but there is
nothing wrong with returning EXIT_FAILURE either (except of course you
are not exiting)

[...]

Returning EXIT_FAILURE from a function that returns int is perfectly
legal, but IMHO it's poor style for a function other than main.

For one thing, the function returns either EXIT_FAILURE or 0.  One
could argue that the standard guarantees EXIT_FAILURE != 0, but
I'm not entirely convinced that the guarantee is absolute.

Just as a matter of style if nothing else, EXIT_SUCCESS and
EXIT_FAILURE should generally be used only as values to return from
main or to pass to exit (or _Exit).

ok I assume you mean -1 would be better.
 
F

Frank

[OP intentionally destroying context]

Thanks for your post, io. I like your enthusiasm for precisely the
reasons that I like my enthusiasms. The second invokation of j.exe
shows behavior that is still wonky.


F:\gfortran\dan>gcc j3.c -Wall -o j.exe

F:\gfortran\dan>j 5 ot3.txt
argv1 is 5
stderr has the following error 0
errno is 0
endp is 003D2445
the pointer char endp, points to [ ]:[0]
all ok

F:\gfortran\dan>j 5t ot3.txt
argv1 is 5
stderr has the following error 0
errno is 0
endp is 003D2445
the pointer char endp, points to [t]:[116]
all ok

F:\gfortran\dan>j tja5 ot3.txt
argv1 is 0
stderr has the following error 0
errno is 0
endp is 003D2444
the pointer char endp, points to [t]:[116]
Errore nell'inserimento dell'input

F:\gfortran\dan>type j3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

if(n<0||n>999||path==0||*path==0) return EXIT_FAILURE;
nc=strlen(path); if(nc<0||nc>999) return EXIT_FAILURE;
c =strlen(exp_suffix); if(c <0||c >999) return EXIT_FAILURE;
nc+=c;
path_exp = malloc(nc + 1);
if(!path_exp)
{fprintf(stderr, "%s: %s\n", "exptab", "malloc error");
return EXIT_FAILURE;
}
strcat(strcpy(path_exp, path), exp_suffix);
fout = fopen(path_exp, "w");
free(path_exp);
if(!fout){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__,
"fopen");
return EXIT_FAILURE;
}
fin = fopen(path, "r");
if(!fin){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__,
"fopen");
fclose(fout);
return EXIT_FAILURE;
}
while( (c=fgetc(fin)) != EOF )
{if(c == '\t')
{nc=n;
while(nc--)
fputc(' ', fout);
}
else fputc(c, fout);
}
c=0;
if( fclose(fin) !=0 ) c=1;
if( fclose(fout)!=0 ) c=1;
return c==1?(fprintf(stderr, "%s(%d): %s\n",
__FILE__, __LINE__,"exptab"),EXIT_FAILURE):0;

}

/*test*/
#include <errno.h>
int main(int argc, char *argv[])
{long n;
char *endp;
int errnoStrtol;

if(argc != 3){fprintf(stderr, "%s: <num> <filename>\n", argv[0]);
return -1;
}
errno=0; endp=argv[1];
n=strtol(argv[1], &endp, 10);
errnoStrtol=errno;

// print some values
printf("argv1 is %ld\n" , n);
fprintf(stderr, "stderr has the following error %d\n ", errnoStrtol);
printf("errno is %d\n" , errnoStrtol);
printf("endp is %p\n" , (void*) endp);
// printf(" endp points to %p\n" , (void*)*endp);
// have no meaning:
// long strtol(char* s, char** whereIn_s, int base);
// strtol has need to change the value in the
// char pointer "endp" for doing that
// i have to pass to strtol the &endp (that is "char**" )
// so it(strtol()function) can change endp with the right value

if(endp!=0)
printf(" the pointer char endp, points to [%c]:[%d]\n" ,
endp[0], (int)endp[0]);
if (endp==argv[1] || // this mens that no number is get
errnoStrtol!=0 || // this means there were error of overflow
n>9999 // number n too big
){//perror("main");
printf("Errore nell'inserimento dell'input\n");
return EXIT_FAILURE;
}
return exptab( atoi(argv[1]), argv[2])==0?
(printf("all ok\n"), 0): EXIT_FAILURE;
}

// gcc j3.c -Wall -o j.exe

F:\gfortran\dan>

Are you Italian?
 
F

Frank

On Aug 19, 10:22 am, "io_x" <[email protected]> wrote:
F:\gfortran\dan>

Are you Italian?

I replaced the EXIT_FAILURES outside of main with -1 and made a couple
other changes that looked right to me


int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

I've started to read this now and like a lot of what I am seeing.
Your declarations are concise and stylish.

Seems to be behaving better:


F:\gfortran\dan>gcc j4.c -Wall -o j.exe

F:\gfortran\dan>j 5 ot3.txt
argv1 is 5
stderr has the following error 0
errno is 0
endp is 003D2445
the pointer char endp, points to [ ]:[0]
all ok

F:\gfortran\dan>j 5555555555555 ot3.txt
argv1 is 2147483647
stderr has the following error 34
errno is 34
endp is 003D2451
the pointer char endp, points to [ ]:[0]
Errore nell'inserimento dell'input

F:\gfortran\dan>j tja5 ot3.txt
argv1 is 0
stderr has the following error 0
errno is 0
endp is 003D2444
the pointer char endp, points to [t]:[116]
Errore nell'inserimento dell'input

F:\gfortran\dan>j 10005 ot3.txt
argv1 is 10005
stderr has the following error 0
errno is 0
endp is 003D2449
the pointer char endp, points to [ ]:[0]
Errore nell'inserimento dell'input

F:\gfortran\dan>type j4.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

if(n<0||n>999||path==0||*path==0) return -1;
nc=strlen(path); if(nc<=0||nc>999) return -1;
c =strlen(exp_suffix); if(c <=0||c >999) return -1;
nc+=c;
path_exp = malloc(nc + 1);
if(!path_exp)
{fprintf(stderr, "%s: %s\n", "exptab", "malloc error");
return -1;
}
strcat(strcpy(path_exp, path), exp_suffix);
fout = fopen(path_exp, "w");
free(path_exp);
if(!fout){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__,
"fopen");
return -1;
}
fin = fopen(path, "r");
if(!fin){fprintf(stderr, "%s(%d): %s\n", __FILE__, __LINE__,
"fopen");
fclose(fout);
return -1;
}
while( (c=fgetc(fin)) != EOF )
{if(c == '\t')
{nc=n;
while(nc--)
fputc(' ', fout);
}
else fputc(c, fout);
}
c=0;
if( fclose(fin) !=0 ) c=1;
if( fclose(fout)!=0 ) c=1;
return c==1?(fprintf(stderr, "%s(%d): %s\n",
__FILE__, __LINE__,"exptab"),-1):0;

}

/*test*/
#include <errno.h>
int main(int argc, char *argv[])
{long n;
char *endp;
int errnoStrtol;

if(argc != 3){fprintf(stderr, "%s: <num> <filename>\n", argv[0]);
return -1;
}
errno=0; endp=argv[1];
n=strtol(argv[1], &endp, 10);
errnoStrtol=errno;

// print some values
printf("argv1 is %ld\n" , n);
fprintf(stderr, "stderr has the following error %d\n ", errnoStrtol);
printf("errno is %d\n" , errnoStrtol);
printf("endp is %p\n" , (void*) endp);
// printf(" endp points to %p\n" , (void*)*endp);
// have no meaning:
// long strtol(char* s, char** whereIn_s, int base);
// strtol has need to change the value in the
// char pointer "endp" for doing that
// i have to pass to strtol the &endp (that is "char**" )
// so it(strtol()function) can change endp with the right value

if(endp!=0)
printf(" the pointer char endp, points to [%c]:[%d]\n" ,
endp[0], (int)endp[0]);
if (endp==argv[1] || // this mens that no number is get
errnoStrtol!=0 || // this means there were error of overflow
n>9999 // number n too big
){//perror("main");
printf("Errore nell'inserimento dell'input\n");
return EXIT_FAILURE;
}
return exptab( atoi(argv[1]), argv[2])==0?
(printf("all ok\n"), 0): EXIT_FAILURE;
}

// gcc j4.c -Wall -o j.exe

F:\gfortran\dan>
 
J

James Kuyper

Barry said:
errno = 0;
n = strtol(argv[1], &endp, 10);
if (endp == argv[1] || errno)
/* there was an error */
I do not think that the doublepipe is decideable without knowing the
truth value of argv[1].

There are two possibilities: argv[1] is NULL or it is not. If it is
NULL, then the call to strtol invokes undefined behavior and your if
becomes irrelevant. If argv[1] is not NULL, the only time the left
operand will be true is if the first significant (non-white-space)
character in the string is not part of an integer.

Setting endp==argv[1] is the method strtol(argv[1], &endp, 0) uses to
report errors of two types: "If the subject sequence is empty or does
not have the expected form ..." (7.20.1.4p7). So, for instance, If
argv[1] pointed at " Hello!", the subject sequence would be empty.

"The subject sequence is defined as the longest initial subsequence of
the input string, starting with the first non-white-space character,
that is of the expected form." (7.1.2.40p4) When the base is 0, the
longest such sequence that I can figure out that is not actually of the
expected form would be either "-" or "+"; either of those could match
the expected form if follow by a digit from '0' to '9', but not if
followed by any other character (including '\0'), strtol(argv[1], &endp,
0) should therefore set endp to argv[1], if argv[1] points at something
like "-mount".
As it stands, it will be false if argv[1] points to a string like
"123" or "2abc". Basically, the test tells you almost nothing. Your
previous test (*endp) made more sense.

strtol(argv[1], &endp, 0) will set endp to point at the terminating null
character of argv[1], thereby making *endp=='\0', only if a) the string
was empty, in which chase endp will be set to point at argv[1][0], which
will be '\0', or b) the subject sequence is of the expected form, and
extends to include the entire rest of the string, in which case endp
will be set to point at the terminating null character of that string.
That might or might not be an error, depending upon whether or not the
subject sequence represents an integer that is outside of the range that
can be represented as a long int.

Therefore, Using *endp isn't very useful.
 
J

James Kuyper

Barry said:
On Tue, 18 Aug 2009 20:35:08 -0700 (PDT), Frank


%p works better with void*. One of the more valid reasons for a cast.

"A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.39)" (6.2.5p27). The 39 at
the end of that sentence is in superscript, and refers to footnote 39:
"The same representation and alignment requirements are meant to imply
interchangeability as arguments to functions, return values from
functions, and members of unions."

Now, despite what is "meant", "same representation and alignment" does
not actually imply interchangeability, since it is possible to define an
ABI that distinguishes char* and void* without any difference in either
the representation or alignment; it could pass them in different
registers, for instance. However, as a practical matter, treating what
6.2.5p27 says as if the implication were valid or footnote 39 were
normative is one of the safest risks you can take in C programming.
 
B

Ben Bacarisse

James Kuyper said:
"A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.39)" (6.2.5p27). The 39
at the end of that sentence is in superscript, and refers to footnote
39: "The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values from
functions, and members of unions."

Now, despite what is "meant", "same representation and alignment" does
not actually imply interchangeability, since it is possible to define
an ABI that distinguishes char* and void* without any difference in
either the representation or alignment; it could pass them in
different registers, for instance. However, as a practical matter,
treating what 6.2.5p27 says as if the implication were valid or
footnote 39 were normative is one of the safest risks you can take in
C programming.

I agree, by the way, but it seems worth nothing that the code violates
a "shall" (in 7.19.6.1 p8) and one must therefore hope the no
implementation has taken that as an opportunity of do something
peculiar! In other words, even if footnote 39 is taken to be
normative, printf (et al) have further dispensation to do odd things.
 
K

Keith Thompson

Frank said:
Barry Schwarz said:
On Tue, 18 Aug 2009 19:10:13 -0700 (PDT), Frank
int exptab(int n, const char *path)
{
   FILE *fin, *fout;
   char *path_exp, *exp_suffix = ".exp";
   int c;
   const int cn = n;
   path_exp = malloc(strlen(path) + strlen(exp_suffix) + 1);
   if (!path_exp){
       fprintf(stderr, "%s: %s\n", __func__, "malloc error");
       return EXIT_FAILURE;
There was nothing wrong with returning -1 from exptab but there is
nothing wrong with returning EXIT_FAILURE either (except of course you
are not exiting)

[...]

Returning EXIT_FAILURE from a function that returns int is perfectly
legal, but IMHO it's poor style for a function other than main.

For one thing, the function returns either EXIT_FAILURE or 0.  One
could argue that the standard guarantees EXIT_FAILURE != 0, but
I'm not entirely convinced that the guarantee is absolute.

Just as a matter of style if nothing else, EXIT_SUCCESS and
EXIT_FAILURE should generally be used only as values to return from
main or to pass to exit (or _Exit).

ok I assume you mean -1 would be better.

All I really meant was that EXIT_FAILURE is unclear; I didn't express
an opinion on what would be better. But yes, 0 for success and -1 for
failure is a reasonable convention, as long as you document it.
 
K

Keith Thompson

Frank said:
I replaced the EXIT_FAILURES outside of main with -1 and made a couple
other changes that looked right to me


int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

I've started to read this now and like a lot of what I am seeing.
Your declarations are concise and stylish.
[...]

"io_x"'s coding style is extremely non-traditional, and gratuitously
difficult for experienced C programmers to read. I advise against
adopting it yourself. One could argue, I suppose, that it's in some
way better than more traditional layouts, but the purpose of code is
to communicate, primarily to human readers, secondarily to the
compiler (which doesn't care about layout).

Here's how I'd write the above:

int exptab(int n, const char *path)
{
FILE *fin;
FILE *fout;
char *path_exp;
char *exp_suffix = ".exp";
int c
int nc;

There's no point in inserting extra blanks just to make the
semicolons line up.

As Henry Spencer famously wrote in
<http://www.lysator.liu.se/c/ten-commandments.html>:

Thou shalt make thy program's purpose and structure clear to thy
fellow man by using the One True Brace Style, even if thou likest
it not, for thy creativity is better used in solving problems than
in creating beautiful new impediments to understanding.
 
K

Keith Thompson

James Kuyper said:
"A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.39)" (6.2.5p27). The 39
at the end of that sentence is in superscript, and refers to footnote
39: "The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values from
functions, and members of unions."

Now, despite what is "meant", "same representation and alignment" does
not actually imply interchangeability, since it is possible to define
an ABI that distinguishes char* and void* without any difference in
either the representation or alignment; it could pass them in
different registers, for instance. However, as a practical matter,
treating what 6.2.5p27 says as if the implication were valid or
footnote 39 were normative is one of the safest risks you can take in
C programming.

Yes, it's one of the safest risks you can take. It's also one of the
easiest to avoid. A printf call with a "%p" format and no cast should
always be suspicious. It's much simpler to add the cast than to
convince yourself that it's unnecessary.
 
P

Phil Carmody

Keith Thompson said:
Frank said:
I replaced the EXIT_FAILURES outside of main with -1 and made a couple
other changes that looked right to me


int exptab(int n, const char *path)
{FILE *fin, *fout;
char *path_exp,
*exp_suffix = ".exp";
int c, nc;

I've started to read this now and like a lot of what I am seeing.
Your declarations are concise and stylish.
[...]

"io_x"'s coding style is extremely non-traditional, and gratuitously
difficult for experienced C programmers to read. I advise against
adopting it yourself. One could argue, I suppose, that it's in some
way better than more traditional layouts, but the purpose of code is
to communicate, primarily to human readers, secondarily to the
compiler (which doesn't care about layout).

Here's how I'd write the above:

int exptab(int n, const char *path)
{
FILE *fin;
FILE *fout;
char *path_exp;
char *exp_suffix = ".exp";

I'd const that, but I'm like that.

Phil
 
K

Keith Thompson

Phil Carmody said:
I'd const that, but I'm like that.

Sure, so would I; I was just fixing the layout.

const char *exp_suffix = ".exp";

Since string literals aren't modifiable, but the language doesn't
make them const, adding the const keyword makes it easier to catch
mistaken attempts to modify the string. (The only excuse for not
using const here would be if exp_suffix might later point to some
modifiable string, but that would be ugly.)

In fact, I'd likely change the last declaration to:

const char *const exp_suffix = ".exp";

unless I had some specific need to change exp_suffix later.
 
B

Barry Schwarz

Barry Schwarz said:
errno = 0;
n = strtol(argv[1], &endp, 10);
if (endp == argv[1] || errno)
/* there was an error */

I do not think that the doublepipe is decideable without knowing the
truth value of argv[1].

There are two possibilities: argv[1] is NULL or it is not. If it is
NULL, then the call to strtol invokes undefined behavior and your if
becomes irrelevant. If argv[1] is not NULL, the only time the left
operand will be true is if the first significant (non-white-space)
character in the string is not part of an integer.
As it stands, it will be false if argv[1] points to a string like
"123" or "2abc".

"it will be false"

it is false, so no error, so the string "123" or "2abc" is get
(with the values 123 and 2 respectivament)
and i not see what it is wrong in it

The left operand evaluates to 0. strtol is not required to set errno
if the string is "2abc". So the right operand could also evaluate to
0. Therefore the test does not tell you if the user entered a "clean"
string or not and so is essentially useless.
the previos test should not get the string "13 "
because endp should point in the space char after "13"
(and it is not '\0') so *endp is different of zero
and signal one error

That is why the *endp test is better which is what a said before.
 
P

Phil Carmody

Keith Thompson said:
Sure, so would I; I was just fixing the layout.

const char *exp_suffix = ".exp";

Since string literals aren't modifiable, but the language doesn't
make them const, adding the const keyword makes it easier to catch
mistaken attempts to modify the string. (The only excuse for not
using const here would be if exp_suffix might later point to some
modifiable string, but that would be ugly.)

In fact, I'd likely change the last declaration to:

const char *const exp_suffix = ".exp";

unless I had some specific need to change exp_suffix later.

This issuette cropped up whilst I was attempting to bodge together
some code last night in an indecisive daze. Which do you prefer:
const char *const exp_suffix = ".exp";
const char exp_suffix[] = ".exp";

Phil
 
K

Keith Thompson

Phil Carmody said:
In fact, I'd likely change the last declaration to:

const char *const exp_suffix = ".exp";

unless I had some specific need to change exp_suffix later.

This issuette cropped up whilst I was attempting to bodge together
some code last night in an indecisive daze. Which do you prefer:
const char *const exp_suffix = ".exp";
const char exp_suffix[] = ".exp";

The latter, but not by a wide margin. It has several minor
advantages. Unlike the first declaration, the second doesn't
create a separate pointer object. ``sizeof exp_suffix'' is useful.
And it's simpler.
 
P

Phil Carmody

Keith Thompson said:
Phil Carmody said:
In fact, I'd likely change the last declaration to:

const char *const exp_suffix = ".exp";

unless I had some specific need to change exp_suffix later.

This issuette cropped up whilst I was attempting to bodge together
some code last night in an indecisive daze. Which do you prefer:
const char *const exp_suffix = ".exp";
const char exp_suffix[] = ".exp";

The latter, but not by a wide margin. It has several minor
advantages. Unlike the first declaration, the second doesn't
create a separate pointer object. ``sizeof exp_suffix'' is useful.
And it's simpler.

We are aligned. I also like the fact that the chars' address is
really constant, rather than just declared so with a label which
can be cast away in anger. (Which is part of the separate pointer
issue.)

Phil
 
F

Frank

Barry said:
On Tue, 18 Aug 2009 21:42:12 -0700 (PDT), Frank
    errno = 0;
    n = strtol(argv[1], &endp, 10);
    if (endp == argv[1] || errno)
        /* there was an error */
I do not think that the doublepipe is decideable without knowing the
truth value of argv[1].
There are two possibilities: argv[1] is NULL or it is not.  If it is
NULL, then the call to strtol invokes undefined behavior and your if
becomes irrelevant.  If argv[1] is not NULL, the only time the left
operand will be true is if the first significant (non-white-space)
character in the string is not part of an integer.  

Setting endp==argv[1] is the method strtol(argv[1], &endp, 0) uses to
report errors of two types: "If the subject sequence is empty or does
not have the expected form ..." (7.20.1.4p7). So, for instance, If
argv[1] pointed at "   Hello!", the subject sequence would be empty.

"The subject sequence is defined as the longest initial subsequence of
the input string, starting with the first non-white-space character,
that is of the expected form." (7.1.2.40p4) When the base is 0, the
longest such sequence that I can figure out that is not actually of the
expected form would be either "-" or "+"; either of those could match
the expected form if follow by a digit from '0' to '9', but not if
followed by any other character (including '\0'), strtol(argv[1], &endp,
0) should therefore set endp to argv[1], if argv[1] points at something
like "-mount".
As it stands, it will be false if argv[1] points to a string like
"123" or "2abc".  Basically, the test tells you almost nothing.  Your
previous test (*endp) made more sense.

strtol(argv[1], &endp, 0) will set endp to point at the terminating null
character of argv[1], thereby making *endp=='\0', only if a) the string
was empty, in which chase endp will be set to point at argv[1][0], which
will be '\0', or b) the subject sequence is of the expected form, and
extends to include the entire rest of the string, in which case endp
will be set to point at the terminating null character of that string.
That might or might not be an error, depending upon whether or not the
subject sequence represents an integer that is outside of the range that
can be represented as a long int.

Therefore, Using *endp isn't very useful.

Thanks for your reply, james.
 

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

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top