-2

Okay, i have tried all solutions suggested but still no joy. The code I have so far is

`struct account* accounts = (struct account*)malloc(sizeof(struct account));

while (1) {
    printf(" 1. New Account\n 2. Close Account\n 3. Access Account\n 4. quit\n");

    int choice = 0;
    scanf("%d", &choice);
    int numberAccounts = 0;


    switch(choice){
                case 1:
                    accounts = realloc(accounts, sizeof(struct account) * (numberAccounts + 2));
                    newAccount(accounts , sizeof *accounts, numberAccounts);
                    numberAccounts++;
                    break;
                case 2:
                    printf("first name = %s\n", accounts[0].firstName);
                    printf("first name = %s\n", accounts[1].firstName);
                    break;
                case 4: exit(1);
            }

void newAccount(struct account *accounts , int size , int numberAccounts) {





    printf("please enter first name\n");
    scanf("%s", accounts[numberAccounts].firstName);

    printf("please enter last name\n");
    scanf("%s", accounts[numberAccounts].lastName);

    printf("please enter overdraft\n");
    scanf("%d", &accounts[numberAccounts].overdraft);

    accounts[numberAccounts].accountNumber = (100 + numberAccounts);

    accounts[numberAccounts].balance = 0.0;

}

It still spits out garbage for accounts[1]. However I did do a stripped down version, same code, but with less crap and that works fine. I dont understand it. its the same.

struct account{
char *firstName;

};

int main(int argc, char** argv) {

struct account* accounts = (struct account*)malloc(sizeof(struct account));
accounts[0].firstName = "ben";
accounts = realloc(accounts, sizeof(struct account) * 2);
accounts[1].firstName = "tori";
printf("accounts[0] = %s\n", accounts[0].firstName);
printf("accounts[1] = %s\n", accounts[1].firstName);

The output from the first code is

first name = tori first name = lication\debug

and the second

first name = ben first name = tori as it should be. inputs were ben first, tori second for 2 accounts. weird

`

Ben Rider
  • 25
  • 2
  • 11
    Don't post images of text. Post the text. – Irelia Nov 12 '19 at 17:22
  • `sizeof *accounts` results in the size of ONE account object. – joop Nov 12 '19 at 17:26
  • 1
    `sizeof(*accounts)` is the size of one account. `sizeof(struct account)` is the size of one account,, so `realloc` is creating size of 2 accounts... is that what you want? – yano Nov 12 '19 at 17:26
  • Soz, first time I've used this site – Ben Rider Nov 12 '19 at 17:27
  • Your `sizeof` usage/logic is broken. it doesn't do what you think it does. you seem to be under the impression that `sizeof *accounts` will increase as you `realloc`, which is not true. And the first line of `newAccount` is broken from inception. – WhozCraig Nov 12 '19 at 17:27
  • Yes, just want to increase by one every time I create a new account – Ben Rider Nov 12 '19 at 17:29
  • 1
    you're only increasing by 1 with the first call to `realloc`. The argument to `realloc` resolves to two accounts every time. To increase by one each time, you need to keep track of the number of accounts in a separate variable, then so something like `realloc(accounts, numAccounts++ * sizeof(*accounts));` – yano Nov 12 '19 at 17:31
  • The int n is redundant, it was from a previous draft, forgot to erase – Ben Rider Nov 12 '19 at 17:32
  • @BenRider The question isn't bad, but I suspect the down-votes are due to people not being able to copy paste the text in order to make suggestions. We don't want to type out all the code in an answer. – NTDLS Nov 12 '19 at 17:34
  • Yano will try that when I get to uni, ta – Ben Rider Nov 12 '19 at 17:35

1 Answers1

2

As the others have pointed out in the comments, the sizeof(accounts *) will not increase as you allocate more ram. It is just returning the size of a pointer.

Personally, I'd keep track of the number of allocated accounts so that you can easily reallocate later - as such:

int accountsAllocated = 1;

//Initial allocation.
struct account* accounts = (struct account*)malloc(sizeof(struct account));

