//I need help trying to find a way to make all my variables local and also allowing the user to type in name of the data file for reading. Also do a simple search to retrieve the weather information for a single query date

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;

//Globals
string year, year2, year3, year4;
string avgMinTmp,avgMinTmp2,avgMinTmp3,avgMinTmp4;
string avgMaxTmp,avgMaxTmp2,avgMaxTmp3,avgMaxTmp4;
string totalRainfall,totalRainfall2,totalRainfall3,totalRainfall4;
string reportedWeather,reportedWeather2,reportedWeather3,reportedWeather4;
string daysReported,daysReported2,daysReported3,daysReported4;


//Function Prototypes
void SaveDataFile();
void LoadDataFile();
void OverallStats();
void SearchByDate();
void MonthlyStats();
void Quit();
//------------------------------------------------------------------------------------------------------------------------
int main(int argc, char** argv) 

{
    char CHOICE[25];

    cout << "\n\t Welcome to my Weather stat generator\n";

    while(CHOICE[0] !='Q')
    {
        cout << "\n\t-------------------Main Menue---------------------";
        cout << "\n\t|                                                 |";
        cout << "\n\t|       (L)oad data file                          |";
        cout << "\n\t|       (O)verall stats                           |";
        cout << "\n\t|       (F)earch by date                          |";
        cout << "\n\t|       (M)ontly stats                            |";
        cout << "\n\t|       (Q)uit                                    |";
        cout << "\n\t|                                                 |";
        cout << "\n\t|  Enter a Capital Letter to make a selction      |";
        cout << "\n\t-------------------Main Menue---------------------";

        cin >> CHOICE;

        switch(CHOICE[0])
        {
            case 'S' : SaveDataFile(); break;
            case 'L' : LoadDataFile(); break;
            case 'O' : OverallStats(); break;
            case 'F' : SearchByDate(); break;
            case 'M' : MonthlyStats(); break;
            case 'Q' : Quit(); break;
            default : "\n\tInvalid input!";

        }


    }
    system("PAUSE");
    return 0;
}
//---------------------------------there is a option to save the data but not shown to us---------------------------------  
void SaveDataFile()
{
    try
    {
        ofstream DATAFILE; 
        DATAFILE.open("DATA1.FILE",ios::out);

        DATAFILE << " 2012 "  << "\n";
        DATAFILE << " 11" << "\n";
        DATAFILE << " 19" << "\n";
        DATAFILE << " 230 mm" << "\n";
        DATAFILE << " Snow" << "\n";
        DATAFILE << " 140" << "\n";

        DATAFILE << " 2013 "  << "\n";
        DATAFILE << " 12" << "\n";
        DATAFILE << " 20" << "\n";
        DATAFILE << " 300 mm" << "\n";
        DATAFILE << " Rain" << "\n";
        DATAFILE << " 160" << "\n";

        DATAFILE << " 2014 "  << "\n";
        DATAFILE << " 15" << "\n";
        DATAFILE << " 23" << "\n";
        DATAFILE << " 102 mm" << "\n";
        DATAFILE << " Clear" << "\n";
        DATAFILE << " 260" << "\n";

        DATAFILE << " 2015 "  << "\n";
        DATAFILE << " 16" << "\n";
        DATAFILE << " 25" << "\n";
        DATAFILE << " 332 mm" << "\n";
        DATAFILE << " hail" << "\n";
        DATAFILE << " 30" << "\n";

        DATAFILE.close();

        cout << "\n\tSuccess! Data was saved to file.";

    }
    catch (exception X)
    { cout << "\n\tFile Error! Could not Save Data.";}
}   


