• Support PF! Buy your school textbooks, materials and every day products Here!

Problem with C++ Information Structures, Pointers, Arrays

  • #1
50
1

Homework Statement


So I'm getting an error when I try to compile my C++ code:
Debug Error
Abort() has been called

I have commented the code reasonably well, but the idea of the program is to take a file, separate the contents in each line to a part of a structure containing:
Product Lookup Number: Like A001
Name: Like Apples
Sales Type (per unit, per pound, 0, 1)
Price per sales type like 0.90
The number of items in inventory like 21

Then the user can buy a "quantity" of these items. The program will update the cost as the user
buys more items. Then it will load all of this updated information to the file and exit when the user is
done. A huge part of the program is input validation. That's why I have the myStod() (string to double)
and myStoi() (string to int) functions. They make sure the data being input is good to use ideally.

I have attached the assignment document to the post, and if my explanation is not clear I can elaborate further.

In my debugging attempts I have determined that the errors are happening when myStoi() and myStod are called. I can't figure it out any further. Some help would be appreciated! Thanks

Homework Equations


I need to test a .txt file containing this text:

A001 Apples 1 0.90 21
A00% Peaches 1 0.82 11
A00& Cherries 1 1.21 25
A004 Oranges 1 .98 31
A005 Grapefruit 1 .39 16
A00^ Avocados 0 1.54 27
A008 Mangos 0 1.69 19
A009 Strawberries_Case 0 12.50 8
4028 STRAWBERRIES_PINT 0 0.99 104
4383 MINNEOLAS 1 0.79 187.3
4261 Rice_1_LB_Bag 0 0.49 107

The Attempt at a Solution


Code:
/*
Author: ____
Compiler: Visual Studio Express 2015
Date: 7/1/2016
Purpose of program: Reads product information from a file, gets input from user. Updates it and checks user out.
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<cctype>
#include<string>
#include<cstring>
#include<fstream>
#define SIZE 100
using namespace std;

//Product structure. Contains PLU, name, salesType, unitPrice, inventoryLevel.

struct Product
{
    string PLU;
    string name;
    int salesType;
    double unitPrice;
    double inventoryLevel;

};

/*
This function takes a string as argument and returns true if all
the characters in the string are letters or digits. Else it returns false
*/
int validatePLU(const string & s)
{
    char * cstr = new char[s.length() + 1];
    strcpy(cstr, s.c_str());
    int maxLen = strlen(cstr);
    int tfRet = 1;
    for (int i = 0; i <= maxLen; i++)
    {
        int tf = isalnum(cstr[i]);
        if (tf == 0)
        {
            tfRet = 0;
        }
    }
    return tfRet;
}
/* This function checks the string is not empty and the string has
only digits
before it calls stoi. Returns true if conversion to int was
successful, false otherwise.
The int converted from the string by stoi, if conversion was
successful, is the reference variable res
*/

bool myStoi(const string & s)
{
    bool tf = true;
    if (s.length() > 0)
    {
        char * cstr = new char[s.length() + 1];
        strcpy(cstr, s.c_str());
        string digits = "0123456789";
        for (int z = 0; z <= strlen(cstr); z++)
        {
            for (int i = 0; i < strlen(cstr); i++)
            {
                if (cstr[z] == digits.at(i))
                {
                    break;
                }
                else if (i == 10 && z == strlen(cstr))
                {
                    tf = false;
                    break;
                }
            }
            if (tf = true && z == strlen(cstr))
            {
                stoi(s);
            }
        }
    }
    return tf;
}

/* This function checks the string is not empty and the string has
only digits and at most one decimal point
before it calls stod. Returns true if conversion to double was
successful, false otherwise.
The double converted from the string by stod, if conversion was
successful, is the reference variable res
*/
bool myStod(const string &s)
{
    string acceptableVals = "0123456789.";
    bool tf = true;
    char * cstr = new char[s.length() + 1];
    strcpy(cstr, s.c_str());
    bool valid = true;
    if (strlen(cstr) > 0)
    {
        for (int i = 0; i <= strlen(cstr); i++)
        {
            if (isalpha(cstr[i]) == 1)
            {
                valid = false;
            }
        }
        if (valid == true && isdigit(stoi(s)) != 1 && s.find(".") == string::npos)
        {
            tf = false;
        }
    }
    if (valid == true && tf == true)
    {
        stod(s);
    }
    else if (strlen(cstr) == 0)
    {
        cout << "Invalid input" << endl;
    }
    return tf;
}

/*
Stores an individual word as a string, specified by the word index. Finds the words by the whitespace between
words and the two surrounding words.
*/

string extractWord(string s, int wordNum)
{
    string newStr = s;
    int index = 0;
    int secondToLastIndex;
    for (int i = 0; i <= wordNum; i++)
    {
        secondToLastIndex = index;
        index = newStr.find(" ");
        newStr = s.substr(index, s.length());
    }
    return s.substr(secondToLastIndex, index + secondToLastIndex);
}

/* This function takes as argument a PLU string, the array of pointers
and the number of products.
It searches the arrayProducts for a matching PLU
and returns the array index if found, or -1 if not found
*/

int searchProduct(string pluStr, Product *arrayProd[], int numProducts)
{
    int index = -1;
    Product currProd;
    for (int i = 0; i <= numProducts; i++)
    {
        currProd = *arrayProd[i];
        {
            if (pluStr == currProd.PLU)
            {
                index = i;
            }
        }
    }
    return index;
}

/*

*/

