Problem with C++ Information Structures, Pointers, Arrays

In summary: This function takes an int as argument and returns thestring representation of that number.The function is called by stoi.*/string stoi(int res){ return c_str();}/*This function prints the string "Hello, world!"*/void printHelloWorld(){ cout << "Hello, world!";}// main()int main(){ Product p; // load the product structure from a file
  • #1
Prof. 27
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

  • CS1337-U16-HW3-2.pdf
    663.1 KB · Views: 362
Physics news on Phys.org
  • #2
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
Didn't change anything. Thanks for the pointer though.
 
  • #4
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:

1. What are pointers in C++?

Pointers in C++ are variables that store the address of another variable. They allow for indirect access and manipulation of data, and are commonly used in conjunction with dynamic memory allocation.

2. How do pointers differ from regular variables?

Pointers differ from regular variables in that they store memory addresses rather than values. They also have their own set of operators and require special syntax for declaration and initialization.

3. What is an array in C++?

An array in C++ is a data structure that stores a collection of elements of the same data type in contiguous memory locations. Each element can be accessed using an index, with the first element having an index of 0.

4. Why are arrays and pointers often used together in C++?

Arrays and pointers are often used together in C++ because they both allow for efficient manipulation of data and memory. Pointers can be used to point to the first element of an array, and can be incremented to access subsequent elements.

5. What are some common problems with C++ information structures?

Common problems with C++ information structures include memory leaks, segmentation faults, and incorrect data access. These can occur due to improper use of pointers, incorrect indexing of arrays, or insufficient memory allocation.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
2
Views
932
  • Engineering and Comp Sci Homework Help
Replies
7
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
4
Views
918
  • Engineering and Comp Sci Homework Help
Replies
18
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
7
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
11
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
8
Views
5K
  • Engineering and Comp Sci Homework Help
Replies
14
Views
4K
Back
Top