Newbie: Problems Picking up integer values (dereferencing problem?)Really Trying To ReadTheGoshDarne

L

Lily Jost

Hello

Is this the proper forum for this question? If not, will you please
let me know where I should ask it? Thank you! - Lily
…………

1) Version numbers, why I'm doing it this way, books/manuals I've
tried

2) Description of Problem

3) Terminal Session

4) My code (it's not that big - I'm a newbie)

.................... 1) Version numbers, why I'm doing it this way,
books/manuals I've tried


I have been trying hard to figure out how to solve this challenge on
my own. Honest!

I’m running Mac OS X, version 10.6.4. I’m using the editor in XCode
ver 3.2.3, to create my examples. I’m compiling and running the
examples from Terminal version 2.1.1.

I’m using this setup because it’s recommended by the book author of
the book I’m using (as a self-taught student – not taking a class).
I’m using the O’Reilly Nutshell book – Cocoa and Objective-C but THIS
QUESTION is based on material up to chapter 3 and that is C - NOT
OBJECTIVE C (Stevenson gets to Objective C starting in chapter 4). I'm
trying to keep writing samples like he writes the book examples,
because he refers back to these methods and how to use data types in
the next chapters (yes - I have moved forward with chapters 4 and 5).
Being able to work with data types - kinda important!

I can get all of the book examples up through chapter 3 to compile and
run properly on my Mac. I thought it would be good to go beyond just
debugging my typing errors, and see if I could do something every so
slightly different than I was being instructed to do, to work.
Especially since the use of ‘*’ and & is not that clear to me, no
matter how many times I reread those sections of the book. In theory I
understand the difference between a memory address where you store
stuff and the value you store there. I understand what an array is. I
have used these ideas in other languages – but I don’t get how they
work in C, so far.

I also checked two C books out of the library this morning and pawed
through them, reading about dereferencing and looking for similar
examples to the one I based this on in the Nutshell book. I can’t find
one that seems to kind of implicitly accept input from the terminal
line, like he does. Though I don’t think the way I’m inputting or
reading is the problem. (Harbison and Steele C, A Reference Manual and
Kalicharan’s C Programming – Beginners Course)


* * * * 2) Here is my problem * * *
Problem is that I’m trying to accept two numbers input on the Terminal
line (following the program name). I can count the number of entries
properly (all 3 error handling conditions work, plus too many inputs
also gives proper error. Also I have tested with numbers that have
more than one digit).

But… I cannot actually manage to pickup/display the actual numeric
data that the user inputs. I THINK MAYBE I’m displaying memory
addresses, and that maybe I’m not understanding dereferencing
properly. I know I find the use of ‘*’ and ‘&’ confusing. I understand
that the compile warning error is telling me I’m not setting up an
integer array correctly, but I don’t understand how to set it up.

I did try asking for membership to the forum that the O’Reilly author
refers to in his book, 2 days ago. But they have to approve all
membership, and I haven’t gotten anything back from them. I promise
I'm a good usenet citizen. I used to get and give a lot of help in the
perl forum – 10 or more years ago (that makes me feel old).

………………. 3) Here is my Terminal session – Even though I got a warning
error, and clearly it’s trying to tell me something important, I can
still run my example. It just doesn’t do what I want it to. ……….

lily-josts-imac:ch03 davidjost$ gcc
AcceptUserInputTwoNumbersNDDisplayEm.c -o
AcceptUserInputTwoNumbersNDDisplayEm
AcceptUserInputTwoNumbersNDDisplayEm.c: In function ‘main’:
AcceptUserInputTwoNumbersNDDisplayEm.c:41: warning: format ‘%i’
expects type ‘int’, but argument 2 has type ‘int *’
AcceptUserInputTwoNumbersNDDisplayEm.c:42: warning: format ‘%i’
expects type ‘int’, but argument 2 has type ‘int **’

… despite the warning – I go ahead and run it …..

lily-josts-imac:ch03 davidjost$ ./AcceptUserInputTwoNumbersNDDisplayEm
4 5
You entered 2 numbers, and that is correct
The first number you input was 1606417151
Or is this more like it? 1606416872
lily-josts-imac:ch03 davidjost$

………………. 4) Here is my Code ……

/*
* AcceptUserInputTwoNumbersNDDisplayEm.c *
* Accept two numbers input by the user on the terminal line
* Display the first number the user typed in
*
*/

#include <stdio.h>


main ( int inputCount, int* inputValues[]) {
// don't count the program name as a value
// I THINK that 'inputCount' from page 69
// only occurs here and as an argument to main
// unclear how inputCount ever picks up a value

int numericCount = 0;
numericCount = (inputCount -1);

// tell the user how many numbers she entered

if (numericCount > 0) {

if (numericCount == 2) {
printf("You entered %i numbers, and that is correct \n",
numericCount);
} else {
printf("You entered the wrong number of input values. Enter 2
values. You entered %i \n", numericCount);
}

} else {
printf("You didn't enter any numbers\n");
// exit (1);
}

// the first instance of the array is 0, but that would be program
name

printf("The first number you input was %i \n", inputValues[1]);
printf("Or is this more like it? %i \n", &inputValues[1]);


}
 
I

Ian Collins

Hello

Is this the proper forum for this question? If not, will you please
let me know where I should ask it? Thank you! - Lily

Assuming the problem really is C!

Excuse generous snipping.

I’m using this setup because it’s recommended by the book author of
the book I’m using (as a self-taught student – not taking a class).
I’m using the O’Reilly Nutshell book – Cocoa and Objective-C but THIS
QUESTION is based on material up to chapter 3 and that is C - NOT
OBJECTIVE C (Stevenson gets to Objective C starting in chapter 4).

* * * * 2) Here is my problem * * *
Problem is that I’m trying to accept two numbers input on the Terminal
line (following the program name). I can count the number of entries
properly (all 3 error handling conditions work, plus too many inputs
also gives proper error. Also I have tested with numbers that have
more than one digit).


lily-josts-imac:ch03 davidjost$ gcc
AcceptUserInputTwoNumbersNDDisplayEm.c -o
AcceptUserInputTwoNumbersNDDisplayEm
AcceptUserInputTwoNumbersNDDisplayEm.c: In function ‘main’:
AcceptUserInputTwoNumbersNDDisplayEm.c:41: warning: format ‘%i’
expects type ‘int’, but argument 2 has type ‘int *’
AcceptUserInputTwoNumbersNDDisplayEm.c:42: warning: format ‘%i’
expects type ‘int’, but argument 2 has type ‘int **’

… despite the warning – I go ahead and run it …..

Never a good idea, the compiler is trying to help you.
lily-josts-imac:ch03 davidjost$ ./AcceptUserInputTwoNumbersNDDisplayEm
4 5
You entered 2 numbers, and that is correct
The first number you input was 1606417151
Or is this more like it? 1606416872

#include<stdio.h>


