Exercise 7-1 
September 3rd, 2008, 03:35 AM
| | | 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. | 
September 3rd, 2008, 03:55 AM
| | | Re: Exercise 7-1
mdh <mdeh@comcast.netwrites: 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" | 
September 3rd, 2008, 04:25 AM
| | | Re: Exercise 7-1
On Sep 2, 8:53*pm, Keith Thompson <ks...@mib.orgwrote: Quote:
mdh <m...@comcast.netwrites: Quote:
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? | 
September 3rd, 2008, 05:55 AM
| | | Re: Exercise 7-1
On Sep 3, 6:34 am, mdh <m...@comcast.netwrote: 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;
} | 
September 3rd, 2008, 05:55 AM
| | | Re: Exercise 7-1
On Sep 3, 8:48 am, vipps...@gmail.com wrote:
<snip> That should've been int argc, char **argv, heh. | 
September 3rd, 2008, 07:45 AM
| | | Re: Exercise 7-1
mdh <mdeh@comcast.netwrites: Quote:
On Sep 2, 8:53*pm, Keith Thompson <ks...@mib.orgwrote: Quote:
>mdh <m...@comcast.netwrites: Quote:
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.
| 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" | 
September 3rd, 2008, 09:35 AM
| | | Re: Exercise 7-1
On Wed, 03 Sep 2008 00:35:23 -0700, Keith Thompson posted: Quote: 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 | 
September 3rd, 2008, 11:45 PM
| | | Re: Exercise 7-1
On Sep 3, 12:35*am, Keith Thompson <ks...@mib.orgwrote: Quote:
mdh <m...@comcast.netwrites:> 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.
|
Sorry about that. I assumed that Tondo and Gimpel and K&R were like a
"horse and carriage" and that everyone just knew about them.(Their
book is promoed on the back cover of my K&R) I have previously
alluded to them using the acronym "T&G" and it had not been
questioned...just goes to show where assumptions will get you! It
really has helped me up to now getting through those exercises. Quote:
>
>
(Does the subject "Exercise 7-1" refer to K&R? *My copy isn't handy.)
| Yes it does..
"Write a program that converts upper case to lower case or lower case
to upper, depending upon the name that it is invoked with, as found in
argv[0]." Quote:
>
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.
| It's a poorly chosen fragment.
My question was specifically directed to the problem of needing to
invoke the program ....which in my case means typing the path name and
then RETURN...then typing something in lower case, then RETURN
converts this to upper case.
As I thought the issue was not really related to the code that was
written, I did not really give due diligence to the issues you were
pointing out...which was my mistake, and which I will try and correct
below. Quote:
>
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.
>
>
>
What you've done is an incorrect mixture of the two approaches.
>
>
| 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;
}
<<<<<<<< | 
September 3rd, 2008, 11:45 PM
| | | Re: Exercise 7-1
On Sep 2, 10:48*pm, vipps...@gmail.com wrote: Quote:
On Sep 3, 6:34 am, mdh <m...@comcast.netwrote:
> 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?
> | Well, I am not sure if it is a "C" issue or an "Xcode" issue, which is
what I use when working through the exercises. If it is an Xcode
issue, I think I would be directed to the appropriate forum ( which
exists) but having said that, I ask here to find out with certainty
which it is. | 
September 4th, 2008, 12:05 AM
| | | Re: Exercise 7-1
mdh <mdeh@comcast.netwrites:
[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" | 
September 4th, 2008, 12:15 AM
| | | Re: Exercise 7-1
On Sep 3, 5:00*pm, Keith Thompson <ks...@mib.orgwrote: Quote:
mdh <m...@comcast.netwrites:
>
>
>
Ok, that looks reasonable, mostly.
| Finally!! :-) Quote:
>
But now I've lost track of what you were asking about.
|
LOL!
The question was why one invoked the program by using the "name" , in
this case lower/upper. Then on my computer, I need to hit "Return",
then type some stuff, which, after a return, converts it to upper or
lower as requested in the name.
In other words, you cannot do this...
/....whateverthepathis/lower CONVERT ME TO LOWER
but you can do this.
/....whateverthepathis/lower RETURN
**program launches**
Now type:
CONVERT ME TO LOWER
and it performs as expected. ie output is "convert me to lower" Quote:
>
*I suggest printing the value of
argv[0] to see how it's actually being set.
|
Thank you...did not think of that. | 
September 4th, 2008, 02:05 AM
| | | Re: Exercise 7-1
On Sep 4, 2:40 am, mdh <m...@comcast.netwrote: Quote:
On Sep 2, 10:48 pm, vipps...@gmail.com wrote:
> Quote: |
On Sep 3, 6:34 am, mdh <m...@comcast.netwrote:
| > Quote: Quote: |
I am not sure how relevant to C this is, but here goes.
| | > Quote: |
It's a C exercise from a C book, how more relevant can it be?
| >
Well, I am not sure if it is a "C" issue or an "Xcode" issue, which is
what I use when working through the exercises. If it is an Xcode
issue, I think I would be directed to the appropriate forum ( which
exists) but having said that, I ask here to find out with certainty
which it is.
|
It's a C exercise from a C book, how more relevant can it be? | 
September 4th, 2008, 04:15 AM
| | | Re: Exercise 7-1
On Tue, 2 Sep 2008 20:34:36 -0700 (PDT), mdh <mdeh@comcast.netwrote: 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.
| After you fix the bad logic and undefined behavior in your code, print
out the string argv[0] points to and find out what your "shell" is
doing different between the two invocations of your program.
--
Remove del for email | 
September 4th, 2008, 01:15 PM
| | | Re: Exercise 7-1
On Sep 3, 9:12*pm, Barry Schwarz <schwa...@dqel.comwrote: Quote: |
On Tue, 2 Sep 2008 20:34:36 -0700 (PDT), mdh <m...@comcast.netwrote:
| .. Quote:
>
After you fix the bad logic and undefined behavior in your code, print
out the string argv[0] points to and find out what your "shell" is
doing different between the two invocations of your program.
>
| No difference.
As this is the first time K&R involved I/O use, I wanted to get this
working. What I missed was the fact that getchar() reads from the
standard input, as Keith showed with his diagram. | 
September 4th, 2008, 10:15 PM
| | | Re: Exercise 7-1 vippstar@gmail.com wrote: Quote:
>
It's a C exercise from a C book, how more relevant can it be?
| It's hard to say -- some books which claim to be about C contain
exercises that have little to nothing to do with C.
--
Larry Jones
Temporary insanity! That's all it was! -- Calvin | 
September 5th, 2008, 07:05 AM
| | | Re: Exercise 7-1 lawrence.jones@siemens.com wrote: Quote: vippstar@gmail.com wrote: Quote:
It's a C exercise from a C book, how more relevant can it be?
| >
It's hard to say -- some books which claim to be about C contain
exercises that have little to nothing to do with C.
| Well, yeah, but in this case it's not from a C book, but from the C
book: K&R 2.
Richard | | Thread Tools | Search this Thread | | | |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 220,989 network members.
|