[comp.lang.c] I need help with this structure loop

cee1@ra.MsState.Edu (The Chuckmeister) (05/28/91)

Ok here goes a biggee problem for me, taht I have been working on for DAYS.

The following code is more or less like a program 'savebook.c' in "C: Step
by Step" by the Waite Group, and I had this same problem as in this code,
so i decided to completely start over and write my own code to try to see
my problem.

Ok, easy enough, I set up my structure to read in the author, title, and
year published of, in this case, 5 books and print them out. Simple.
Well when it does the initial runthru of asking for the info, it does fine.
However, on the first looping and the successive ones, it asks for the
title, however, it does not give room or anything for it, it goes ahead
and asks for the author in the space for the title, and teh year works fine.
Does anyone see an obvious flaw,.. is either scanf or gets or puts or printf
adding an extra linefeed.. thats the only thing I can come up with.

So when It finishes teh 'five' it prints out the author and and date [if I
remember correctly] i have run so many test copies.

I am using Borland C++ 2.0, and have tried it with UNIX C, having deleted
the clrscr() along with #include <conio.h> which I guess is incompatible with
UNIX. Also, I tried to doctor it up trying to catch my error by putting
periods in the field and the series of '\b'.. ANyone know an easier way to
do that?

Ok, most important.. does ANYONE see or know whats going wrong with the code.

Oh, back to thinking of what the actual code from my C book .. it gave the
error: 'scanf : floating point formats not linked' and Abormal Prog. Term.

What the heck did that, I used:

scanf("%f", &libry[count++].value);

value was variablized, or whatever the term as float in the structure:

struct book {
     ...
     float value;
     };

then :

main()
{
	struct book libry[MAXBKS];  /* MAXBKS defined as 10 */
        int count = 0;
        ...

then, inside the loop of asking for, yes, title, author, and in this case value
it shoots that error when it gets to the scanf line.. Sheezz.

I could upload that source if needed, but mainly I am after my first question.
Thanks, any help please send to ---> cee1@ra.msstate.edu <--- Thanks.

----------------BEGIN-------CUT-HERE------------BEGIN------------

/* Checks to see if Borland C++ has a bug 
 */
#include <stdio.h>
#include <conio.h>
#define MAXTIT 50
#define MAXNUMBOOKS 5

struct books {
	char author[MAXTIT];
	char title[MAXTIT];
	int year;
	};

main()
{
	struct books inventory[MAXNUMBOOKS];
	int count = 0;
	int index;

	clrscr();
	puts("           Welcome to the Library Connection");
	puts("                by Charles Evans, 1991");
	puts("");
	while ( count < MAXNUMBOOKS)
	{
		puts("Please enter the author.");
		printf("[..............................]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
		gets(inventory[count].author);
		puts("Now, please enter the title.");
		printf("[..............................]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
		gets(inventory[count].title);
		puts("Finally, enter the year published.");
		printf("[....]\b\b\b\b\b");
		scanf("%d", &inventory[count].year);
		count++;
	}
	clrscr();
	printf("Inventory:\n");
	for ( index = 0; index < 5; index++)
		printf("%s by %s, %d.\n",inventory[index].title,inventory[index].author,inventory[index].year);
	getch();
	return 0;
}
}

bobb@netcom.COM (Bob Beaulieu) (05/29/91)

In article <789@ra.MsState.Edu>, cee1@ra.MsState.Edu (The Chuckmeister) writes:
> 		puts("Finally, enter the year published.");
> 		printf("[....]\b\b\b\b\b");
> 		scanf("%d", &inventory[count].year);

                fflush(stdin); 
              
This addition lets your program work just fine for me. I believe another scanf
would do the same job (get rid of the newline);

Hope it help!

bobb
-- 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|                              Bob Beaulieu                            |
|                              San Jose, CA.                           |
|                             (408) 723-0556                           | 
|                             bobb@netcom.com                          |
|                   {apple,amdahl,claris}!netcom!bobb                  |
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/02/91)

In article <789@ra.MsState.Edu>, cee1@ra.MsState.Edu (The Chuckmeister) writes:

> [program reading stuff in a loop, first time around works fine,
> second time around skips first question]

> Oh, back to thinking of what the actual code from my C book .. it
> gave the error: 'scanf : floating point formats not linked' and
> Abormal Prog. Term.

> What the heck did that, I used:

> scanf("%f", &libry[count++].value);

The problem here is that the DOS compiler you used tries to be smart
and not bring in the floating-point support unless you use it.
However, you didn't do any floating-point operations the compiler could
see; all the floating-point code was hidden in scanf().

A legacy of machines with tiny memories....

I've stripped out most of this code; only the relevant bits remain.

> 	while ( count < MAXNUMBOOKS)
> 	{
> 		gets(inventory[count].author);
> 		gets(inventory[count].title);
> 		scanf("%d", &inventory[count].year);
> 	}

The problem is that the scanf is *not* reading the newline at the end
of that line.  That remains in the stdio buffer for the gets() at the
beginning of the next loop to trip over.

Generally you don't want to mix line-based I/O (like gets) with
format-based I/O (like scanf).  You should probably replace the scanf
with a call to fgets and then some sort of conversion routine, perhaps
a call to sscanf.  Which leads me into my next point....

You shouldn't be using gets().  gets() should not exist; please pretend
it doesn't.  Those who have to maintain your code will thank you.  Use
fgets() instead.

The reason for this is that it has no checking to prevent overrunning
the buffer passed to it, and by its very design *cannot* have any such
checking.  As soon as the day comes when someone types more input than
your buffer is prepared to handle, your program will fail in strange
and mysterious ways - anything from coming crashing down to giving
sutbly wrong answers.  gets() was the cause of one of the bugs
exploited by the RTM Internet worm of November '88, for precisely the
reasons I just outlined.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

torek@elf.ee.lbl.gov (Chris Torek) (06/02/91)

In article <1991Jun1.205224.27309@thunder.mcrcim.mcgill.edu>
mouse@thunder.mcrcim.mcgill.edu (der Mouse) writes:
>You shouldn't be using gets(). ... Use fgets() instead.
>The reason for this is that it has no checking to prevent overrunning
>the buffer passed to it, and by its very design *cannot* have any such
>checking.

Well, technically, it *can*; Saber-C is one example.  However, it is
fairly expensive to make it check (`gets' itself does not do the checking
in Saber, but rather the underlying implementation; and the checking
vanishes when you use precompiled code), and most implementations will
not, so the above remains good advice.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov