2

I'm trying to write a program that reads a maximum of 8 bank account information and store them dynamically in a linked list. I wrote a function to calculate the average of all the entered bank accounts' balances but when I try to call that function no output is produced. can you please help me figure out where the problem is?

#include <stdio.h>

#include <stdlib.h>

//node structure
typedef struct node {
   int no;
   char name[20];
   float total;
   struct node * nextptr;
}
account;

//int for division of total to find the average
static int t;

//adding accounts function
account * addaccount(account * temp) {
   fflush(stdin);
   printf("Enter the account name: \n");
   gets(temp -> name);
   printf("Enter the account number: \n");
   scanf("%d", & temp -> no);
   printf("Enter the account balance: \n");
   scanf("%f", & temp -> total);
   t++; // used for finding the average 
   return temp;
}

// function for calculating the average
float sum(account * temp) {
   float average = 1.0, sum = 0.0;
   int i;
   account * start;
   temp = start;
   for (i = 0; i < t; i++) {
      sum += temp -> total;
      temp = temp -> nextptr;
   }
   average = sum / t;
   return average;
}

int main() {
   int selection;
   account * start = NULL;
   account * save, * temp;
   account * ptr;
   ptr = (account * ) malloc(sizeof(account) * 8);
   do {
      //Menu
      printf("\n1.Adding account\n");
      printf("2.Find the average of the added accounts' balances\n");
      printf("3.Exit\n");
      scanf("%d", & selection);
      switch (selection) {
      case 1: {
         if (ptr == NULL)
            ptr = (account * ) realloc(ptr, sizeof(account));
         save = addaccount(ptr);
         if (start == NULL) {
            start = save;
            start -> nextptr = NULL;
         } else {
            temp = start;
            while (temp -> nextptr != NULL)
               temp = temp -> nextptr;
            temp -> nextptr = save;
            save -> nextptr = NULL;
         }
         break;
      }
      case 2: {
         float avg;
         avg = sum(temp);
         printf("%f", avg);
         break;
      }
      case 3: {
         temp = start;
         while (temp != NULL) {
            free(temp);
            temp = temp -> nextptr;
         }
         break;
      }
      }
   } while (selection != 4);
   return 0;
}
Buffer
  • 35
  • 8
  • 1
    Now would be a good time to learn to debug your own code. Run your program in a debugger and trace the program flow and variable values as it runs. [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – kaylum Apr 29 '22 at 00:20
  • 2
    Please fix your code indentation. Also, you're essentially pre-allocating space for all 8 accounts in an array. Either do this and then use simple array indexing instead of the linked list or ditch the idea of pre-allocating all 8 and allocate them one-by-one as needed (which is what you would do in a real linked list). – jarmod Apr 29 '22 at 00:22
  • 1
    Mustafa, Who or what text suggested using `fflush(stdin);`? – chux - Reinstate Monica Apr 29 '22 at 00:55
  • @chux-ReinstateMonica Probably to discard a `\n` left behind by `scanf("%d", &selection);` – Remy Lebeau Apr 29 '22 at 01:01
  • @RemyLebeau No doubt. [Question](https://stackoverflow.com/questions/72051493/problem-in-storing-data-dynamically-in-linked-list?noredirect=1#comment127311908_72051493) still remains. – chux - Reinstate Monica Apr 29 '22 at 01:53
  • 1
    @chux-ReinstateMonica Our professor in university suggested it. – Buffer Apr 29 '22 at 04:00
  • 1
    @Mustafa Note that [`gets()`](https://stackoverflow.com/q/1694036/2410359) is no longer part of C and `fflush(stdin)` has its [troubles](https://stackoverflow.com/a/18170435/2410359). Gauge your instruction accordingly. – chux - Reinstate Monica Apr 29 '22 at 10:16

2 Answers2

5

Look here

// function for calculating the average
float sum(account* temp) {
    float average = 1.0, sum = 0.0;
    int i;
    account* start; <<<==== a random value
    temp = start;   <<<=== over write the parameter of this function with a random value
    for (i = 0; i < t; i++) {
        sum += temp->total;
        temp = temp->nextptr;
    }
    average = sum / t;
    return average;
}

Not sure what you are trying to do here - but that is for sure wrong

pm100
  • 48,078
  • 23
  • 82
  • 145
  • That's exactly where the problem was, I had to assign the start pointer value to the temp pointer from the main function not from inside the sum function. It's working now thank you. – Buffer Apr 29 '22 at 00:54
3

There are quite a number of problems with your code:

  • you say you want a maximum of 8 accounts, but there is no such limit being imposed by the code.

  • in sum() (which is misnamed, BTW), you are not looping through the nodes correctly, because the temp = start; assignment is backwards. start is uninitialized, and then temp is used inside the loop, thus invoking undefined behavior. You don't actually need the start variable at all, since you can simply increment the account* temp parameter.

  • in main(), you are initially pointing ptr to an array of 8 accounts, but if the user enters 1 on your menu, and ptr is NULL (which it would not be unless that initial malloc() failed), then you are pointing ptr to a single account. If your goal is to allow the user to enter an arbitrary number of accounts, your list management is all wrong.

    Worse, every time the user enters 1 on your menu, you are calling addaccount() on the 1st account in the array, and addaccount() simply populates the specified account with data. So, you are not actually creating a new account and adding it to the list, at all. You are just linking the 1st account back to itself, over and over.

  • if the user enters 2 on your menu, you are calling sum() on the last account created by 1. If no account has been created yet, your code will crash since temp is uninitialized at that point. You need to call the function on the first account instead, so it can iterate the whole list.

  • if the user enters 3 on your menu, the code tries to free() individual accounts, but you did not actually malloc() individual accounts to begin with. You are trying to store accounts in an array instead, so you would just need to free() the array instead.

    Also, your loop is checking for selection != 4, but your menu doesn't have an option 4. You should be checking for selection != 3 instead.

With that said, try something more like this:

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

//node structure
typedef struct node {
   int no;
   char name[20];
   float total;
   struct node * nextptr;
}
account;

//adding accounts function
account* addaccount() {
   account *temp = malloc(sizeof(account));
   if (temp == NULL) {
      printf("Unable to create new account\n");
      return NULL;
   }
   fflush(stdin);
   printf("Enter the account name: \n");
   gets(temp->name);
   printf("Enter the account number: \n");
   scanf("%d", &temp->no);
   printf("Enter the account balance: \n");
   scanf("%f", &temp->total);
   temp->nextptr = NULL;
   return temp;
}

// function for calculating the average
float average(account* start) {
   if (start == NULL) return 0.0;
   float sum = 0.0;
   int t = 0;
   do {
      sum += start->total;
      start = start->nextptr;
      ++t;
   }
   while (start != NULL);
   return sum / t;
}

int main() {
   int selection;
   account *start = NULL, *last = NULL, *temp;

   do {
      //Menu
      printf("1.Adding account\n");
      printf("2.Find the average of the added accounts' balances\n");
      printf("3.Exit\n");
      scanf("%d", &selection);
      switch (selection) {
         case 1: {
            if ((temp = addaccount()) == NULL) break;
            if (start == NULL)
               start = temp;
            else
               last->nextptr = temp;
            last = temp;
            break;
         }
         case 2: {
            printf("%f\n", average(start));
            break;
         }
      }
   } while (selection != 3);

   temp = start;
   while (temp != NULL) {
      free(temp);
      temp = temp -> nextptr;
   }

   return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770