Odd linked list runtime error

B

Brian Dude

Hello, I'm really at a loss as to what's going wrong with my code. I
have it posted below. How it appears is how I had it originally. I've
deleted all error-checking for simplicity:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int n;
struct data2{
double x;
double y;
int index;
struct data2 *next;
}*first,*current,*hold;

do{
printf("How many pairs of data? ");
scanf("%d",&n);
fflush(stdin);
}while(n<2);


first=malloc(sizeof(struct data2));
first->index=0;
puts("\nEnter data pairs separated by spaces,\nentries separated by
ENTER:");
current=first;

while(1){
scanf("%lf %lf",&current->x,&current->y);
fflush(stdin);
current->index++;
current->next=malloc(sizeof(struct data2));
if(current->index >= n){
free(current->next);
current->next=NULL;
break;
}
current=current->next;
}

putchar('\n');
/*Quick verification...*/
current=first;
while(current){
printf("%lf : %lf\n",current->x,current->y);
current=current->next;
}

for(current=first;current!=NULL;current=hold){
hold=current->next;
free(current);
}
return 0;
}

Everything runs fine up until the first scanf() of the while loop. When
it reaches that statement, I get the following error message:

scanf : floating point formats not linked
Abnormal program termination


However, if I add the following declarations to the top:

double X,Y;

and replace the scanf() parameters with:

scanf("%lf %lf",&X,&Y);
current->x=X;
current->y=Y;

The numbers get entered into the list just fine... But incrementing
current->index goes awry and I get garbage numbers, so similarly, I have
to add to my declarations:

int i;

and work it into the while loop:

i++;
current->index=i;

and again it runs fine.
Another odd aspect to it. If I change only one of the parameters, say:

scanf("%lf %lf",&X,&current->y);
current->x=X;

it runs fine (swapping the other two parameters works as well).

If there was no floating point library linked in, wouldn't I get an
error at link time?

TIA,
Brian Dude
 
V

vippstar

Brian Dude said:


You'd have done better to leave the error checking in.



The behaviour of fflush on input streams is undefined.


You're using a C90 implementation, so in printf (not in scanf, but in
printf) use %f for double. %lf means double in scanf, but is meaningless
in printf.

I think you mean the l length modifier is meaningless in printf's f
conversion specifier because the effect is the same without it.
lf is certainly not meaningless in printf (it behaves like f)
 
G

gw7rib

(snip)

Richard's covered your question about linking, and pointed out your
fflush() error, but there's still your question about index. The
answer seems to be that you're not setting it properly.
        first=malloc(sizeof(struct data2));
        first->index=0;

