Order of Variable Declartion

I

Interrupt

Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
going!! Something’s don’t make sense- for example I’ve written a bit
of code if I declare variable int a; at the start of variable
declarations (in a watch window : the code doesn’t work because int a
=0 always; ) But if I declare it last the code works ie what ever the
user inputs???

************ Code *********************************************
#include <stdio.h>
#include <stdlib.h>
int manipulate(int a,int box,char c);
int main()
{
while(1)
{
// if I declare int a here code doesn’t work???????
char c;
int z;
int box;
int a; // when I declare it here it works ??????

puts("enter an integer b");
scanf("%d",&box);

puts( " the integer value a");
scanf("%d",&a);


puts("Enter the type of manipulation Required,/,*,+,-.");
scanf("%s",&c);

z = manipulate( a, box, c);

printf("the Answer is %d\n\n",z);
}
return 0;
}
************************ Code
**********************************************************************
 
N

Nick

Interrupt said:
Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
going!! Something’s don’t make sense- for example I’ve written a bit
of code if I declare variable int a; at the start of variable
declarations (in a watch window : the code doesn’t work because int a
=0 always; ) But if I declare it last the code works ie what ever the
user inputs???

That is a sure sign that something has gone horribly wrong in your code,
and something is stamping on the space in memory that your variable is
held in.
************ Code *********************************************
#include <stdio.h>
#include <stdlib.h>
int manipulate(int a,int box,char c);
int main()
{
while(1)
{
// if I declare int a here code doesn’t work???????
char c;
int z;
int box;
int a; // when I declare it here it works ??????

puts("enter an integer b");
scanf("%d",&box);

puts( " the integer value a");
scanf("%d",&a);


puts("Enter the type of manipulation Required,/,*,+,-.");
scanf("%s",&c);

And here's where it happens. You read a string (%s) but c is char.

So even if the user only enters a single character, you will still read
that character and an "end of string" marker character ('\0'). Notice
that it's when you put 'a' next to 'c' in the declaration that it goes
wrong.

If your user enters "I'd like to multiply those two numbers together
please Bob", heaven knows what will happen.

You either need to scanf for a character, or create a suitable sized
string buffer for the result. I'm not a great user (or fan) of scanf,
so I'll leave detailed recommendations on that to others.
 
A

Andrew Poelstra

Hi folks, I'm trying to teach myself C, I?m finding it pretty hard
going!! Something?s don?t make sense- for example I?ve written a bit
of code if I declare variable int a; at the start of variable
declarations (in a watch window : the code doesn?t work because int a
=0 always; ) But if I declare it last the code works ie what ever the
user inputs???

************ Code *********************************************
#include <stdio.h>
#include <stdlib.h>
int manipulate(int a,int box,char c);
int main()
{
while(1)
{
// if I declare int a here code doesn?t work???????
char c;
int z;
int box;
int a; // when I declare it here it works ??????

puts("enter an integer b");
scanf("%d",&box);

puts( " the integer value a");
scanf("%d",&a);

puts("Enter the type of manipulation Required,/,*,+,-.");
scanf("%s",&c);

Here is your problem. %s expects a pointer to an array of char of
indefinite length. Since such a thing does not exist, I'm not sure
why the specifier is allowed to be used this way. (If you were to
use, say, %20s, it would expect a pointer to an array of 20 char.)

BUT, you don't have, nor do you want, an array. You have a single
char, and for that you need to use the %c specifier.

%s can't tell if you've given it a proper array; it just assumes
that you have, even though you actually handed it an address of
a single char. So it happily writes '+' to c, '\n' to the byte
after c, and '\0' to the byte after that. But since you don't
own those bytes, anything could happen! In this case I think you
are overwriting the value of a, or something like that, which is
why your code appears not to work.

I hope this helps. I tried to be concise but I don't think I did.
 
J

Jens Thoms Toerring

Interrupt said:
Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
going!! Something’s don’t make sense- for example I’ve written a bit
of code if I declare variable int a; at the start of variable
declarations (in a watch window : the code doesn’t work because int a
=0 always; ) But if I declare it last the code works ie what ever the
user inputs???

The problem isn't related to the variable 'a' (that's only a
collateral damage) but to the fact that your variable 'c' is
defined as a single char but you try to read a string into it:
************ Code *********************************************
#include <stdio.h>
#include <stdlib.h>
int manipulate(int a,int box,char c);
int main()
{
while(1)
{
// if I declare int a here code doesn’t work???????
char c;
int z;
int box;
int a; // when I declare it here it works ??????
puts("enter an integer b");
scanf("%d",&box);
puts( " the integer value a");
scanf("%d",&a);

puts("Enter the type of manipulation Required,/,*,+,-.");
scanf("%s",&c);

Here you tell scanf() with "%s" that '&c' is a pointer to an array
of chars but 'c' is only a single char. And scanf() will try to
write the string the user enters into this location. Since there
isn't room enough it's going to overwrite some other unrelated data
(e.g. your variable 'a' if it's in the way). If you just need a
char use "%c" instead if "%s" - that tells scanf() that you only
expect a single char.

Obviously your compiler organizes the variables in an order
that, when you define 'a' before 'c', 'a' is located shortly
after 'c' in memory and thus writing past 'c' overwrites what
is stored in 'a'. But note that it could also the other way
round, the compiler is free to decide where to put the vari-
ables. And if you define 'a' after 'c' it may seem as if it
works, but that's pure bad luck, you're then just overwriting
some other (perhaps in this special case less essential) data.

Just a warning: using scanf() to read strings with a simple "%s"
is always dangerous since scanf() has no idea at all how much
space there is for the string, and if the users enters a string
that's longer than what would fit into the memory you set aside
for it it, will happily write past the end of the array, resul-
ting in a potentialy hard to find bug!

Regards, Jens
 
B

Ben Bacarisse

Andrew Poelstra said:
Here is your problem. %s expects a pointer to an array of char of
indefinite length. Since such a thing does not exist, I'm not sure
why the specifier is allowed to be used this way. (If you were to
use, say, %20s, it would expect a pointer to an array of 20 char.)

BUT, you don't have, nor do you want, an array. You have a single
char, and for that you need to use the %c specifier.

Beginners can get in a mess with %c because it does not skip white
space and there will (probably) be some there from the previous
numeric input.

To the OP: if you switch to %c put a space in front like this:

scanf(" %c", &c);

The space is another input directive and means "skip white space
characters".
%s can't tell if you've given it a proper array; it just assumes
that you have, even though you actually handed it an address of
a single char. So it happily writes '+' to c, '\n' to the byte
after c, and '\0' to the byte after that.

Nit: %s stops on white space so it will only write '+' followed by
'\0' when the '\n' is seen. The '\n' is left for the next input
operation to see.

Second to the OP: you really should be testing the return from scanf.
It is a great habit to get into, not because it is the right thing to
do (though it is) but because it gets you thinking about how the
program should be shaped to cope with thing going wrong. Coping with
things going wrong is one of the most important things to pick up, and
you can't start too early.

<snip>
 
B

Ben Bacarisse

Richard Heathfield said:
Interrupt wrote:

Here's your problem. The easiest fix is to change %s to %c.

" %c" will be less confusing to a beginner.
I suggest taking a good long look at the fgets() function. Not the
broken, deprecated gets() function, but the good, solid, easy-to-use
fgets() function, which reads a string from a file (you can use stdin,
of course) into an array of char. Grab all your data that way, and
convert it into numbers (where necessary) once you've got it safely
out of the input stream. And leave scanf until you've got a lot more
experience under your belt.

Hmm... I'm not sure about this often quoted advice. scanf is fiddly,
but so is line-based input and subsequent conversion. I agree that it
is often better in the long-run, so it is worth getting to know that
method, but I am not convinced that it is easier to /start/ doing
input that way.
 
A

Andrew Poelstra

...

Nit: %s stops on white space so it will only write '+' followed by
'\0' when the '\n' is seen. The '\n' is left for the next input
operation to see.

That's more than a nit - I didn't know that and it probably would
have nailed me! (If I were ever to use scanf() on stdin.)
Second to the OP: you really should be testing the return from scanf.
It is a great habit to get into, not because it is the right thing to
do (though it is) but because it gets you thinking about how the
program should be shaped to cope with thing going wrong. Coping with
things going wrong is one of the most important things to pick up, and
you can't start too early.

That one I knew, but forgot to mention.
 
I

Interrupt

Hi folks thanks to the many replies very helpful !! As you’ll have
noticed I’m only starting so excuse my ignorance, how do you test the
return from scanf??
 
J

Jens Thoms Toerring

Hi folks thanks to the many replies very helpful !! As you’ll have
noticed I’m only starting so excuse my ignorance, how do you test the
return from scanf??

The return value tells you how many items scanf() found in the
input. Normally you want as many as you asked for, e.g. if you
have

scanf( "%d %d %d", &x, &y, &z );

then you should check if scanf() returned 3, i.e.

if ( scanf( "%d %d %d", &x, &y, &z ) != 3 ) {
fprintf( stderr, "Expected 3 int's but didn't find as many\n" );
exit( EXIT_FAILURE );
}

Or, if the return value is 2, then you know that 'z' hasn't been
set by the call of scanf() and thus it's not be safe to use its
value (unless it had been set to a sane default value before).

In your case, where you expect a single char, scanf() returns 1
on success - but if it returns 0 then the user didn't enter a
character (perhaps just hit the return key) and thus you should
e.g. ask again.
Regards, Jens
 
B

Ben Bacarisse

In your case, where you expect a single char, scanf() returns 1
on success - but if it returns 0 then the user didn't enter a
character (perhaps just hit the return key) and thus you should
e.g. ask again.

It is not obvious how scanf("%c", &c) could return 0 in any normal
use. If there is no more input or an input error occurs, scanf
returns EOF. Otherwise a character (any character) is read and
assigned. Obviously, if the behaviour is undefined because, for
example, c is a float not a char then anything could happen (including
a zero return).

In particular, if the next character is a new line it will be read and
scanf will return 1.
 
J

Jens Thoms Toerring

Richard Heathfield said:
Jens Thoms Toerring wrote:
<snip>
It is not clear to me from the Standard whether it is safe to rely on
'z''s value in such a circumstance even if you did set it to a sane
default value before the call.

Probably an unwarranted assumption, based on hopeful thinking;-)
And I also forgot to mention that scanf() may also return EOF
(a negative number, often -1) on input failure before anything
could be read (e.g. due to the user closing in the input chan-
nel).
Regards, Jens
 
O

osmium

io_x said:
"Interrupt" <[email protected]> ha scritto nel messaggio
Hi folks, I'm trying to teach myself C, I'm finding it pretty hard
going!! Something's don't make sense- for example I've written a bit
of code if I declare variable int a; at the start of variable
declarations (in a watch window : the code doesn't work because int a
=0 always; ) But if I declare it last the code works ie what ever the
user inputs???

************ Code *********************************************
what about: (don't know if it is right)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define P printf
#define F for
#define u8 unsigned char

int manipulate(int a, int box, char c)
{P("Here enter: (a, box, char) == %d %d %c\n",
a, box, c);
return 0;
}

int main()
{
while(1)
{int z;
int box;
int a; // when I declare it here it works ??????
char v[1024], c, *pc;

puts( " the integer value a");
*v=0; pc=fgets(v, 1024, stdin);
if(pc==0) break;
z=sscanf(v, "%d",&a);
if(z!=1) break;

puts("enter an integer b");
*v=0; pc=fgets(v, 1024, stdin);
if(pc==0) break;
z=sscanf(v, "%d", &box);
if(z!=1) break;

puts("Enter the type of manipulation Required,/,*,+,-.");
*v=0; pc=fgets(v, 1024, stdin);
if(pc==0) break;
F(z=0; z<1024&&v[z]; ++z)
if(!isspace((u8) v[z])) break;
if(z==1024||v[z]==0) break;
c=v[z];
z=manipulate( a, box, c);
printf("the Answer is %d\n\n",z);
}

return 0;
}

for one game this code could be right
for other it is need to write down routines
that cach all errors (overflow, required "/*+-" etc etc

Google strikes again. That message, as viewed on my newsreader is almost
undecipherable. Caused by the fact that Interrupt is posting from Google
with their cavalier standards WRT protocols.

I see no attributions and this is a thread I haven't been following.
Finally, after chasing through the history, I detected a three line message
appended at the end.

Damn those people at Google!
 
D

David Thompson

Here is your problem. %s expects a pointer to an array of char of
indefinite length. Since such a thing does not exist, I'm not sure

Not really indefinite; just large enough for the actual (whitespace
delimited) input value found. If you have sufficient control over or
trust of your input data this might be right -- but that 'if' is often
hard to maintain over time, which is why this is unwise.
why the specifier is allowed to be used this way. (If you were to
use, say, %20s, it would expect a pointer to an array of 20 char.)
21, to be safe. %Ns, and %N[charset], will store up to N input
characters plus a null terminator. OTOTH %Nc will store only N
characters, and fgets(buf,N,fp) will store up to N-1 chars including
the newline (if found) plus a null for a total not exceeding N.

Yes, this can be annoying.
 
O

osmium

James Harris - 1xf said:
I've looked at the message you refer to in via three methods: Google,
x-privat web and x-privat via Outlook Express. It looks decipherable to me
in all three.

That said, io_x's programming style is equally hard to read in all three
but that's due to his lack of spacing rather than any display issues.




Again, in all three options the message seems to me to be properly linked
into the thread. What reader are you using?

I have no reason to think any link was bad. The problem is that my
newsreader elides the leading '>' on certain messages from Google, thus the
message and the response to it are just a jumble. Note that almost
undecipherable doesn't mean the same thing as undecipherable. I use Outlook
Express, there is a front end for it, called QuoteFix, that solves that
problem but the (convenient) link provided from my browser leads to the
basic OE. I probably used the QuoteFix version on my earlier response.

I haven't studied this but someone once said Google posts HTML and Usenet is
supposed to be plain text.
 
O

osmium

Richard Heathfield said:
osmium wrote:



I *have* studied this. Using a tremendously significant statistical sample
of - um - one article, I conclude that Google doesn't *always* post HTML.
The one article I checked was plain text. The relevant header was:

Content-Type: text/plain; charset=ISO-8859-1

and the content was straight text. Not so much as an = in the whole
article body.

Thanks much for the update! That is consistent with my finding that quoting
a Google message only leads to problems part of the time. Bill Cunningham
posts, for one, sometimes give me a problem, sometimes not. Maybe you can
focus your follow on studies on him, assuming you get your grant of stimulus
money.
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top