double checkout(Product *arrayProd[], const int numProducts)
{
    string PLU;
    int quantity;
    bool keepGoing = true;
    double totalCost = 0;
    while (keepGoing = true)
    {
        cout << "Please enter the PLU code or type 0 to exit: " << endl;
        cin >> PLU;
        if ((validatePLU(PLU)) == 1 && PLU.find("0") != string::npos)
        {
            cout << "Please enter the quantity: " << endl;
            cin >> quantity;
            if ((isdigit(quantity) == 1) && (quantity > 0))
            {
                int index = searchProduct(PLU, arrayProd, numProducts);
                arrayProd[index]->inventoryLevel = (arrayProd[index]->inventoryLevel - quantity);
                totalCost += ((arrayProd[index]->unitPrice)*quantity);
            }
            else
            {
                cout << "Error: Invalid input" << endl;
                continue;
            }
        }
        else if (PLU.find("0") == string::npos)
        {
            keepGoing = false;
        }
        else
        {
            cout << "Error: Invalid input" << endl;
            continue;
        }
        cout << "The total cost of your purchases was: " << totalCost << endl;
    }
    return totalCost;
}

/* This function takes as arguments a file name and an array of
pointers to Product, along with
the max size of the array. It opens the file and reads the inventory
from the file.
It reads line by line, where each line corresponds to a product.
For each product, it dynamically allocates a Product structure and
assigns the pointer to an element of the array.
It does input validation (PLU has only letters or digits, sales type
can be only 0 or 1,
unit price must be > 0, inventory level >= 0) and populates the
structure with the data entered.
The structure content is displayed. The function terminates when there
is no more data in the file
or when the array is full. It also terminates upon error condition.
It returns the number of products if all the data was valid, -1 in all
other cases of error.
*/
int readInventory(string fName, Product * arrayProd[])
{
    string line;
    string lineArr[1000];
    ifstream inFile;
    inFile.open(fName);
    int i = 0;
    if (!inFile.fail())
    {
        while (getline(inFile, line))
        {
            lineArr[i] = line;
            i++;
        }
        for (int z = 0; z <= i; z++)
        {
            Product *structPtr = new Product;
            structPtr->PLU = extractWord(lineArr[z], 1);
            structPtr->name = extractWord(lineArr[z], 2);
            structPtr->salesType = myStoi(extractWord(lineArr[z], 3));
            structPtr->unitPrice = myStod(extractWord(lineArr[z], 4));
            structPtr->inventoryLevel = myStod(extractWord(lineArr[z], 5));
            arrayProd[z] = structPtr;
        }
    }
    else
    {
        cout << "File failed to open " << endl;
        exit(EXIT_FAILURE);
    }
    return i;
}

int main()//Start of main()
{
    bool menu = true; //t/f for while loop
    Product *arr[SIZE]; //Initialize array
    int numProds;//The number of products in the array
    string str;//A spare string for cstring and string manipulation
    while (menu = true)
    {
        int ans;//input for the user in the menu
        cout << "Type 1 for Checkout" << endl;
        cout << "Type 2 to Close and Exit" << endl;
        cin >> ans;
        if (ans == 1)
        {
            numProds = readInventory("productData0.txt", arr);
            double price = checkout(arr, numProds);
        }
        else if (ans == 2)
        {
            ofstream outFile;
            string oName = "productData0.txt";
            outFile.open("productData0.txt");
            for (int a = 0; a < numProds; a++)
            {
                string strToLoad = arr[a]->PLU + arr[a]->name + to_string(arr[a]->salesType) + to_string(arr[a]->unitPrice) + to_string(arr[a]->inventoryLevel);
                char * cStrPtr = new char[strToLoad.length() + 1];
                strcpy(cStrPtr, strToLoad.c_str());
                outFile << (cStrPtr);
                outFile << ("\n");
                cout << "Success" << endl;
            }
            outFile.close();
            menu = false;
        }
        else
        {
            cout << "Invalid input. Please re-enter" << endl;
        }
    }
    system("pause");
    return 0;
}//End of main()
 

Attachments

Answers and Replies

  • #2
rcgldr
Homework Helper
8,680
514
There's a small chance this is related to using unicode instead of Ascii. Right click on project, properties, ... all configuration, and set "character set" to "not set" (instead of it possibly being "unicode").
 
  • #3
50
1
Didn't change anything. Thanks for the pointer though.
 
  • #4
rcgldr
Homework Helper
8,680
514
The inner loop of myStoi has an issue, since i is incremented to strlen(ctsr) instead of 10 (strlen(digits)). Also, the result from stoi() is not stored or returned. There's a similar problem with myStod().

Code:
bool myStoi(const string & s)
{
    if (s.length() > 0)
    {
        static string digits = "0123456789";
        for (int z = 0; z < s.length(); z++)
        {
            for (int i = 0; i < 10; i++)
            {
                if (s.at(z) == digits.at(i))
                    break;
            }
            if(i == 10)
            {
                return false;
            }
        }
        stoi(s);      // where is this result stored?
        return true;
    }
    return false;     // zero length string
}
 
Last edited:

Related Threads on Problem with C++ Information Structures, Pointers, Arrays

  • Last Post
Replies
8
Views
1K
  • Last Post
Replies
2
Views
804
Replies
4
Views
1K
Replies
6
Views
7K
  • Last Post
Replies
11
Views
699
Replies
3
Views
3K
  • Last Post
Replies
5
Views
560
Replies
15
Views
6K
Replies
8
Views
3K
Top