code works

B

Bill Cunningham

I re-wrote this code today from what I posted yesterday and finally got
what I wanted! I had to add argc==0 to print something and exit otherwise I
was getting a seg fault.

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

int main(int argc, char **argv)
{
if (argc > 3 || argc == 1) {
puts("hexideci usage error");
exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {
long y = strtol(argv[2], NULL, 10);
printf("%x\n", y);
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);
printf("%i\n", x);
return 0;
}


Bill
 
K

Keith Thompson

Bill Cunningham said:
I re-wrote this code today from what I posted yesterday and finally got
what I wanted! I had to add argc==0 to print something and exit otherwise I
was getting a seg fault.

If you "had to add argc==0", why don't I see it in your code?
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
if (argc > 3 || argc == 1) {
puts("hexideci usage error");

Error messages should generally be printed to stderr. It would also
be good for the message to tell the user what the correct usage is.

If "hexideci" is meant to be an abbreviation of "hexadecimal", you've
misspelled it.
exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {

Look into strcmp().
long y = strtol(argv[2], NULL, 10);

By passing NULL as the second argument to strtol, you forgo the
possibility of any error checking. You could get a result of 0 if the
argument doesn't contain a number, or LONG_MIN or LONG_MAX on
underflow or overflow (you can detect the latter by checking errno).
But if you want to ignore such errors, that's ok.
printf("%x\n", y);

"%x" requires an argument of type unsigned int. y is of type long.

You might want to consider printing a "0x" prefix in front of your
hexadecimal output, just to make it clearer to the user.
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);

As above, you're not doing any error checking.
printf("%i\n", x);

"%i" requires an argument of type unsigned int. x is of type long.
return 0;
}

Assuming your program is named "hexideci", I think your intent is to
allow either
hexideci -d <decimal_number>
or
hexideci <hexadecimal_number>

You check that you have either 1 or 2 arguments, and you check whether
the first argument is "-d", but you ignore the relationship
between those checks. You want either:
1 argument, which is a hexadecimal number
or
2 arguments, of which the first is "-d"

But you allow:
2 arguments, of which the first needn't be "-d" (so the second
argument is ignored)
or
1 argument, which is "-d" (so you try to look at the second argument).

To see what happens, try this:

hexideci -d

hexideci 12 34
 
B

Barry Schwarz

I re-wrote this code today from what I posted yesterday and finally got
what I wanted! I had to add argc==0 to print something and exit otherwise I

Not only did you not have to but you obviously did not do this anyway.
was getting a seg fault.

