|  | Exercise 7-1 |  | |
| | | mdh |  |
| Posted: Wed Sep 03, 2008 3:34 am Post subject: Exercise 7-1 |  |
I am not sure how relevant to C this is, but here goes. The exercise is to write a simple program "upper" that is invoked by this name. The program itself is pretty easy...even for me. 
#include <stdio.h> #include <ctype.h> #include <string.h>
int main (int argc, const char * argv[]) { int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/ upper")==0) while ( (c = getchar() ) != EOF) putchar(toupper(c)); else putchar(tolower(c)); return 0; }
<<<<<<
But, my question is this? When I type "/.....upper" immediately followed by an argument, the program does not work. If I type "/...upper" RETURN, then enter the arguments, it works. Any reason? I have asked on Xcode forum, but no answer yet? If this is OT, then I apologize. |
| |
| | | Keith Thompson |  |
| Posted: Wed Sep 03, 2008 3:34 am Post subject: Re: Exercise 7-1 |  |
| |  | |
mdh <mdeh@comcast.net> writes:
| Quote: | I am not sure how relevant to C this is, but here goes. The exercise is to write a simple program "upper" that is invoked by this name. The program itself is pretty easy...even for me. :-)
#include <stdio.h #include <ctype.h #include <string.h
int main (int argc, const char * argv[]) { int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/ upper")==0) while ( (c = getchar() ) != EOF) putchar(toupper(c)); else putchar(tolower(c)); return 0; }
But, my question is this? When I type "/.....upper" immediately followed by an argument, the program does not work. If I type "/...upper" RETURN, then enter the arguments, it works. Any reason? I have asked on Xcode forum, but no answer yet? If this is OT, then I apologize.
|
Having the program silently do nothing if argv[0] doesn't have a specific value is odd, but if that's what you want it to do, that's ok.
Your indentation is inconsistent and doesn't correspond either to the actual structure of your code or to the intended structure of your code.
Here's your program after it's been filtered through "indent -kr" (and after I manually joined the split line):
#include <stdio.h> #include <ctype.h> #include <string.h>
int main(int argc, const char *argv[]) { int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/upper") == 0) while ((c = getchar()) != EOF) putchar(toupper(c)); else putchar(tolower(c)); return 0; }
This should be enough to tell you what the problem is. It's also a good argument for using braces for all structured statements, whether they're required or not. For example, I always write:
if (condition) { statement; }
rather than
if (condition) statement;
It makes this kind of error slightly more difficult to make.
-- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
| |
| | | mdh |  |
| Posted: Wed Sep 03, 2008 4:19 am Post subject: Re: Exercise 7-1 |  |
| |  | |
On Sep 2, 8:53 pm, Keith Thompson <ks...@mib.org> wrote:
| Quote: | mdh <m...@comcast.net> writes: I am not sure how relevant to C this is, but here goes. .
Your indentation is inconsistent and doesn't correspond either to the actual structure of your code or to the intended structure of your code.
|
Sorry about the formatting.I will have to figure that out sometime.
| Quote: | Here's your program after it's been filtered through "indent -kr" (and after I manually joined the split line):
#include <stdio.h #include <ctype.h #include <string.h
int main(int argc, const char *argv[]) { int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/upper") == 0) while ((c = getchar()) != EOF) putchar(toupper(c)); else putchar(tolower(c)); return 0;
}
This should be enough to tell you what the problem is.
|
The solution, except for the omission in error of a second "while ((c = getchar()) != EOF)" is from Tondo and Gimpel. I think it is really simple to illustrate the issue that K&R are trying to make, instead of making it bullet proof?
while ((c = getchar()) != EOF){ putchar(toupper(c)); } else { while ((c = getchar()) != EOF) putchar(tolower(c)); }
<<<<<
But, have I missed something. Is that the reason one needs a 2 step invocation of this program? |
| |
| | | Ron Ford |  |
| Posted: Wed Sep 03, 2008 5:07 am Post subject: Re: Exercise 7-1 |  |
On Tue, 2 Sep 2008 22:52:15 -0700 (PDT), vippstar@gmail.com posted:
| Quote: | On Sep 3, 8:48 am, vipps...@gmail.com wrote:
snip
int main(void) {
That should've been int argc, char **argv, heh.
|
What a revelation. -- Wealth - any income that is at least one hundred dollars more a year than the income of one's wife's sister's husband. 6 H. L. Mencken |
| |
| | | Keith Thompson |  |
| Posted: Wed Sep 03, 2008 5:35 am Post subject: Re: Exercise 7-1 |  |
| |  | |
mdh <mdeh@comcast.net> writes:
| Quote: | On Sep 2, 8:53 pm, Keith Thompson <ks...@mib.org> wrote: mdh <m...@comcast.net> writes: I am not sure how relevant to C this is, but here goes. .
Your indentation is inconsistent and doesn't correspond either to the actual structure of your code or to the intended structure of your code.
Sorry about the formatting.I will have to figure that out sometime.
Here's your program after it's been filtered through "indent -kr" (and after I manually joined the split line):
#include <stdio.h #include <ctype.h #include <string.h
int main(int argc, const char *argv[]) { int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/upper") == 0) while ((c = getchar()) != EOF) putchar(toupper(c)); else putchar(tolower(c)); return 0;
}
This should be enough to tell you what the problem is.
The solution, except for the omission in error of a second "while ((c = getchar()) != EOF)" is from Tondo and Gimpel.
|
That would be "The C Answer Book". If you're going to cite books other than K&R, please be specific; I had to look that up.
| Quote: | I think it is really simple to illustrate the issue that K&R are trying to make, instead of making it bullet proof?
while ((c = getchar()) != EOF){ putchar(toupper(c)); } else { while ((c = getchar()) != EOF) putchar(tolower(c)); }
But, have I missed something. Is that the reason one needs a 2 step invocation of this program?
|
(Does the subject "Exercise 7-1" refer to K&R? My copy isn't handy.)
I'm afraid I can't tell from your response whether you understood my point or not. In the code you've marked with ">>>>>" and "<<<<<", you have an "else" with no corresponding "if". If that's a fragment of Tondo and Gimpel's solution, it's a poorly chosen fragment.
If I understand correct, the program is supposed to convert its input to upper case if it's invoked as "upper", and to lower case otherwise.
The problem is that, due to the way you've structured the code, if it's invoked as "upper" (or rather as "/Users/.../upper") it uses a while loop to read each character from stdin, otherwise it reads only a single character.
There are two obvious ways to do what you're trying to do.
In pseudo-code, with structure shown only by indentation, you can do either:
if my name is "upper" for each input character print that character in upper case else for each input character print that character in lower case
or:
for each input character if my name is "upper" print that character in upper case else print that character in lower case
What you've done is an incorrect mixture of the two approaches.
-- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
| |
| | | Guest |  |
| Posted: Wed Sep 03, 2008 5:48 am Post subject: Re: Exercise 7-1 |  |
| |  | |
On Sep 3, 6:34 am, mdh <m...@comcast.net> wrote:
| Quote: | I am not sure how relevant to C this is, but here goes.
|
It's a C exercise from a C book, how more relevant can it be?
| Quote: | The exercise is to write a simple program "upper" that is invoked by this name. The program itself is pretty easy...even for me. 
|
You seem to be having problems with it though...
| Quote: | #include <stdio.h #include <ctype.h #include <string.h
int main (int argc, const char * argv[]) {
|
argv is char *argv[] or char **argv, etc. Drop `const'.
| Quote: | int c; if (strcmp(argv[0], "/Users/m/Desktop/upper/build/Release/ upper")==0)
|
argv[argc] is always NULL. argc may be 0.
| Quote: | while ( (c = getchar() ) != EOF) putchar(toupper(c)); else putchar(tolower(c));
|
`else' is reached if strcmp returns a non-zero value. `c' is not initialized, thus you are invoking undefined behavior when you use its value.
| Quote: | return 0;
}
But, my question is this? When I type "/.....upper" immediately followed by an argument, the program does not work.
|
Because there are several errors in your code.
| Quote: | If I type "/...upper" RETURN, then enter the arguments, it works. Any reason? I have asked on Xcode forum, but no answer yet? If this is OT, then I apologize.
|
Because you read from stdin, you don't do anything with the arguments. Here's a complete program that does what you want.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>
int main(void) { int (*f[2])(int) = { toupper, tolower }, c, i;
if(argc == 0) return EXIT_FAILURE; i = !!strcmp(argv[0], "upper"); while((c = getchar()) != EOF) putchar(f[i](c)); if(ferror(stdin)) return EXIT_FAILURE; return 0; } |
| |
| | | Guest |  |
| Posted: Wed Sep 03, 2008 5:52 am Post subject: Re: Exercise 7-1 |  |
On Sep 3, 8:48 am, vipps...@gmail.com wrote:
<snip>
That should've been int argc, char **argv, heh. |
| |
| | | Ron Ford |  |
| Posted: Wed Sep 03, 2008 7:27 am Post subject: Re: Exercise 7-1 |  |
| |  | |
On Wed, 03 Sep 2008 00:35:23 -0700, Keith Thompson posted:
| Quote: | The solution, except for the omission in error of a second "while ((c = getchar()) != EOF)" is from Tondo and Gimpel.
That would be "The C Answer Book". If you're going to cite books other than K&R, please be specific; I had to look that up.
|
I've got Tondo and Gimpel at hand. I can't imagine that it would trump Keith if the exercise were "do io in contemporary standard C."
#include <stdio.h> #include <ctype.h>
#define MAXLINE 100 #define OCTLEN 6
int main ( int vipp, ** char star) { // berkeley bracing ala dan pop int c, pos; int inc(int pos, int n);
//main control pos = 0; while((c = getchar()) != EOF) if (iscntrl(c) || c==' ' { // non-graphic or blank pos = inc(pos, OCTLEN); printf =(" \\%03o ", c); // sic
// newline ? if (c == '\n') {
pos = 0; putchar('\n');
}
}
// brace mismatch alert
else {
pos = inc( pos, 1); putchar(c);
}
return 0;
// an external function; this belongs up top
int inc(int pos, int n) { if (pos + n < MAXLINE) return pos + n; else { putchar('\n'); return n; }
}
Anyways, I like to type in the middle of the night. This is a classic
and outdated soultion. The T&C solns don't hold up together, with this
an example of monstrous msicalculation.
I don't have a C compiler online other than Richard right now.
} -- When a new source of taxation is found it never means, in practice, that the old source is abandoned. It merely means that the politicians have two ways of milking the taxpayer where they had one before. 8 H. L. Mencken |
| |
| | | Keith Thompson |  |
| Posted: Wed Sep 03, 2008 10:00 pm Post subject: Re: Exercise 7-1 |  |
| |  | |
mdh <mdeh@comcast.net> writes: [big snip]
| Quote: | Your point is taken. Let me then accept your code, but having done this, does it answer the query that I am puzzled about? And for completeness, I include, the **hopefully** full code from T&G as well. ( I have added braces as per your suggestion )
#include <stdio.h #include <ctype.h #include <string.h
int main (int argc, char * argv[]) { int c; if (strcmp(argv[0], "upper")==0){ while ( (c = getchar() ) != EOF) putchar(toupper(c)); } else { while (( c = getchar() ) != EOF) putchar(tolower(c)); } return 0; }
|
Ok, that looks reasonable, mostly. Your indentation is still inconsistent, and I'd add braces to the while statements as well as the if statements:
#include <stdio.h> #include <ctype.h> #include <string.h>
int main(int argc, char *argv[]) { int c; if (strcmp(argv[0], "upper") == 0) { while ((c = getchar()) != EOF) { putchar(toupper(c)); } } else { while ((c = getchar()) != EOF) { putchar(tolower(c)); } } return 0; }
But now I've lost track of what you were asking about.
One possible issue I can see is that argv[0], if it's non-null, points to a string that "represents the program name". The manner in which it does so may vary. For example, on a Unix-like system, it could be any of "./upper", "/some/long/path/upper", or just "upper", depending on how you invoked the program. I suggest printing the value of argv[0] to see how it's actually being set. <OT>Try both installing the program in some directory in your $PATH and invoking it by name, and typing the full path to the executable file, and see what happens.</OT>
For a simple test, you can just pick a way to invoke the program and check for whatever value of argv[0] that gives you. For more generality, you could figure out how to detect all the possible ways it could be invoked.
-- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
| |
| | | Andrew Poelstra |  |
| Posted: Wed Sep 03, 2008 10:11 pm Post subject: Re: Exercise 7-1 |  |
| |  | |
On Wed, 2008-09-03 at 17:00 -0700, Keith Thompson wrote:
| Quote: | mdh <mdeh@comcast.net> writes: [big snip]
Your point is taken. Let me then accept your code, but having done this, does it answer the query that I am puzzled about? And for completeness, I include, the **hopefully** full code from T&G as well. ( I have added braces as per your suggestion )
#include <stdio.h #include <ctype.h #include <string.h
int main (int argc, char * argv[]) { int c; if (strcmp(argv[0], "upper")==0){ while ( (c = getchar() ) != EOF) putchar(toupper(c)); } else { while (( c = getchar() ) != EOF) putchar(tolower(c)); } return 0; }
Ok, that looks reasonable, mostly. Your indentation is still inconsistent, and I'd add braces to the while statements as well as the if statements:
#include <stdio.h #include <ctype.h #include <string.h
int main(int argc, char *argv[]) { int c; if (strcmp(argv[0], "upper") == 0) { while ((c = getchar()) != EOF) { putchar(toupper(c)); } } else { while ((c = getchar()) != EOF) { putchar(tolower(c)); } } return 0; }
But now I've lost track of what you were asking about.
One possible issue I can see is that argv[0], if it's non-null, points to a string that "represents the program name". The manner in which it does so may vary. For example, on a Unix-like system, it could be any of "./upper", "/some/long/path/upper", or just "upper", depending on how you invoked the program. I suggest printing the value of argv[0] to see how it's actually being set. <OT>Try both installing the program in some directory in your $PATH and invoking it by name, and typing the full path to the executable file, and see what happens.</OT
For a simple test, you can just pick a way to invoke the program and check for whatever value of argv[0] that gives you. For more generality, you could figure out how to detect all the possible ways it could be invoked.
|
Probably he could use strstr() to check for "upper" or "lower" in the program name that way, which would be reasonably portable. |
| |
| Page 1 of 3 .:. Goto page 1, 2, 3 Next | |
|
|