0

I have to get the user to input data for an item and then when they have done that they can display that information by pressing 2. I get an Exception thrown at 0x7A111F4C (ucrtbased.dll) in ProceduralProjectG00358662.exe: 0xC0000005: Access violation reading location 0x0000004F. It displays the item number and then I get the exception. Any help is appreciated thanks

#include<stdio.h>
#include<conio.h>
#include<string.h>
#include <malloc.h>
#include <string>

typedef struct node {//Node Struct to read in file data
    int itemNum;
    std::string itemName;
    std::string itemSupplierName;
    int itemSupplierPhoneNumber;
    int reorderLimit;
    int numOfUnits;
    float costPerUnit;
    std::string  lastOrderDate;
    int needToBeStored;
    int departmentDelivery;
    int  monthsToReorder;
    int authorize;

    struct node* NEXT; //Moves to next line in the file
}stock;

typedef struct loginUser {//login information for the user
    std::string name;
    std::string password;

    struct loginUser* NEXT; //Moves to next line in the file
}login;

//Functions
void addNode(struct node** top, int numItemFunc, std::string nameItemFunc, std::string supplierNameFunc, int phoneNumFunc,  int limitFunc, int numBoughtFunc, float unitCostFunc, std::string  dateFunc, int storageFunc, int deliveryFunc, int reorderFunc, int authorizeFunc);
void addStockToList(struct node** top);
void displayList(struct node* top);

void main()
{
    struct node* headPtr = NULL;
    struct node* loginUser = NULL;
    FILE* report;
    FILE* stock;
    FILE* users;

    report = fopen("Report File.txt", "r");
    stock = fopen("Stock File.txt", "r");
    users = fopen("Users File.txt", "r");

    //Variables for stock file
    int numItem;
    std::string nameItem;
    std::string nameItemSupplier;
    int phoneNumberItemSupplier;
    int limitReorder;
    int amount;
    float unitPerCost;
    std::string dateLastOrder;
    int storageNeeded;
    int deliveryDepartment;
    int  reorderMonths;
    int authorize;

    //variables for login
    std::string username;
    std::string passwordLogin;

    //variables
    int option;

    if (stock == NULL)
    {
        printf("Nothing added to the list\n");
    }

    else
    {
        while (!feof(stock))
        {
            fscanf(report, "%d %s %s %d %d %d %f %s %d %d %d %d\n", numItem, nameItem, nameItemSupplier, phoneNumberItemSupplier, limitReorder,
                amount, unitPerCost, dateLastOrder, storageNeeded, deliveryDepartment, reorderMonths, authorize);

            addNode(&headPtr,  numItem,  nameItem, nameItemSupplier, phoneNumberItemSupplier,
                limitReorder, amount, unitPerCost, dateLastOrder, storageNeeded, deliveryDepartment, reorderMonths,  authorize);
        }
        fclose(stock);
    }



    //User menu
    printf("1 to add a stock item\n");
    printf("2 display all stock items on the screen\n");
    printf("3 to display specific stock items\n");
    printf("4 to update stock item details\n");
    printf("5 to delete stock item\n");
    printf("6 to generate statistics\n");
    printf("7 to print stock items into the report file\n");
    printf("8 to display items in order of value\n");
    printf("-1 to exit\n");

    scanf("%d", &option);

    while (option != -1)
    {

        if (option == 1)
        {
            addStockToList(&headPtr);
        }

        else if (option == 2)
        {
            displayList(headPtr);
        }
        //User menu
        printf("1 to add a stock item\n");
        printf("2 display all stock items on the screen\n");
        printf("3 to display specific stock items\n");
        printf("4 to update stock item details\n");
        printf("5 to delete stock item\n");
        printf("6 to generate statistics\n");
        printf("7 to print stock items into the report file\n");
        printf("8 to display items in order of value\n");
        printf("-1 to exit\n");

        scanf("%d", &option);
    }

    getch();
}//main

//Functions
void addNode(struct node** top, int numItemFunc, std::string  nameItemFunc, std::string  supplierNameFunc, int phoneNumFunc,
    int limitFunc, int numBoughtFunc, float unitCostFunc, std::string  dateFunc, int storageFunc, int deliveryFunc, int reorderFunc, int authorizeFunc)//Adds in data from Stock File.txt
{
    struct node* newNode = (struct node*)malloc(sizeof(struct node));

    newNode->itemNum = numItemFunc;
    newNode->itemName = nameItemFunc;
    newNode->itemSupplierName = supplierNameFunc;
    newNode->itemSupplierPhoneNumber = phoneNumFunc;
    newNode->reorderLimit = limitFunc;
    newNode->numOfUnits = numBoughtFunc;
    newNode->costPerUnit = unitCostFunc;
    newNode->lastOrderDate = dateFunc;
    newNode->needToBeStored = storageFunc;
    newNode->departmentDelivery = deliveryFunc;
    newNode->monthsToReorder = reorderFunc;
    newNode->authorize = authorizeFunc;

    newNode->NEXT = *top;

    *top = newNode;
}