//------------------------------------------------------------------------------------------------------------------------  
void LoadDataFile()
{
    try
    {
        ifstream DATAFILE;
        DATAFILE.open("DATA1.FILE",ios::in);

        getline(DATAFILE,year);
        getline(DATAFILE,avgMinTmp);
        getline(DATAFILE,avgMaxTmp);
        getline(DATAFILE,totalRainfall);
        getline(DATAFILE,reportedWeather);
        getline(DATAFILE,daysReported);

        getline(DATAFILE,year2);
        getline(DATAFILE,avgMinTmp2);
        getline(DATAFILE,avgMaxTmp);
        getline(DATAFILE,totalRainfall2);
        getline(DATAFILE,reportedWeather2);
        getline(DATAFILE,daysReported2);

        getline(DATAFILE,year3);
        getline(DATAFILE,avgMinTmp3);
        getline(DATAFILE,avgMaxTmp3);
        getline(DATAFILE,totalRainfall3);
        getline(DATAFILE,reportedWeather3);
        getline(DATAFILE,daysReported3);

        getline(DATAFILE,year4);
        getline(DATAFILE,avgMinTmp4);
        getline(DATAFILE,avgMaxTmp4);
        getline(DATAFILE,totalRainfall4);
        getline(DATAFILE,reportedWeather4);
        getline(DATAFILE,daysReported4);



        DATAFILE.close();

        cout << "\n\tSuccess! Data was loaded.";
    }
    catch (exception X)
    { cout << "\n\tFile Error! Unable to Load dat.";}
}
//------------------------------------------------------------------------------------------------------------------------
void OverallStats()
{
    system("CLS");
    cout << "\n\n\t------------------Weather Data--------------------------";
    cout << "\n\tYear:" <<  year;
    cout << "\n\tAverage Min Tempature:" << avgMinTmp;
    cout << "\n\tAverage Max Tempature:" << avgMaxTmp;
    cout << "\n\tTotal Rain Fall:" << totalRainfall;
    cout << "\n\tWeather Type:" << reportedWeather;
    cout << "\n\tDays Reported:" << daysReported;
    cout << "\n\n\t--------------------------------------------------------";

    cout << "\n\n\t------------------Weather Data--------------------------";
    cout << "\n\tYear:" <<  year2;
    cout << "\n\tAverage Min Tempature:" << avgMinTmp2;
    cout << "\n\tAverage Max Tempature:" << avgMaxTmp2;
    cout << "\n\tTotal Rain Fall:" << totalRainfall2;
    cout << "\n\tWeather Type:" << reportedWeather2;
    cout << "\n\tDays Reported:" << daysReported2;
    cout << "\n\n\t--------------------------------------------------------";

    cout << "\n\n\t------------------Weather Data--------------------------";
    cout << "\n\tYear:" <<  year3;
    cout << "\n\tAverage Min Tempature:" << avgMinTmp3;
    cout << "\n\tAverage Max Tempature:" << avgMaxTmp3;
    cout << "\n\tTotal Rain Fall:" << totalRainfall3;
    cout << "\n\tWeather Type:" << reportedWeather3;
    cout << "\n\tDays Reported:" << daysReported3;
    cout << "\n\n\t--------------------------------------------------------";

    cout << "\n\n\t------------------Weather Data--------------------------";
    cout << "\n\tYear:" <<  year4;
    cout << "\n\tAverage Min Tempature:" << avgMinTmp4;
    cout << "\n\tAverage Max Tempature:" << avgMaxTmp4;
    cout << "\n\tTotal Rain Fall:" << totalRainfall4;
    cout << "\n\tWeather Type:" << reportedWeather4;
    cout << "\n\tDays Reported:" << daysReported4;
    cout << "\n\n\t--------------------------------------------------------";



}
//------------------------------------------------------------------------------------------------------------------------
void SearchByDate()
{
    cout << "\n\tEnter a Year: ";
    cin.ignore();
    getline(cin, year);
}
//------------------------------------------------------------------------------------------------------------------------
void MonthlyStats()
{

}
//------------------------------------------------------------------------------------------------------------------------
void Quit()
{

}
//------------------------------------------------------------------------------------------------------------------------

//End of main

Dani AI

Generated

A few focused, practical steps to get this working cleanly (addresses making variables local, letting the user pick the file, and doing a single-date search). Good direction already from (use a record/class) and (use a container and avoid system-specific calls). The simplest, safest pattern is: keep a small record type, load all records into a local std::vector in main (or return it from a loader), and pass that container by reference into your menu actions. That removes globals and makes testing easier.

Read the filename from the user and validate the stream before parsing. Example snippet to prompt and open the file:

std::string filename;
std::cout << "Enter data file (default DATA1.FILE): ";
std::getline(std::cin, filename);
if (filename.empty()) filename = "DATA1.FILE";
std::ifstream fin(filename);
if (!fin) { std::cerr << "Cannot open " << filename << "\n"; return; }

When loading, prefer line-based reads plus std::istringstream to parse lines like "230 mm" into a number and unit — that handles extra spaces and units robustly. After you populate the vector, a single-year lookup is easy and readable with std::find_if (no globals needed):

int yearToFind = /* read from user */;
auto it = std::find_if(records.begin(), records.end(),
                       [yearToFind](const Record& r){ return r.year == yearToFind; });
if (it != records.end()) printRecord(*it);
else std::cout << yearToFind << " not found\n";

Extra tips: use std::getline when fields may contain spaces (weather description), trim input or ignore stray newlines when switching between operator>> and getline, validate conversions (std::stoi) with try/catch, and consider an unordered_map<int,Record> if you need O(1) lookups for many years. These small changes keep everything local, make the filename user-configurable, and give a simple, fast search for a single date.

Recommended Answers

All 2 Replies

It looks to me you might need some custom classes. One to represent the data for each record and also a class that controls a collection of that data:

#include <iostream>
#include <string>
#include <vector>

using std::string;
using std::ostream;
using std::istream;
using std::vector;
class DataCollection
{
private:

    class Data
    {
    private:
        class Rainfall
        {
        public:
            int amount;
            string scale;
            Rainfall(int _amount = 0, string _scale = "mm")
            {
                amount = _amount;
                scale = _scale;
            }
            void WriteData(ostream& outFile)
            {
                outFile << amount << " " << scale << '\n';
            }
            void LoadData(istream& inFile)
            {
                inFile >> amount >> scale;
            }
    };
    public:
        int year;
        int avgMinTemp;
        int avgMaxTemp;
        Rainfall totalRainfall;
        string reportedWeather;
        int daysInReport;
        Data(int _year = 1900, int _avgMinTemp = 0, int _avgMaxTemp = 0, int amtOfRain = 0, string _scale = "mm", string _reportedWeather = "Clear", int _daysInReport = 0)
        {
            year = _year;
            avgMinTemp = _avgMinTemp;
            avgMaxTemp = _avgMaxTemp;
            totalRainfall.amount = amtOfRain;
            totalRainfall.scale = _scale;
            reportedWeather = _reportedWeather;
            daysInReport = _daysInReport;
        }
        void WriteData(ostream& outFile)
        {
            outFile << year << '\n';
            outFile << avgMinTemp << '\n';
            outFile << avgMaxTemp << '\n';
            totalRainfall.WriteData(outFile);
            outFile << reportedWeather << '\n';
            outFile << daysInReport << '\n';
        }
        void LoadData(istream& inFile)
        {
            inFile >> year;
            inFile >> avgMinTemp;
            inFile >> avgMaxTemp;
            totalRainfall.LoadData(inFile);
            inFile >> reportedWeather;
            inFile >> daysInReport;
        }
    };
    vector<Data> collection;
public:
    enum Properties
    {
        Year,
        Min,
        Max,
        Rain,
        Weather,
        Days
    };
    DataCollection();
    ~DataCollection();
    void AddData(int _year = 1900, int _avgMinTemp = 0, int _avgMaxTemp = 0, int amtOfRain = 0, string _scale = "mm", string _reportedWeather = "Clear", int _daysInReport = 0)
    {
        Data temp(_year, _avgMinTemp, _avgMaxTemp, amtOfRain, _scale, _reportedWeather, _daysInReport);
        collection.emplace_back(temp);
    }
    void WriteAllData(ostream& outFile)
    {
        for (Data d : collection)
        {
            d.WriteData(outFile);
        }
    }
    void LoadAllData(istream& inFile)
    {
        while (inFile.good())
        {
            Data temp;
            temp.LoadData(inFile);
            collection.emplace_back(temp);                
        }
    }        
    void FindData(Properties prop,int value,ostream& outFile)
    {
        for (Data d : collection)
        {
            bool good = false;
            switch (prop)
            {
            case Year:
                if (value == d.year)
                {
                    good = true;
                }
                break;
            case Min:
                if (value == d.avgMinTemp)
                {
                    good = true;
                }
                break;
            case Max:
                if (value == d.avgMaxTemp)
                {
                    good = true;
                }
                break;
            case Rain:
                if (value == d.totalRainfall.amount)
                {
                    good = true;
                }
                break;
            case Days:
                if (value == d.daysInReport)
                {
                    good = true;
                }
                break;
            default:
                outFile << "Property/Value mismatch\n";
                return;
            }
            if (good)
            {
                d.WriteData(outFile);
            }
        }

    }
    void FindData(Properties prop, string value, ostream& outFile)
    {
        for (Data d : collection)
        {
            bool good = false;
            switch (prop)
            {
            case Weather:
                if (value == d.reportedWeather)
                {
                    good = true;
                }
            default:
                outFile << "Property/Value mismatch\n";
                return;
            }
            if (good)
            {
                d.WriteData(outFile);
            }
        }
    }
};

These are a little rough, but they should give you an idea on how to proceed. One area that needs fleshing out is data validation.

Do not use system("PAUSE"); // this is not portable C++ code //

Your data file structure of :

/*
DATAFILE << " 2012 "  << "\n";
DATAFILE << " 11" << "\n";
DATAFILE << " 19" << "\n";
DATAFILE << " 230 mm" << "\n";
DATAFILE << " Snow" << "\n";
DATAFILE << " 140" << "\n";
*/

/*
getline(DATAFILE,year);
getline(DATAFILE,avgMinTmp);
getline(DATAFILE,avgMaxTmp);
getline(DATAFILE,totalRainfall);
getline(DATAFILE,reportedWeather);
getline(DATAFILE,daysReported);
*/

seems to implicate a very simple way to start ...

Use a struct to hold each data record:

struct Weather
{
    int year, avgMinTmp, avgMaxTmp, totalRainfall; //  H2O in mm
    string reportedWeather; // example "Snow"
    int daysReported;

    istream& takeIn( istream& is )
    {
        string mm;
        is >> year >> avgMinTmp >> avgMaxTmp >> totalRainfall >> mm >> reportedWeather >> daysReported;
        return is;
    }

    void print( ostream& os = cout )
    {
        return os << year << '\n' << avgMinTmp << '\n' << avgMaxTmp << '\n' totalRainfall << " mm\n" << reportedWeather << '\n' << daysReported;
    }
};

Then use a ...

vector < Weather > data; // to hold all the records read from file

You could use some functions to read and write the file data.

bool takeIn( const char* fname, vector < Weather >& data );
void outPut( const char* fname, const < Weather >& data );

One def'n could be like this:

bool takeIn( const char* fname, vector < Weather >& data )
{
    ifstream fin( fname );
    if( fin )
    {
        Weather w;
        while( w.takeIn(fin) ) data.push_back( w );
        fin.close();
        return true;
    }
    // else ...
    return false;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.