You code is still broken. The only reason you haven't observed
another seg fault is bad luck and poor testing.
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
if (argc > 3 || argc == 1) {

What about the case where argc is 2 or 0?
puts("hexideci usage error");
exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {

You have no idea if argv[1] exists.

And you like this better than
if (strcmp(argv[1], "-d") == 0){
because?
long y = strtol(argv[2], NULL, 10);

You have no idea if argv[2] exists or if it points to a string. And
by using NULL for the second argument, you have eliminated any chance
of finding out if the string it might point to represents a decimal
number.
printf("%x\n", y);

And here you invoke undefined behavior the same as in your original
post.
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);
printf("%i\n", x);

The same problem with argv[1] again, the same lack of error checking
again, and the same undefined behavior.
return 0;
}

Why do you post if you don't take the responses seriously?
 
K

Keith Thompson

Bill Cunningham said:
I re-wrote this code today from what I posted yesterday and finally got
what I wanted! I had to add argc==0 to print something and exit otherwise I
was getting a seg fault.

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

int main(int argc, char **argv)
{
if (argc > 3 || argc == 1) {
puts("hexideci usage error");
exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {
long y = strtol(argv[2], NULL, 10);
printf("%x\n", y);
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);
printf("%i\n", x);
return 0;
}

I've already posted a critique of your code. I have another more
general comment to make.

It rarely makes sense to use constant values when indexing into argv.
For example, for this program you want the user to type either
hexideci -d 123
or
hexedeci 123
(123 is just an example). So, is it argv[1] or argv[2] that points to
the string "123"? You don't know until you've looked at the first
argument.

So the best way to handle this is to use a variable (say, "int i;") to
step through argv one element at a time, from 1 to argc-1.

Rather than looking at argv[1] or argv[2], you should be looking at
argv, where i is your current position.
 
B

Bill Cunningham

Barry Schwarz said:
Not only did you not have to but you obviously did not do this anyway.

Sorry misquote. that should've been argc==1.
was getting a seg fault.

You code is still broken. The only reason you haven't observed
another seg fault is bad luck and poor testing.
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
if (argc > 3 || argc == 1) {

What about the case where argc is 2 or 0?
puts("hexideci usage error");
exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {

You have no idea if argv[1] exists.

And you like this better than
if (strcmp(argv[1], "-d") == 0){
because?
long y = strtol(argv[2], NULL, 10);

You have no idea if argv[2] exists or if it points to a string. And
by using NULL for the second argument, you have eliminated any chance
of finding out if the string it might point to represents a decimal
number.

I am not sure what to do about that.
printf("%x\n", y);

And here you invoke undefined behavior the same as in your original
post.
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);
printf("%i\n", x);

The same problem with argv[1] again, the same lack of error checking
again, and the same undefined behavior.
return 0;
}

Why do you post if you don't take the responses seriously?

Barry have you ever read a paragraph of text kandr2 or anything else and
had no idea what you read? Do you forget entire conversations that occurred
10 minutes before? This isn't an excuse but it's what I have to put up with
all the time. I still trudge along. I am receiving a lot of good help here
and do appreciate it. Sometimes I receive contradictory feedback though (not
in this case) and have to make a decision on my own. I received A's in high
school for spelling and now have a serious problem remembering how to spell
even the most simple words. I have to save emails and reread them several
times to get the core of what I'm told. Maybe I should give up. That would
be the easy thing. But I have set a goal and it I'm afraid will be a long
term goal to learn C.

Bill
 
K

Keith Thompson

Bill Cunningham said:
No hexideci is the name of the utility.

Ok, you can call it whatever you like. But I assume the name comes
from the English word "hexadecimal", so "hexadeci" would be a more
logical name. But that's not a C issue.

[...]
When converting to decimal I want hexideci to take letters. But of
course not when converting to hex.

Sure, if you call strtol() with a base of 10, it will accept digits
0-9; if you call it with a base of 16, it will accept digits 0-9 and
a-f (or A-F). But in either case, if you give it "xyz", it will fail.
You don't check for this kind of failure.

[...]
I wan't able to find a function to make the conversion from int or
unisgned to long. I remeber being faced with this when the code was written.

You don't need a function to convert from one arithmetic type to
another. In most cases, the conversion is done implicitly when you
assign it. Or, in some cases, you might want to use a cast.

[...]
 
B

Bill Cunningham

Keith Thompson said:
If you "had to add argc==0", why don't I see it in your code?


Error messages should generally be printed to stderr. It would also
be good for the message to tell the user what the correct usage is.

If "hexideci" is meant to be an abbreviation of "hexadecimal", you've
misspelled it.
No hexideci is the name of the utility.
>> exit(EXIT_FAILURE);
}
if (argv[1][0] == '-' && argv[1][1] == 'd' && argv[1][2] == '\0') {

Look into strcmp().
long y = strtol(argv[2], NULL, 10);

By passing NULL as the second argument to strtol, you forgo the
possibility of any error checking.

I've never passed anything but NULL as a second parameter. I will look
more into strtol which I rarely use.

You could get a result of 0 if the
argument doesn't contain a number, or LONG_MIN or LONG_MAX on
underflow or overflow (you can detect the latter by checking errno).
But if you want to ignore such errors, that's ok.

When converting to decimal I want hexideci to take letters. But of
course not when converting to hex.
"%x" requires an argument of type unsigned int. y is of type long.

It looks like maybe I need to recheck my specifiers to printf.
You might want to consider printing a "0x" prefix in front of your
hexadecimal output, just to make it clearer to the user.
exit(EXIT_SUCCESS);
}
long x = strtol(argv[1], NULL, 16);

As above, you're not doing any error checking.
printf("%i\n", x);

"%i" requires an argument of type unsigned int. x is of type long.

I wan't able to find a function to make the conversion from int or
unisgned to long. I remeber being faced with this when the code was written.
Assuming your program is named "hexideci", I think your intent is to
allow either
hexideci -d <decimal_number>
or
hexideci <hexadecimal_number>

You check that you have either 1 or 2 arguments, and you check whether
the first argument is "-d", but you ignore the relationship
between those checks. You want either:
1 argument, which is a hexadecimal number
or
2 arguments, of which the first is "-d"

But you allow:
2 arguments, of which the first needn't be "-d" (so the second
argument is ignored)
or
1 argument, which is "-d" (so you try to look at the second argument).

To see what happens, try this:

hexideci -d

hexideci 12 34

Oh my I need to clean this up. Do you know of any functions that convert
long to unsigned it?

Bill
 
C

CBFalconer

Bill said:
.... snip ...

Oh my I need to clean this up. Do you know of any functions that
convert long to unsigned it?

unsigned int ui;
long lng;

lng = VALUE; /* defined elsewhere */
ui = lng; /* converts, using unsigned overflow rules */
 
B

Bill Cunningham

I've already posted a critique of your code. I have another more
general comment to make.

It rarely makes sense to use constant values when indexing into argv.
For example, for this program you want the user to type either
hexideci -d 123
or
hexedeci 123
(123 is just an example). So, is it argv[1] or argv[2] that points to
the string "123"? You don't know until you've looked at the first
argument.

So the best way to handle this is to use a variable (say, "int i;") to
step through argv one element at a time, from 1 to argc-1.

Rather than looking at argv[1] or argv[2], you should be looking at
argv, where i is your current position.

Sounds like a for loop is needed there.

Bill
 
B

Barry Schwarz

Barry have you ever read a paragraph of text kandr2 or anything else and
had no idea what you read? Do you forget entire conversations that occurred
10 minutes before? This isn't an excuse but it's what I have to put up with
all the time. I still trudge along. I am receiving a lot of good help here
and do appreciate it. Sometimes I receive contradictory feedback though (not
in this case) and have to make a decision on my own. I received A's in high
school for spelling and now have a serious problem remembering how to spell
even the most simple words. I have to save emails and reread them several
times to get the core of what I'm told. Maybe I should give up. That would
be the easy thing. But I have set a goal and it I'm afraid will be a long
term goal to learn C.

In view of the number of mistakes I've posted here, it is obvious
there is a lot in K&R2 that I don't understand as well as I thought I
did. I also walk into rooms and wonder why I went there. However,
when I use printf, I do attempt to find the correct format for the
type of variable I want to print. I don't just assume everything is
an int.

I am quite willing to accept that you have a condition which makes
learning C difficult for you. But

1 - You post code which appears to have been cut and pasted from your
source files. Yet you refuse to do the same for error messages and
instead posting phrases of the form "something like ..." Since you
know how to cut and paste, this is due to either laziness or trolling,
not your condition.

2 - In spite of repeated advice to the contrary, you continue to guess
when dealing with something new. It would actually be less work for
you and us if you would simply ask for ideas how to accomplish the
task du jour. If you can't specify what you want to do, you can't
write code to do it.

Others may add to this list but the bottom line is that haphazardly
slapping code together does not qualify as making a serious effort.
 
B

Bill Cunningham

[snip]
1 - You post code which appears to have been cut and pasted from your
source files.

Yes.

Yet you refuse to do the same for error messages and
instead posting phrases of the form "something like ..."

Sometimes I have trouble redirecting bash's stderr to a text file. So
then I try to remember what the error is to not much good evidently.

Since you
know how to cut and paste, this is due to either laziness or trolling,
not your condition.

2 - In spite of repeated advice to the contrary, you continue to guess
when dealing with something new. It would actually be less work for
you and us if you would simply ask for ideas how to accomplish the
task du jour.

Some aren't williing to just hand me the answers and I understand where
they're coming from. But simply sitting down and reading kandr2 doesn't seem
to help much at times.

If you can't specify what you want to do, you can't
 

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


Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top