So, first -> index is set to 0, before the loop starts.
        puts("\nEnter data pairs separated by spaces,\nentries separated by
ENTER:");
        current=first;

        while(1){
                scanf("%lf %lf",&current->x,&current->y);
                fflush(stdin);
                current->index++;

The first time through, this will increase first -> index to 1.
                current->next=malloc(sizeof(struct data2));
                if(current->index >= n){
                        free(current->next);
                        current->next=NULL;
                        break;

(Just as a side point, this idea of malloc'ing a structure that you
don't need, and then immediately free'ing it again, is somewhat
strange. But it does seem to work.)
                }
                current=current->next;

And now "current" points to another data2 - but have you set the value
of index in that one? As far as I can see, you haven't.
        }

Hope that helps.
Paul.
 
B

Ben Bacarisse

Brian Dude said:
Hello, I'm really at a loss as to what's going wrong with my code. I
have it posted below. How it appears is how I had it originally. I've
deleted all error-checking for simplicity:

The error is fixed, so you may have gone, but in case you continue to
read there are a few things I'd say about this code...

int main(void)
{
int n;
struct data2{
double x;
double y;
int index;
struct data2 *next;
}*first,*current,*hold;

do{
printf("How many pairs of data? ");
scanf("%d",&n);
fflush(stdin);
}while(n<2);

Computers are good at counting so don't ask the user to count the data
as well. The great thing about a linked list is it can grow, so you
don't need to know how many pairs there are before you read them. It
is almost always better to avoid counted input though there are
exceptions.
first=malloc(sizeof(struct data2));
first->index=0;

Code often ends up simpler if you can deal with "degenerate" cases line
no input (and thus an empty list). I know in this case you want at
least two pairs, but the code if often simpler if you accept and empty
(or shorter list) and complain later that is does not meet your needs.
puts("\nEnter data pairs separated by spaces,\nentries separated by
ENTER:");

This instruction is not enforced. The user can enter the data in lots
of other ways as well and you can't tell. Better to tell them just to
"enter %d numbers" (give n*2 for the %d output) and leave it at that.
current=first;

while(1){

I am not a fan of loops like this because is hides (or at least delays
the explanation of) the reasons for stopping. You have an error
(already explained by someone else) with the way you count entries so
I can't write a better test without adding new variables, but I would
write:

while (scanf("%lf %lf", &x, &y) == 2)

because I would not be using counted input.

In short, I'd do something more like this (not tested as per tradition
and with error checking removed to match your pattern):

double x, y;
int n = 0;
struct node2 *first = NULL;
struct node2 **head_ptr = &first;

printf("Enter at least 2 pairs of numbers:\n");
while (scanf("%lf %lf", &x, &y) == 2) {
struct node2 *np = malloc(sizeof *np);
np->x = x; np->y = y;
np->index = n++;
np->next = NULL;
*head_ptr = np;
head_ptr = &np->next;
}
if (n < 2)
fprintf(stderr, "Not enough data.\n");

The stuff with the struct node ** may be more that want to think about
right now but it never hurts to see other ways to do stuff.
 
B

Brian Dude

Richard said:
Brian Dude said:
[snip]
Everything runs fine up until the first scanf() of the while loop. When
it reaches that statement, I get the following error message:

scanf : floating point formats not linked
Abnormal program termination

Borland, right?

Yes, 'tis Borland :p And an old one too - 4.52.
Just add this to main:

double what_a_silly_borland_bug = 3.14159;

That should fix your problem. Bizarre, huh?

I actually had to expand on your idea to get it to work. Simply adding
the declaration did not work. So I thought I would put it into a
pointless printf() statement before data entry:

printf("%f\n",what_a_silly_borland_bug*4.1);

That still didn't work. So I thought to really make sure the floating
point code gets worked in I included math.h and used a function from it:

printf("%f\n",pow(what_a_silly_borland_bug,4.1));

And now it runs fine ...Very bizarre, but thank you for pointing me in
the right direction!

Brian
 
B

Brian Dude

(snip)

Richard's covered your question about linking, and pointed out your
fflush() error, but there's still your question about index. The
answer seems to be that you're not setting it properly.


So, first -> index is set to 0, before the loop starts.


The first time through, this will increase first -> index to 1.


(Just as a side point, this idea of malloc'ing a structure that you
don't need, and then immediately free'ing it again, is somewhat
strange. But it does seem to work.)

Now that you mention it, it is a little strange. I just threw this
program together quickly for myself...
And now "current" points to another data2 - but have you set the value
of index in that one? As far as I can see, you haven't.


Hope that helps.
Paul.

D'oh! Yes it does help, thank you. I forgot I was incrementing a new
variable through each loop iteration.
 
B

Brian Dude

Ben said:
The error is fixed, so you may have gone, but in case you continue to
read there are a few things I'd say about this code...



Computers are good at counting so don't ask the user to count the data
as well. The great thing about a linked list is it can grow, so you
don't need to know how many pairs there are before you read them. It
is almost always better to avoid counted input though there are
exceptions.


Code often ends up simpler if you can deal with "degenerate" cases line
no input (and thus an empty list). I know in this case you want at
least two pairs, but the code if often simpler if you accept and empty
(or shorter list) and complain later that is does not meet your needs.


This instruction is not enforced. The user can enter the data in lots
of other ways as well and you can't tell. Better to tell them just to
"enter %d numbers" (give n*2 for the %d output) and leave it at that.


I am not a fan of loops like this because is hides (or at least delays
the explanation of) the reasons for stopping. You have an error
(already explained by someone else) with the way you count entries so
I can't write a better test without adding new variables, but I would
write:

while (scanf("%lf %lf", &x, &y) == 2)

because I would not be using counted input.

In short, I'd do something more like this (not tested as per tradition
and with error checking removed to match your pattern):

double x, y;
int n = 0;
struct node2 *first = NULL;
struct node2 **head_ptr = &first;

printf("Enter at least 2 pairs of numbers:\n");
while (scanf("%lf %lf", &x, &y) == 2) {
struct node2 *np = malloc(sizeof *np);
np->x = x; np->y = y;
np->index = n++;
np->next = NULL;
*head_ptr = np;
head_ptr = &np->next;
}
if (n < 2)
fprintf(stderr, "Not enough data.\n");

The stuff with the struct node ** may be more that want to think about
right now but it never hurts to see other ways to do stuff.

I don't mind the suggestions at all. I just do this as a hobby, so I'm
quite out of the loop with the evolution of the language, but I do learn
a lot from these groups. And I'm always interested in bettering my
techniques. Thanks!

Brian
 

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,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top