[C/C++/C#] C++ using 2 dimensional arrays

Discussion in 'Programming' started by Jimmayboy, May 6, 2010.

  1. Jimmayboy

    Jimmayboy Active Member

    The question: The program is to use a 2 dimensional array to store the following shipping data, which is to be stored in a csv file.
    Freight Charges ($) (by shipping zone)
    1 2 3 4
    2.50 3.50 4.00 5.00
    3.50 4.00 5.00 6.50
    4.50 6.50 7.50 10.00
    10.00 11.00 12.00 13.50
    13.50 16.00 20.00 27.50
    32.00 34.00 35.00 38.00
    The data is to be read into the array (from the file) and the array searched to find the appropriate cost for shipping an item of a specified weight in a specified zone. Each row in the table represents the cost for a particular shipping weight. You will need to work out a way of assigning a particular weight range to each row. A user needs to be able to enter multiple items to be shipped and so the program needs to continue until the user wants to QUIT. Each customer is given a numeric ID code. The item number is assigned automatically. An itemized list is to be displayed including:

    Cust IDnumber Item Number Shipping zone Weight Category Actual Weight Cost

    A total of the individual item costs per customer and an average cost per customer is to be displayed.

    well i was wondering if i am on the right track here is my code so far

    #include <iostream>
    #include <iomanip>
    using namespace std;
    const MAXROWS = 6;
    const MAXCOLS = 4;
    typedef float PriceType[MAXROWS][MAXCOLS]; // creates a new data type
    // of a 2D array of floats
    void getPrices(PriceType, int&, int&); // gets the prices into the array
    void printPrices(PriceType, int, int); // prints data as a table
    int main()
    {
    int rowsUsed; // holds the number of rows used
    int colsUsed; // holds the number of columns used
    PriceType priceTable; // a 2D array holding the prices
    getPrices(priceTable, rowsUsed, colsUsed); // calls getPrices to fill the array
    printPrices(priceTable, rowsUsed, colsUsed);// calls printPrices to display array
    system("pause");
    return 0;
    }
    void getPrices(PriceType table, int& numOfRows, int& numOfCols)
    {
    cout << "Please input the number of rows from 1 to "<< MAXROWS << endl;
    cin >> numOfRows;
    cout << "Please input the number of columns from 1 to "<< MAXCOLS << endl;
    cin >> numOfCols;
    }
     
  2. GetTriggerUnit-

    GetTriggerUnit- Well-Known Member

    Code:
    const MAXROWS = 6;
    const MAXCOLS = 4;
    //aren't these missing the type 'short, int or long'
    

    Why can't you use a struct that way?

    Code:
    struct ALine {
        double row1;
        double row2;
        double row3;
        double row4;
    };
    
    int main() {
        ALine[] lines;
    }
    
    Is that a C++ homework you got for shcool? :D
     
  3. odie

    odie Well-Known Member

    I guess, you are on the right track. There are several improvements possible (e.g. I would encapsulate the array in a class), but in general yes.

    As GetTriggerUnit- already said, you need to specify a type for the constants. I recommend unsigned int. This kind of implicit int declaration was deprecated in 1989, but some not-so-strict compilers allow it to this day.

    The struct is not that useful, since it seems you have to use 2-dim arrays and also leads to maintenace hell. The moment another zone is added you have to change all code where row1 - row4 are accessed. With arrays you simply change MAXCOLS and that should be it.

    Note: You should check that the user doesn't enter invalid values. e.g. 27. Your program would crash in that case. Handling "xyz" is more difficult. If you need it, I can show you how to do it properly.
     
  4. Jimmayboy

    Jimmayboy Active Member

    @gettriggerunit- yeah it is for uni its hard as ive never done this before firstyear doing it xD and yeah i think i could change it thanks xD

    @odie ohh i am on the right track sweet! ohh the constants hey soo a constant integer :S

    sooo to finish it i jsut have to change maxcols and add constant integers :S and yeah would like it if you couldshow mthe handling of xyz xD sorry if i sound all over the place c++ is very new to me.
     
  5. odie

    odie Well-Known Member

    I tried to create an example as simple as possible. I hope it worked. There is room for improvement, but that would again increase the complexity. My purpose was to show how to read an integer from stdin with error handling.

    Another possible implementation would be to use getline and parse the input afterwards.

    Code:
    #include <iostream>
    #include <iomanip>
    #include <limits>
    #include <string>
    using namespace std;
    const unsigned MAXROWS = 6;
    
    int readInput(std::string const& error, int min, int max) {
    	int input;
    
    	// Lets read from input till the value is in [min, max]
    	while (true)
    	{
    		if (!(std::cin >> input))
    		{
    			// Read failed, clear the failbit
    			std::cin.clear();
    			// Remove all characters in input stream
    			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    			// Give an error message
    			if (!(std::cout << error)) {
    			// In/Out is completely "broken". Completely unlikely to happen, still we should get out of the endless loop
    		    // In a real program I would throw an exception here or maybe even call exit();
    				break;
    			}
    			continue;
    		}
    		if (input < min || input > max) {
    			std::cout << error;
    			continue;
    		}
    		break;			
    	}
        // In case there is more in the input, discard it. e.g. after entering "1w" or something
    	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	return input;
    }
    
    int main()
    {
    	std::cout << "Please input the number of rows from 1 to " << MAXROWS << "\n";
    	int numOfRows = readInput ("Invalid input. Please retry\n", 1, MAXROWS);
    	cout << "\nYou entered " << numOfRows << "\n";
    }
    Basically reading is done in an endless loop till everything is fine.
    if (!cin) tests if the stream is still good or bad. When a user types e.g. "xyz" an error occurs and the stream becomes bad. We ignore the various possible reasons and just assume that the user indeed type something that is not an integer. cin.clear() removes the failbit. Afterwards the invalid characters are still in the stream. The next read would fail again. So we clean all characters till the next Enter with cin.ignore().

    Then we test if the value is in the required range. If everything is fine, we break the loop.
    Again, we clear the rest of the characters. e.g. someone might have typed "1 haha" or something like that.

    I hope this explains how to read input a bit better.
    Personal note: I really don't like C++ streams, they are stupid and awkward. Error handling is really a pain. I prefer to use getline and sscanf.
     
  6. Jimmayboy

    Jimmayboy Active Member

    ohh thanks it works mcuh better now odie yeh when a user types "xyz" its ignored well thanks heaps ! yeah ti does explain how to read input much better i understand it now. Now all i need to do is loop this zone thing can you show me to do this for the 4 freight zones ?
     
  7. odie

    odie Well-Known Member

    To read from a file you use ifstream. Basically it works the same way as reading from cin. Give it a try yourself and then we can take a look at it and improve it.
     
  8. Jimmayboy

    Jimmayboy Active Member

    sorry im still new to c++ what exactly do you mean xD
     
  9. odie

    odie Well-Known Member

    google for "ifstream" and look at some of the examples. Then try to implement it yourself. When you are really stuck, post what you have got.