Learning C - Scanf or Getch, or Getchar not working correctly after first loop.

T

tesh.uk

Hi Gurus,

I have written the following code with the help of Ivor Horton's
Beginning C :

// Structures, Arrays of Structures.

#include "stdafx.h"
#include "stdio.h"
#define MY_ARRAY 15
#define BASIS 360

struct swap
{
char counterParty[10];
float notional;
float intRate;
int busDays;
//int basis = 360;
float flows;
};

void main()
{

/*Arrays of Structures*/

swap myArraySwap[MY_ARRAY];


int hcount = 0;
int i = 0;
//='\0';

// for (hcount = 0; hcount < 5 ; hcount++ )
do
{
char test = NULL;
printf("\nWould you like to enter Swaps (Y or N)?:");

test = getchar();

if (test != 'Y') //|| test !='y')
break;

printf("\nEnter CounterParty:");
scanf("%s", &myArraySwap[hcount].counterParty );
printf("\nEnter Notional :" );
scanf("%f", &myArraySwap[hcount].notional );
printf("\nEnter Interest Rate:" );
scanf("%f", &myArraySwap[hcount].intRate );
printf("\nEnter Number of days:" );
scanf("%d", &myArraySwap[hcount].busDays );
myArraySwap[hcount].flows = (myArraySwap[hcount].notional *
(myArraySwap[hcount].intRate/100.0f) *
((float)myArraySwap[hcount].busDays/360.0f));

hcount++;
}
while (hcount < 5);

for (i=0 ; i < hcount ; i++)
{
printf("\nCounter Party: %s",myArraySwap[hcount].counterParty);
printf("\nFlows %f", myArraySwap.flows);
printf("\nDone");
}


}


Problem:

First time around the var test = '' and I can enter a value i.e. Y

here is the dos output:

Would you like to enter Swaps (Y or N)?:Y

Enter CounterParty:Test

Enter Notional :1000

Enter Interest Rate:5.25

Enter Number of days:35

Would you like to enter Swaps (Y or N)?:

second time around the at the point of test = getchar(); test is set
to '0 ' automatically and I am not able to enter Y or N.

when the app reaches:test = getchar(); it automatically sets the var
from Y 89 to : 0 ''

is this compiler related i have vs.net 2003 ?

