1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Problem with C++ Information Structures, Pointers, Arrays

  1. Jul 1, 2016 #1
    1. The problem statement, all variables and given/known data
    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

    2. Relevant 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

    3. The attempt at a solution
    Code (C):
    /*
    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()
     

    Attached Files:

  2. jcsd
  3. Jul 1, 2016 #2

    rcgldr

    User Avatar
    Homework Helper

    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").
     
  4. Jul 1, 2016 #3
    Didn't change anything. Thanks for the pointer though.
     
  5. Jul 2, 2016 #4

    rcgldr

    User Avatar
    Homework Helper

    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 (Text):

    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: Jul 2, 2016
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Problem with C++ Information Structures, Pointers, Arrays
  1. IP packet information (Replies: 0)

Loading...