accountsAllocated += 10; //If we we want to make room for 10 new accounts.

//Reallocate using the size of the pointer multiplied by the count of them.
accounts = (struct account*)realloc(accounts, sizeof(struct account) * accountsAllocated);

This is a tweaked, working copy your code.

#define _CRT_SECURE_NO_WARNINGS

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

struct account {
    char firstName[256];
    char lastName[256];
    int overdraft;
    int accountNumber;
    double balance;
};

void newAccount(account* accounts, int numberAccounts);

int main()
{
    account* accounts = (account*)malloc(sizeof(struct account));
    int numberAccounts = 0;

    while (1)
    {
        printf(" 1. New Account\n 2. Close Account\n 3. Access Account\n 4. Quit\n");

        int choice = 0;
        scanf("%d", &choice);

        switch (choice)
        {
        case 1:
            accounts = (account*)realloc(accounts, sizeof(struct account) * (numberAccounts + 1));
            newAccount(accounts, numberAccounts);
            numberAccounts++;
            break;
        case 2:
            printf("Not implemented...\n");
            break;
        case 3:
            printf("Which account position? (%d - %d)\n", 0, numberAccounts - 1);
            scanf("%d", &choice);

            if (choice >= 0 && choice < numberAccounts)
            {
                account* localAccount = &accounts[choice];

                printf("Acount = %d\n", localAccount->accountNumber);
                printf("First Name = %s\n", localAccount->firstName);
                printf("Last Name = %s\n", localAccount->lastName);
                printf("Balance = %.2f\n", localAccount->balance);
                printf("Overdraft = %d\n", localAccount->overdraft);
            }
            else
            {
                printf("Invalid account position!\n");
            }
            break;
        case 4:
            exit(1);
        default:
            printf("Invalid command!\n");
            break;
        }
        printf("----------------------------------------------------------------------\n");
    }
}

void newAccount(struct account* accounts, int numberAccounts)
{
    //Create a local pointer, just so we don't have to reference the array position every time below.
    account *localAccount = &accounts[numberAccounts];

    //Zero out the memory used by the account.
    memset(localAccount, 0, sizeof(account));

    printf("please enter first name\n");
    scanf("%s", localAccount->firstName);

    printf("please enter last name\n");
    scanf("%s", localAccount->lastName);

    printf("please enter overdraft\n");
    scanf("%d", &localAccount->overdraft);

    localAccount->accountNumber = (100 + numberAccounts);

    localAccount->balance = 0.0;
}
NTDLS
  • 4,757
  • 4
  • 44
  • 70
  • 1
    also no need to cast the results of `malloc` and friends, although I get less heartburn from that than most folks on SO: https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – yano Nov 12 '19 at 17:44
  • Okay, couldnt wait tilltomorrow so i tried it now. replaced the previous with accounts = (struct account*)realloc(accounts, sizeof(*accounts) * (numberAccounts + 2)); numberAccounts is initialised to zero. unfortunately, same result. pulling my hair out haha – Ben Rider Nov 12 '19 at 17:49
  • You have "sizeof(*accounts) * (numberAccounts + 2)" should be "sizeof(account) * (numberAccounts + 2)" You want to allocate enough memory to store n number of acount objects, so take the sizeof(struct account) and multiply by the count you want to store. Instead, your comment example is allocating enough memory for n pointers. – NTDLS Nov 12 '19 at 18:18
  • tried your suggestions, still cant get it to work. I have updated my post to show the changes. I got it to work bare bones, but not with the function call main version. Appreciate all the help btw – Ben Rider Nov 13 '19 at 06:44
  • @BenRider in your code, you are printing the firstName of the 1st and 2nd account after only setting the 1st accounts firstName. I think this is a mistake. printf("first name = %s\n", accounts[0].firstName); printf("first name = %s\n", accounts[1].firstName); – NTDLS Nov 14 '19 at 15:28
  • @BenRider I added a full working example that I've been playing with locally. :D – NTDLS Nov 14 '19 at 16:09