i have also tried scanf and get the same :(

thank you.

tesh
 
N

Nick Keighley

On 15 Feb, 09:06, "(e-mail address removed)" <[email protected]>
wrote:


subject: Learning C - Scanf or Getch, or Getchar not working
correctly after first loop.

note C is a type sensitive language so Scanf etc. should
be written scanf.

Have you read the FAQ, which may be found at:-
http://c-faq.com/stdio/index.html

Try:

12.18a "I'm reading a number with scanf and %d, and then a string with
gets()
but the compiler seems to be skipping the call to gets()"

12.18b "I'm using scanf %c to read a Y/N response, but later input
gets skipped."


12.20 "Why does everyone say not to use scanf? What should I use
instead?"

as these may answer your questions


I have written the following code with the help of Ivor Horton's
Beginning C :

I'd find a better book. Have you tried
"The C Programming Language" by Kernighan & Richie?
// Structures, Arrays of Structures.

#include "stdafx.h"

non-standard header
#include "stdio.h"

standard headers should use this syntax

#include said:
#define MY_ARRAY 15
#define BASIS 360

struct swap
{
char counterParty[10];
float notional;

prefer double to float unless you *really* need to save space.
float intRate;
int busDays;
//int basis = 360;
float flows;
};

void main()

int main(void)
{

/*Arrays of Structures*/

not a very useful comment. Ok when you are starting out.
swap myArraySwap[MY_ARRAY];

int hcount = 0;
int i = 0;
//='\0';

// for (hcount = 0; hcount < 5 ; hcount++ )
do
{
char test = NULL;

no, NULL is usually a pointer constant. Use '\0' to represent
a nul charcter.
printf("\nWould you like to enter Swaps (Y or N)?:");
fflush(stdout);


test = getchar();

if (test != 'Y') //|| test !='y')
break;

printf("\nEnter CounterParty:");
scanf("%s", &myArraySwap[hcount].counterParty );
printf("\nEnter Notional :" );
scanf("%f", &myArraySwap[hcount].notional );
printf("\nEnter Interest Rate:" );
scanf("%f", &myArraySwap[hcount].intRate );
printf("\nEnter Number of days:" );
scanf("%d", &myArraySwap[hcount].busDays );
myArraySwap[hcount].flows = (myArraySwap[hcount].notional *
(myArraySwap[hcount].intRate/100.0f) *
((float)myArraySwap[hcount].busDays/360.0f));

hcount++;
}
while (hcount < 5);

for (i=0 ; i < hcount ; i++)
{
printf("\nCounter Party: %s",myArraySwap[hcount].counterParty);
printf("\nFlows %f", myArraySwap.flows);
printf("\nDone");
}

}

Problem:

First time around the var test = '' and I can enter a value i.e. Y

here is the dos output:

Would you like to enter Swaps (Y or N)?:Y

Enter CounterParty:Test

Enter Notional :1000

Enter Interest Rate:5.25

Enter Number of days:35

Would you like to enter Swaps (Y or N)?:

second time around the at the point of test = getchar(); test is set
to '0 ' automatically and I am not able to enter Y or N.

when the app reaches:test = getchar(); it automatically sets the var
from Y 89 to : 0 ''

is this compiler related i have vs.net 2003 ?

i have also tried scanf and get the same :(
 
R

Richard Heathfield

(e-mail address removed) said:
Hi Gurus,

I have written the following code with the help of Ivor Horton's
Beginning C :

I suggest you get a better book. From the look of your code, Mr Horton
needs to learn C before he tries writing a book about it.
// Structures, Arrays of Structures.

#include "stdafx.h"

No such header is defined by the C language.
#include "stdio.h"

Since you want to pick up the standard header, it's probably better to
use:

#include said:
#define MY_ARRAY 15
#define BASIS 360

struct swap
{
char counterParty[10];
float notional;
float intRate;
int busDays;
//int basis = 360;
float flows;
};

void main()

int main(void)
{

/*Arrays of Structures*/

swap myArraySwap[MY_ARRAY];


int hcount = 0;
int i = 0;
//='\0';

// for (hcount = 0; hcount < 5 ; hcount++ )
do
{
char test = NULL;

NULL is intended for use as a pointer value, not a char value. Use 0 for
an initialiser if you don't want test's value to be indeterminate.
Furthermore, you'll be using this for getchar, which - despite its name
- returns int, so make test an int, not a char. (There is a good reason
for this which would be overkill to go into at this stage.)
printf("\nWould you like to enter Swaps (Y or N)?:");

test = getchar();

if (test != 'Y') //|| test !='y')
break;

Well, yes, that's *one* way to get out of a loop, but it isn't the way
I'd have chosen.

Now, when you run your program, you press the 'Y' key, and then you
press the ENTER key, yes? The getchar() call will retrieve the 'Y' from
the standard input stream and assign its value to 'test', but that
still leaves a newline character in the stream (because you pressed
'ENTER'), and that has yet to be read. The next input function call,
then, will retrieve it. But you don't /want/ your scanf call to
retrieve it. You just want to throw it away. You can do so like this:

getchar(); /* read and discard newline character */

This isn't very robust (what if the user typed 'Yes' rather than 'Y'?),
but it'll get you back on track for now.
printf("\nEnter CounterParty:");
scanf("%s", &myArraySwap[hcount].counterParty );

Several problems here. Firstly, never ever use %s with scanf. If you
must use scanf to read a string, specify the maximum length of string
that your buffer can support. In this case, the counterParty member of
your struct has ten elements, so it can support a string up to 9
characters in length, so use %9s rather than %s. Secondly, you are
expected to provide a pointer to the first character in your buffer,
not a pointer to the array. So use EITHER

&myArraySwap[hcount].counterParty[0]

with the leading ampersand but specifying the first character in the
array as its operand, OR, more simply and equivalent in meaning:

myArraySwap[hcount].counterParty

(without the leading ampersand).

Also, scanf can fail, so be sure you check the return value.

That'll do to be going on with.

<snip>
 
R

Richard

Richard Heathfield said:
(e-mail address removed) said:


I suggest you get a better book. From the look of your code, Mr Horton
needs to learn C before he tries writing a book about it.

Does your arrogance know no bounds? Did you never see bad code written
by people who read K&R?
 
C

Christopher Benson-Manica

Does your arrogance know no bounds? Did you never see bad code written
by people who read K&R?

Anyone who would write

void main()

after reading K&R (as OP and, like as not, Mr. Horton did), should
invest in a pair of glasses. Mr. Horton would neither be the first
nor the last would-be textbook author to make that particular error,
and it does not inspire confidence in the other material presented in
Mr. Horton's text.
 
N

Nick Keighley

Does your arrogance know no bounds? Did you never see bad code written
by people who read K&R?

assuming the code is a fair reflection of the book, there should
*not* be quite so many "school boy howlers" in a short peice of
code intended for teaching purposes.

Yes, we can all write bad code but code for teaching purposes
should be reviewed by at least two pairs of competent eyes.

(this is not directed at the original poster, who is quite entitled
to make mistakes like this at this stage)
 
S

santosh

Christopher said:
Anyone who would write

void main()

after reading K&R (as OP and, like as not, Mr. Horton did), should
invest in a pair of glasses. Mr. Horton would neither be the first
nor the last would-be textbook author to make that particular error,
and it does not inspire confidence in the other material presented in
Mr. Horton's text.

Here, a so-called "premier" institute for IT, which boasts of
"partnership" with MS, Sun, Oracle etc., uses void main(), K&R style
function declarations, gets(), scanf("%s", ...), char to recieve the
return value of fgetc() and family, and says that all arrays are
automatically terminated with a nul character.

The list is not exhaustive. Can you believe it? With such a quality in
pedagogy from frontline institutes, I'm not surprised at the questions
we get here.
 
C

Christopher Benson-Manica

santosh said:
The list is not exhaustive. Can you believe it? With such a quality in
pedagogy from frontline institutes, I'm not surprised at the questions
we get here.

My institution (Georgia Tech) didn't place a lot of weight on strict
conformance, but there were certainly no egregious violations on the
order of void main().
 
C

CBFalconer

I have written the following code with the help of Ivor Horton's
Beginning C :

// Structures, Arrays of Structures.

#include "stdafx.h"
#include "stdio.h"
#define MY_ARRAY 15
#define BASIS 360

struct swap
{
char counterParty[10];
float notional;
float intRate;
int busDays;
//int basis = 360;
float flows;
};

void main()
{

/*Arrays of Structures*/

swap myArraySwap[MY_ARRAY];

int hcount = 0;
int i = 0;
//='\0';

// for (hcount = 0; hcount < 5 ; hcount++ )
do
{
char test = NULL;
printf("\nWould you like to enter Swaps (Y or N)?:");

test = getchar();

if (test != 'Y') //|| test !='y')
break;

printf("\nEnter CounterParty:");
scanf("%s", &myArraySwap[hcount].counterParty );
printf("\nEnter Notional :" );
scanf("%f", &myArraySwap[hcount].notional );
printf("\nEnter Interest Rate:" );
scanf("%f", &myArraySwap[hcount].intRate );
printf("\nEnter Number of days:" );
scanf("%d", &myArraySwap[hcount].busDays );
myArraySwap[hcount].flows = (myArraySwap[hcount].notional *
(myArraySwap[hcount].intRate/100.0f) *
((float)myArraySwap[hcount].busDays/360.0f));

hcount++;
}
while (hcount < 5);

for (i=0 ; i < hcount ; i++)
{
printf("\nCounter Party: %s",myArraySwap[hcount].counterParty);
printf("\nFlows %f", myArraySwap.flows);
printf("\nDone");
}

}


Errors detected:

[1] c:\c\junk>cc junk.c
junk.c:1:20: stdafx.h: No such file or directory (ENOENT)
junk.c:12: parse error before '/' token
junk.c:12: warning: no semicolon at end of struct or union
junk.c:14: parse error before '}' token
junk.c:14: warning: ISO C does not allow extra `;' outside of a
functio
junk.c:17: warning: return type of `main' is not `int'
junk.c: In function `main':
junk.c:21: `swap' undeclared (first use in this function)
junk.c:21: (Each undeclared identifier is reported only once
junk.c:21: for each function it appears in.)
junk.c:21: parse error before "myArraySwap"
junk.c:26: parse error before '/' token
junk.c:28: parse error before ')' token
junk.c:34: `test' undeclared (first use in this function)
junk.c:36: parse error before '/' token
junk.c:36: warning: empty body in an if-statement
junk.c:40: `myArraySwap' undeclared (first use in this function)
junk.c:25: warning: unused variable `i'
junk.c:28: warning: statement with no effect
junk.c: At top level:
junk.c:53: parse error before "while"
junk.c:58: parse error before string constant
junk.c:58: warning: type defaults to `int' in declaration of
`printf'
junk.c:58: warning: conflicting types for built-in function
`printf'
junk.c:58: ISO C forbids data definition with no type or storage
class
junk.c:59: parse error before string constant
junk.c:59: warning: type defaults to `int' in declaration of
`printf'
junk.c:59: ISO C forbids data definition with no type or storage
class

After correcting the foolish use of // comments we get:

[1] c:\c\junk>cc junk.c
junk.c:1:20: stdafx.h: No such file or directory (ENOENT)
junk.c:17: warning: return type of `main' is not `int'
junk.c: In function `main':
junk.c:21: `swap' undeclared (first use in this function)
junk.c:21: (Each undeclared identifier is reported only once
junk.c:21: for each function it appears in.)
junk.c:21: parse error before "myArraySwap"
junk.c:40: `myArraySwap' undeclared (first use in this function)

After you correct these errors so that the code is compilable in
ISO standard C, repost and we will try to help you. Read the
documentation for your system to find out how to make it compile
standard C.

I had thought that Horton was fairly sound. Looks like I may need
to revise that opinion.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
C

CBFalconer

Richard said:
Richard said:

I don't believe so, no. Why do you ask?

I believe it is bounded slightly below my own level. However in
the limit the levels may be the same. It all depends on epsilon.

Has Richard<noname> deliberately selected his name with the
intention of making him hard to PLONK?

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
K

Keith Thompson

I have written the following code with the help of Ivor Horton's
Beginning C :

// Structures, Arrays of Structures.
[snip]

struct swap
{
char counterParty[10];
float notional;
float intRate;
int busDays;
//int basis = 360;
float flows;
};
[snip]

swap myArraySwap[MY_ARRAY];

[snip]

Here's an error that I don't think anyone else has pointed out, at
least not explicitly. You declare a type called "struct swap", but
you attempt to refer to it as "swap". If your code compiles with this
error, you're probably compiling it as C++, which could mask other
errors as well. First, find out how to tell your compiler to compile
C rather than C++; if you succeed, it will give you an error message
saying that the type "swap" is undeclared. Then change the line
swap myArraySwap[MY_ARRAY];
to
struct swap myArraySwap[MY_ARRAY];

And a style point: The name "MY_ARRAY" implies that it refers to an
array; in fact, it expands to a number. Call it "MY_ARRAY_LENGTH" or
something like that. The compiler doesn't care whether your
identifiers make any sense, but your readers do (that includes you
reading your own code later on).
 
C

CBFalconer

D

David Thompson

On 15 Feb, 09:06, "(e-mail address removed)" <[email protected]>
wrote:
struct swap
{
char counterParty[10];
float notional;

prefer double to float unless you *really* need to save space.
float intRate;
int busDays;
//int basis = 360;
float flows;
};

But if you do ...
printf("\nEnter Notional :" );
scanf("%f", &myArraySwap[hcount].notional );
printf("\nEnter Interest Rate:" );
scanf("%f", &myArraySwap[hcount].intRate );

.... change those to %lf .
printf("\nEnter Number of days:" );
scanf("%d", &myArraySwap[hcount].busDays );

And in all cases check the return value from *scanf; as well as using
a limit on %s (or %[..]) as already noted elsethread and snipped.
myArraySwap[hcount].flows = (myArraySwap[hcount].notional *
(myArraySwap[hcount].intRate/100.0f) *
((float)myArraySwap[hcount].busDays/360.0f));
And for double arithmetic preferably use double constants (no suffix
f) although small integer values like these are exact in either (any)
floating precision.

Even in float (single) that cast isn't needed; intvalue / floatconst
promotes the int to float before dividing, and intvalue / doubleconst
promotes it to double.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 
P

pflink

(e-mail address removed) wrote:

<snip>

I've been studying C for a little while, using online tutorials. I've
read mention in several places against using the scanf function. Is there
an introductory tutorial out there that does NOT introduce this and
instructs the use of another function or array ??

Thanks
 
S

santosh

(e-mail address removed) wrote:

<snip>

I've been studying C for a little while, using online tutorials. I've
read mention in several places against using the scanf function. Is there
an introductory tutorial out there that does NOT introduce this and
instructs the use of another function or array ??

Thanks

To my knowledge no. The problem is that scanf is easy to introduce to
beginners. It's straightforward to use. The fact that it can cause
undefined behaviour if not used very carefully is something that is,
or should be, taught during the middle of the course. Alternatives are
suggested and the student is expected to use one himself.

In books and tutorials it's very convinient to use scanf for the sake
of conciseness and keeping clutter to a minimum in code samples,
(something that's important for a printed book).

fgets combined with a few other conversion functions like strtol,
strtod etc., is a good alternative. Many people also write their own
line input routines; CBFalconer has a version called ggets on his page.
 
D

David Wade

(e-mail address removed) wrote:

<snip>

I've been studying C for a little while, using online tutorials. I've
read mention in several places against using the scanf function. Is there
an introductory tutorial out there that does NOT introduce this and
instructs the use of another function or array ??

Thanks

I tend to use fgets() , followed by strtok() to split the like where I want,
then strtol() etc to convert the data to variables.
 
R

Richard Heathfield

(e-mail address removed) said:
(e-mail address removed) wrote:

<snip>

I've been studying C for a little while, using online tutorials.
I've
read mention in several places against using the scanf function. Is
there an introductory tutorial out there that does NOT introduce this
and instructs the use of another function or array ??

Not yet, as far as I know. That situation may change (if I ever find the
time). There certainly *should* be such a tutorial.
 
M

Malcolm McLean

(e-mail address removed) wrote:

<snip>

I've been studying C for a little while, using online tutorials. I've
read mention in several places against using the scanf function. Is there
an introductory tutorial out there that does NOT introduce this and
instructs the use of another function or array ??
Input is one of the most basic things that a program has to do.
It is also inherently difficult if the programmer does not control what is
entered.

For instance the input 100000000000000000000000 will overflow an integer and
be approximated in a floating point type. However it is a number, it may
even be a valid number for the problem domain. So you have to be very
careful in what you tell the user.
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top