main ( int inputCount, int* inputValues[]) {

IF this is standard C, that's where you problems start. The correct
second parameter for main is char**, not int**.

// the first instance of the array is 0, but that would be program
name

printf("The first number you input was %i \n", inputValues[1]);
printf("Or is this more like it? %i \n",&inputValues[1]);

The compiler warned you about these!

Given the "inputValues" parameter is an array of char*, not int*, you
have to convert the values passed to an int. You can't assume by
declaring them as int*, that they will be converted.

You should read up on the string conversion routines, strtol.
 
K

Keith Thompson

Ian Collins said:
On 07/21/10 10:34 AM, Lily Jost wrote: [...]
main ( int inputCount, int* inputValues[]) {

IF this is standard C, that's where you problems start. The correct
second parameter for main is char**, not int**.

And the conventional names for the arguments to main are argc
and argv. Giving them more "descriptive" names really isn't helpful;
all C programmers know what the names "argc" and "argv" mean.

You should also declare the return type:
int main(int argc, char *argv[])
or, equivalently,
int main(int argc, char **argv)
 
B

Ben Bacarisse

Lily Jost said:
Is this the proper forum for this question?

I'm not sure...

I’m using the O’Reilly Nutshell book – Cocoa and Objective-C but THIS
QUESTION is based on material up to chapter 3 and that is C - NOT
OBJECTIVE C (Stevenson gets to Objective C starting in chapter 4).

Yup, here is good for questions about C.

4) Here is my Code

/*
* AcceptUserInputTwoNumbersNDDisplayEm.c *
* Accept two numbers input by the user on the terminal line
* Display the first number the user typed in
*
*/

The phrase "on the terminal line" is ambiguous. I think you mean "on
that command line". I.e. you will run the program by typing its name
followed by two numbers on the same line that runs the program. These
extra things you type are called command-line arguments.
#include <stdio.h>


main ( int inputCount, int* inputValues[]) {

The return value of main is int and it is better to say so (and to
return a value -- 0 is good if you have no reason to return anything
else).

The two parameters to main are of type int and char ** (which you can
write using [] rather than *). You don't get to change that type no
matter what you want your program to get passed. It gets passed an
array of strings, represented as an array of char pointers. I.e. you
should declare main like this:

int main(int inputCount, char *inputValues[]) /* ... */

You have the task of changing these strings into the kind of data your
program needs.
// don't count the program name as a value
// I THINK that 'inputCount' from page 69
// only occurs here and as an argument to main
// unclear how inputCount ever picks up a value

int numericCount = 0;
numericCount = (inputCount -1);

// tell the user how many numbers she entered

if (numericCount > 0) {

if (numericCount == 2) {
printf("You entered %i numbers, and that is correct \n",
numericCount);
} else {
printf("You entered the wrong number of input values. Enter 2
values. You entered %i \n", numericCount);
}

} else {
printf("You didn't enter any numbers\n");
// exit (1);

exit is declared in stdlib.h along with two macros: EXIT_SUCCESS and
EXIT_FAILURE. exit(1) (or just return 1;) probably works, but
exit(EXIT_FAILURE) is guaranteed to return the right failure code on
every conforming C implementation (it's also a lot clearer to the
reader).

You either need to call exit from all the error cases or you need to
move this code up into the branch of the 'if' where you know the count
is correct. If not, you will always get here and print a message even
when the command-line arguments are incorrect.
// the first instance of the array is 0, but that would be program
name

printf("The first number you input was %i \n", inputValues[1]);
printf("Or is this more like it? %i \n", &inputValues[1]);

Neither. inputValues[1] must be a char * (i.e. a pointer to the start
of a string) and you print strings using the %s format. If you have to
print the number using %i (or %d) then you need to convert the string
into a number. Look up atoi and strtol your book[1]. strtol is the better
function to use, but it takes some care to use it right. It can be used
to check that the string really is a number. What should your program
do if the first command-line argument is, say, "iamnotanumber"?

Finally, you should have 'return 0;' or 'return EXIT_SUCCESS;' here.
Modern C lets you omit the return from the end of main, but must people
think it is better style to include it.

[1] I don't know if they are in there because I don't know the book, but
you probably have the manual pages installed so you can use "man strtol"
etc.
 
L

Lily Jost

Thanks to everybody who replied. It sure is hard starting over from
the beginning again, and getting advice from all of you really helps
me get going.

Lily
 
L

Lily Jost

Thanks to everybody who replied. It sure is hard starting over from
the beginning again, and getting advice from all of you really helps
me get going.

Lily

Thank you again.

I got this VERY SIMPLE example to work, because of the responses
people made to my post yesterday.

I can see that, as suggested by one of the contributors to my question
yesterday, that I need to learn to include

- more error checking (like what happens if the user enters ‘yabba
dabba’ on the command line after the program name
- exit_success and exit_failulre

I also know that I will be learning the XCode GUI interface. I wanted
to get an example to work from the command line (thank you for
reminding me it’s not a ‘terminal line’ ☺
Simply because the command line gives me a base to move forward from.
I was a mainframe programmer for a long time, yes a while back, and
that is something I relate to. From here I will move forward into GUI.

This experience also tells me something about trying to lean
something, for which I, supposedly, only need to learn a subset of
something else. It’s clearly better if you know more of the subset
before you start. And what happens when the subset is unclear?


lily-josts-imac:ch03 davidjost$ gcc
CalculatePermeterWithTwoDimensions.c -o
CalculatePermeterWithTwoDimensions
lily-josts-imac:ch03 davidjost$ ./CalculatePermeterWithTwoDimensions
34 56
You entered 2 numbers, and that is correct
The first number you input was 34
The second number you input was 56
The perimiter of a rectangle with these dimensions would be 180
lily-josts-imac:ch03 davidjost$



/*
* CalculatePerimeterGivenTwoDimensions.c
*
*
* Created by Lily Jost on 7/21/10.
* Accept two dimensions input by the user on the terminal line
* Calculate the perimeter for those 2 dimensions
*
*/

#include <stdio.h>


int main (int argc, char *argv[] ) {

int numericCount = 0;
numericCount = (argc -1);

int dimensionOne = 0;
int dimensionTwo = 0;
int PerimeterInches= 0;



// tell the user how many numbers she entered

if (numericCount > 0) {

if (numericCount == 2) {
printf("You entered %i numbers, and that is correct \n",
numericCount);
} else {
printf("You entered the wrong number of input values. Enter 2
values. You entered %i \n", numericCount);
}

} else {
printf("You didn't enter any numbers\n");
// exit (1);
}

// the first instance of the array is 0, but that would be program
name

dimensionOne = atoi(argv[1]);
dimensionTwo = atoi(argv[2]);

PerimeterInches = ( (2*dimensionOne) + (2*dimensionTwo) );


printf("The first number you input was %i \n", dimensionOne);
printf("The second number you input was %i \n", dimensionTwo);
printf("The perimiter of a rectangle with these dimensions would be
%i", PerimeterInches);
printf("\n");



}
 
K

Keith Thompson

Geoff said:
I might also suggest considering the switch statement as an
alternative to your if-else construct. It allows for n-way decisions
to be a little easier to read and maintain. Breaking up your printf
lines would improve the readability also.

switch(numericCount)
{
default:
printf("You entered the wrong number of input values.");

Did you want a "\n" at the end of that string?
printf("Enter 2 values. You entered %i \n", numericCount);
break;

You can put the default case anywhere you like but it's almost always
given last.
case 2:
printf("You entered %i numbers, and that is correct \n"
,numericCount);

A very minor point: I would have put the comma at the end of the
previous line.

Also, "%i" is equivalent to "%d", but "%d" is more commonly used.
(I'm not even entirely sure why they both exist. "%i" isn't
mentioned in K&R1; perhaps it was invented by ANSI?.)
printf("The first number you input was %s \n", argv[1]);
printf("Or is this more like it? %s \n", argv[2]);
break;

I'd drop the spaces in front of the "\n"; no point in printing extra
spaces at the end of the line that won't be visible anyway.
case 0:
printf("You didn't enter any numbers\n");
break;
}

You might consider using puts() rather than printf() when you're just
printing a string with a new-line. But printf is ok, and there's
something to be said for consistency. Just be careful about '%'s
in the string that aren't intended to be part of format specifiers.
 
K

Keith Thompson

Geoff said:
No, I was keeping to her original intent of printing that line out as
one line.

Ok, but the one line will have no spaces between "input values." and
"Enter 2 values.".
... and nearly always forgotten by novices for that reason. Putting
the default case first annotates that it wasn't forgotten and was
properly considered but style guidelines vary.

It would never have occurred to me that the default case was put first
to emphasize that it wasn't forgotten. I'd say that having it there at
all is more than sufficient sufficient for that purpose.

If you don't do anything in the default case, you might write:

...
default: /* do nothing */

rather than just omitting it. Again, putting that at the end is just as
good as putting it at the beginning.

Or am I missing something?

[snip]
 
K

Keith Thompson

Keith Thompson said:
A very minor point: I would have put the comma at the end of the
previous line.

Also, "%i" is equivalent to "%d", but "%d" is more commonly used.
(I'm not even entirely sure why they both exist. "%i" isn't
mentioned in K&R1; perhaps it was invented by ANSI?.)

Yes, apparently it was. Quoting the C99 Rationale:

The %i conversion specifier was added in C89 for programmer
convenience to provide symmetry with fscanf’s %i conversion
specifier, even though it has exactly the same meaning as the
%d conversion specifier when used with fprintf.

For fscanf, "%d" accepts only decimal input and "%i" accepts either
decimal, octal, or hex.

I still prefer to use "%d" rather than "%i" for printf, if only
because that's what most C programmers use.
 
B

Ben Bacarisse

Lily Jost said:
/*
* CalculatePerimeterGivenTwoDimensions.c
*
*
* Created by Lily Jost on 7/21/10.
* Accept two dimensions input by the user on the terminal line
* Calculate the perimeter for those 2 dimensions
*
*/

#include <stdio.h>


int main (int argc, char *argv[] ) {

int numericCount = 0;
numericCount = (argc -1);

int dimensionOne = 0;
int dimensionTwo = 0;
int PerimeterInches= 0;



// tell the user how many numbers she entered

if (numericCount > 0) {

if (numericCount == 2) {
printf("You entered %i numbers, and that is correct \n",
numericCount);
} else {
printf("You entered the wrong number of input values. Enter 2
values. You entered %i \n", numericCount);
}

} else {
printf("You didn't enter any numbers\n");
// exit (1);
}

// the first instance of the array is 0, but that would be program
name

dimensionOne = atoi(argv[1]);
dimensionTwo = atoi(argv[2]);

You can get here in cases where argv[1] and argv[2] are meaningless.
OK, one call to exit is commented out so you probably intend to put that
back at some time, but when argc == 2 (and numericCount == 1) you will
print an error message and the then come here and try to decode argv[2].

When the user gives only one string, argc will be 2, argv[1] will be
that string and argv[2] will be a null pointer. Passing a null pointer
to atoi is "undefined behaviour" -- anything is possible.

It's often clearer to structure a program round what is needed for
everything to work right, rather than putting the errors up front. For
example, I'd write this:

if (argc == 3) { /* two command-line arguments */
int dimensionOne = atoi(argv[1]);
int dimensionTwo = atoi(argv[2]);
int PerimeterInches = 2*dimensionOne + 2*dimensionTwo;

printf("You entered %d numbers, and that is correct\n", argc - 1);
printf("The first number you input was %d\n", dimensionOne);
printf("The second number you input was %d\n", dimensionTwo);
printf("The perimiter of a rectangle with these dimensions would be %d\n",
PerimeterInches);
}
else if (argc < 3)
printf("You provided too few numbers. Two are required.\n");
else if (argc > 3)
printf("You provided too many numbers. Two are required.\n");

I.e. treat the errors as incidental and the correct path as the main
one. Just a suggestion...
 
A

Alexander Klauer

Keith Thompson wrote:
[...]
If you don't do anything in the default case, you might write:

...
default: /* do nothing */

rather than just omitting it. Again, putting that at the end is just as
good as putting it at the beginning.

Or am I missing something?

Syntactically, the colon after the label must be followed by a statement
(N1256, 6.8.1), so in your case, you may get a syntax error if
the default label is at the very end of the switch statement.

Of course, you can simply write

default:
; /* do nothing */

to circumvent this catch.
 
A

Alexander Klauer

Geoff said:
Keith Thompson wrote:
[...]
If you don't do anything in the default case, you might write:

...
default: /* do nothing */

rather than just omitting it. Again, putting that at the end is just as
good as putting it at the beginning.

Or am I missing something?

Syntactically, the colon after the label must be followed by a statement
(N1256, 6.8.1), so in your case, you may get a syntax error if
the default label is at the very end of the switch statement.

Of course, you can simply write

default:
; /* do nothing */

to circumvent this catch.

I think writing
default:
break; /* do nothing */

would be more in order. Or would it have the same effect as not
including a default case at all?

At the end of a switch statement, that is, ";" or "break;" is the last
statement in the switch block, it doesn't matter which one you have. With
the default label further up, you get fall-through with ";" (or no
statement before the next label at all), and no fall-through with "break;".
But the whole behaviour caused by fall-through is generally
position-dependent anyway.

Hmm, re-reading Keith's post makes me think that he probably had a "break;"
after the default label in mind anyhow, which renders my previous post
moot.
 
K

Keith Thompson

Alexander Klauer said:
Geoff said:
Keith Thompson wrote:
[...]
If you don't do anything in the default case, you might write:

...
default: /* do nothing */

rather than just omitting it. Again, putting that at the end is just as
good as putting it at the beginning.

Or am I missing something?

Syntactically, the colon after the label must be followed by a statement
(N1256, 6.8.1), so in your case, you may get a syntax error if
the default label is at the very end of the switch statement.

Of course, you can simply write

default:
; /* do nothing */

to circumvent this catch.

Yes, you're right, thanks.

It would have the same effect as far as the program's semantics are
concerned, but it tends to document to the human reader that the default
case wasn't omitted accidentally.
At the end of a switch statement, that is, ";" or "break;" is the last
statement in the switch block, it doesn't matter which one you have. With
the default label further up, you get fall-through with ";" (or no
statement before the next label at all), and no fall-through with "break;".
But the whole behaviour caused by fall-through is generally
position-dependent anyway.

Right. You could have a default case at the beginning of a switch
statement followed by a fall-through to another case. But it would
be hard to resist the urge to slap anyone who wrote such code.
Hmm, re-reading Keith's post makes me think that he probably had a "break;"
after the default label in mind anyhow, which renders my previous post
moot.

Thanks for the overestimate, but I just goofed. :cool:}
 
N

Nick

Keith Thompson said:
Alexander Klauer said:
Geoff said:
On Thu, 22 Jul 2010 15:08:02 +0200, Alexander Klauer

Keith Thompson wrote:
[...]
If you don't do anything in the default case, you might write:

...
default: /* do nothing */

rather than just omitting it. Again, putting that at the end is just as
good as putting it at the beginning.

Or am I missing something?

Syntactically, the colon after the label must be followed by a statement
(N1256, 6.8.1), so in your case, you may get a syntax error if
the default label is at the very end of the switch statement.

Of course, you can simply write

default:
; /* do nothing */

to circumvent this catch.

Yes, you're right, thanks.

It would have the same effect as far as the program's semantics are
concerned, but it tends to document to the human reader that the default
case wasn't omitted accidentally.

And, indeed, to some compilers. GCC is clever enough to warn you if you
are switching on an enum and don't have a case for each named value of
the enum, or a default.
 

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