void addStockToList(struct node** top)
{
    struct node** temp = top;
    struct node* newNode = (struct node*)malloc(sizeof(struct node));

    printf("Enter Item number:\n");
    scanf("%d", &newNode->itemNum);

    printf("Enter Item name:\n");
    scanf("%s", &newNode->itemName);

    printf("Enter Item supplier name:\n");
    scanf("%s", &newNode->itemSupplierName);

    printf("Enter Item supplier phone number:\n");
    scanf("%d", &newNode->itemSupplierPhoneNumber);

    printf("Enter Item reorder limit:\n");
    scanf("%d", &newNode->reorderLimit);

    printf("Enter number of units:\n");
    scanf("%d", &newNode->numOfUnits);

    printf("Enter the cost per unit:\n");
    scanf("%f", &newNode->costPerUnit);

    printf("Enter Item last order date:\n");
    scanf("%s", &newNode->lastOrderDate);

    printf("Item needs to be stored?:\n");
    scanf("%d", &newNode->needToBeStored);

    printf("Enter the department this item belongs to, 1 for Office, 2 for Maintenance:\n");
    scanf("%d", &newNode->departmentDelivery);

    printf("Enter the months if you need to reorder 1 - 12 or 0 for none:\n");
    scanf("%d", &newNode->monthsToReorder);

    printf("Enter the person that needs to authorize this, 1 for Managing Director, 2 for Financial Controller or 3 for Department Manager :\n");
    scanf("%d", &newNode->authorize);



    newNode->NEXT = *top;
    *top = newNode;
}

void displayList(struct node* top)
{
    struct node* temp = top;

    while (temp != NULL)
    {
        printf("Item Number: %d\n", temp->itemNum);
        printf("Item Name: %s\n", temp->itemName);
        printf("Item Number: %s\n", temp->itemSupplierName);
        printf("Item supplier phone number: %d\n", temp->itemSupplierPhoneNumber);
        printf("Item reorder limit: %d\n", temp->reorderLimit);
        printf("Item number of units: %d\n", temp->numOfUnits);
        printf("Item cost per unit: %f\n", temp->costPerUnit);
        printf("Item last order date: %s\n", temp->lastOrderDate);
        printf("Item needs to be stored?: %d\n", temp->needToBeStored);
        printf("Item delivery department: %d\n", temp->departmentDelivery);
        printf("Item months it needs to be re orderd: %d\n", temp->monthsToReorder);
        printf("Needs to be authorizied: %d\n", temp->authorize);

        temp = temp->NEXT;
    }
}
  • `typedef struct`, `struct node` are odd in C++. – 273K Apr 27 '20 at 19:30
  • 4
    Thou shalt not `malloc` a `std::string`. It's too complex for `malloc` to handle. – user4581301 Apr 27 '20 at 19:31
  • 2
    Generally, when you write code you should build up gradually from the simple to the complex, and when you hit a bug like this it behooves you to *retreat* to a [minimal complete example](https://stackoverflow.com); it makes the bug much easier to find. – Beta Apr 27 '20 at 19:34
  • Watch out for `fscanf`. Because it's updating the variables you pass as arguments with the values read from the stream, the variables given need to be pointers. Because of the black magic that drives the variable arguments list `fscanf` takes, it can't legally complain as loud as it probably should when you screw up and pass it the wrong argument type. You may have a page-or-so of warnings about this mistake, but the program will compile regardless. It probably won't behave as expected, though – user4581301 Apr 27 '20 at 19:38
  • If you are one if the unfortunates forced to use Turbo C++, I suggest you add a tag for it. This is useful, because Turbo C++ predates C++ standards and is rather horribly outdated, and modern C++ answers will not work with it. – hyde Apr 27 '20 at 19:45
  • Once you figure out your issues, you should post this code over at [Code Review Stack Exchange](https://codereview.stackexchange.com). They will give you a bunch of tips on how to improve it. This code would have looked fine 30 years ago, but it would look completely different if written using modern C++ (and likely would have prevented the issues you are experiencing). – 0x5453 Apr 27 '20 at 19:45
  • @user4581301 ok, so then should I use a char? – Adam Dalton Apr 27 '20 at 19:46
  • @hyde I will add that tag now. This is what im being taught in college unfortunately. – Adam Dalton Apr 27 '20 at 19:50
  • You're a lot better off with `std::string` than `char` arrays. For now, use `new` in place of `malloc`. Future C++ lessons will likely teach better alternatives. – user4581301 Apr 27 '20 at 19:50
  • Slight correction: You are not using Turbo C++. Turbo C++ names the header files slightly differently and didn't have namespaces. You might be learning an old version of C++ or using an up to date version, but being taught from lessons plans from the 1990s. Hard to say, but if you can afford it, grab an [up-to-date book or two](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) to use as companion references. – user4581301 Apr 27 '20 at 19:59
  • @user4581301 Ok. thank you for the advice really means a lot. I enjoy programming a lot just hard to learn because of quarantine – Adam Dalton Apr 27 '20 at 20:02

1 Answers1

1

As others have pointed out in the comments, there are many problems with this code / general solution.

The reason behind the specific access violation you mentioned (which may seem tricky - why would the first printf in displayList work, and then this one fail?) is that you are attempting to treat an std::string as a char* when you pass it into your second printf.

See this for more help.

thisisbenmanley
  • 386
  • 2
  • 9
  • That's a bug, but there are many, MANY places in this code that could be triggering an access violation. Narrowing down to exactly which one the asker's encountering is night-impossible. – user4581301 Apr 27 '20 at 19:40
  • Oh, definitely a ton of vulnerable spots. I was pointing out the reason behind this specific access violation given the scenario in the question (having just pressed `2`, and then having the access violation occur on the second `printf` after one of the `printf`s in `displayList` succeeded). Updating my response to reflect its specificity – thisisbenmanley Apr 27 '20 at 19:45