0

i have this assignment im doing and previously i did an assignment similar and it worked just fine. but now that im doing this second more complex form, its having trouble reading and storing the proper data. when i decided to try the previous source code that worked fine before i sumbitted it, it didnt work now either. im suppose to open a file and store a list of months names in an array of structs along with their high and low temps using a function outside of main, while also using 2 more functions to find the highest and lowest temp which will be output in function main. but with the data not coming out correctly i cant test the other 2 functions. i cant figure out if i have something corrupt somewhere or whats suddenly causing the files input on both programs to suddenly not work properly.

the input file is

January 47 36
February 51 37
March 57 39
April 62 43
May 69 48
June 73 52
July 82 56
August 81 57
September 75 52
October 64 46
November 52 41
December 45 35

the source code i got looks like

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 

struct month
{
string monthName; 
int highTemp;
int lowTemp;
};  
void loadData(ifstream &infile, month Temperatures [], int &size);                                      
month averageHigh(month Temperatures [], int size);                                                 
month averageLow(month Temperatures [], int size);                                                  

int main ()
{
    ifstream inFile;
    int length;                                                                                                                 
    month Temperatures[12]; 
    month highMonth, lowMonth;

    cout << "This program is designed to take a struct of months and their corresponding \nhigh/low 
temperatures "
         << "from an outside file, than calculate which months had the average high and low." << 
endl;       
    cout << endl;

    inFile.open("weather.txt");                                                                                 
    loadData(inFile, Temperatures, length);                                                                         
    averageHigh(Temperatures, length);                                                                          
    averageLow(Temperatures, length);                                                                           

    cout << highMonth.monthName << " has the highest temp of " << highMonth.highTemp << endl;                                       
    cout << lowMonth.monthName << " has the lowest temp of " << lowMonth.lowTemp << endl;                                           

    inFile.close();                                                                                             

    return 0;    
}

void loadData(ifstream &infile, month Temperatures [], int &size)                                                   
{
    cout << "The months highs(left) and lows(right) are: " << endl;                                                 
    for (size = 0; !infile.eof(); size++)                                                                                   
    {
        infile >> Temperatures[size].monthName >> Temperatures[size].highTemp >> 
Temperatures[size].lowTemp;                                             
        cout << Temperatures[size].monthName << " " << Temperatures[size].highTemp << " " << 
Temperatures[size].lowTemp << endl;                         
    }
}

month averageHigh(month Temperatures [], int size)                                                                      
{
    int highArray = 0;

    for (int array = 1; array < size; array++)                                                                          
        if (Temperatures[highArray].highTemp < Temperatures[array].highTemp)                                                        
            highArray = array;

    return  Temperatures[highArray];
}

month averageLow(month Temperatures [], int size)                                                                   
{
     int lowArray = 0;

    for (int array = 1; array < size; array++)                                                                          
        if (Temperatures[lowArray].lowTemp < Temperatures[array].lowTemp)                                                           
            lowArray = array;

    return  Temperatures[lowArray];                                                                                 
}

but with this the file keeps trying to store the values

4343069 0
0 0
11998488 0
321518481 32761
11993088 0
0 0
4342068 0
11998488 0 
321518481 32761
4741664 0
0 0
4746688 0

then it gives random characters like G and pi and 0s.

  • 1
    [while(!feof) is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – KamilCuk Jun 06 '20 at 17:53
  • originally i had it as the loop went while size < 12. but it makes no difference, the only thing it changes it the final pi and 0s and stuff at the end. i cant get that data read. – kyle ellis Jun 06 '20 at 17:55
  • 1
    You shouldn't write all of your code in one sitting, and then find out that the basic reading doesn't work. You should write a simple program that reads from that file, and outputs what you read, and test that program. Once fully tested, then you move that code into a larger program. – PaulMcKenzie Jun 06 '20 at 17:58
  • Are you seeing the output from the for loop in `loadData`? And second what PaulMckenzie said. Don't write too much code at once. – john Jun 06 '20 at 17:59
  • i was mainly converting my original code that used a two dimensional array and a parallel array to store the months and temps. but now that one doesnt even read the data correctly. the values at the bottom, all the numbers, are what the void loadData function outputs to the screen on the for loop. – kyle ellis Jun 06 '20 at 18:02
  • 1
    @kyleellis Almost certainly what is happening is that your file is failing to open. **ALWAYS** check that files open. Add `if (!inFile.is_open()) { cout << "file open failed\n"; }` to your code. – john Jun 06 '20 at 18:05
  • that seems to be outputting the file failed to open, so how can i fix that? the original code opened the file. so idk why the files location can no longer be found – kyle ellis Jun 06 '20 at 18:12
  • Place the file in a known directory and use the full path name. – PaulMcKenzie Jun 06 '20 at 18:13
  • @kyleellis 99% of the time this happens because the program is looking for the file in a different place from what you expected. Unfortunately this is outside the scope of C++ because the default location for files is determined by the operating system or the development environment. – john Jun 06 '20 at 19:26
  • @kyleellis A simple way to test the situation is to add a few lines to the start of your program which **write** out a file. Whereever that file appears, that is where you should put your input file. Make sense? – john Jun 06 '20 at 19:27
  • You have tagged this post as C++. As a new contributor to this forum, let me encourage you to practice C++ (and discourage offering c-style code). For example, your struct "month" can, and _should_ have constructor(s), destructor(s), private data, and methods that support the use of 'month'. Consider: month::load(ifstream&) and month::echo(). Your existing loaddata() function will shrink significantly. Consider: use vector instead of array. A vector grows using push_back, and keeps track of the 'length' in function vector::size(). No need to pass a 2nd parameter. – 2785528 Jun 06 '20 at 19:34

1 Answers1

0

Here is a cleaner code for you:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

struct Temperature {
    string month;
    int high;
    int low;
};

istream &operator>>(istream &in, Temperature &temp) {
    in >> temp.month >> temp.high >> temp.low;
    return in;
}

ostream &operator<<(ostream &out, const Temperature &temp) {
    out << temp.month << (temp.month.length() > 7 ? "\t" : "\t\t") << temp.high << '\t' << temp.low << endl;
    return out;
}

vector<Temperature> getData(ifstream &infile) {
    vector<Temperature> vect;
    Temperature temp;
    while (infile >> temp)
        vect.push_back(temp);
    return vect;
}

Temperature highest(vector<Temperature> &data) {
    return *max_element(data.begin(), data.end(), [](const Temperature &a, const Temperature &b) {
        return a.high < b.high;
    });
}

Temperature lowest(vector<Temperature> &data) {
    return *min_element(data.begin(), data.end(), [](const Temperature &a, const Temperature &b) {
        return a.low < b.low;
    });
}

int main() {
    ifstream infile("weather.txt");
    int length;
    auto data = getData(infile);
    for (auto &i : data)
        cout << i;
    auto h_T = highest(data), l_T = lowest(data);
    cout << endl
         << h_T.month << " has highest temperature of " << h_T.high << endl
         << l_T.month << " has lowest temperature of " << l_T.low << endl
         << endl;
    return 0;
}

weather.txt:

January 47 36
February 51 37
March 57 39
April 62 43
May 69 48
June 73 52
July 82 56
August 81 57
September 75 52
October 64 46
November 52 41
December 45 35

Output:

January         47      36
February        51      37
March           57      39
April           62      43
May             69      48
June            73      52
July            82      56
August          81      57
September       75      52
October         64      46
November        52      41
December        45      35

July has highest temperature of 82
December has lowest temperature of 35

brc-dd
  • 10,788
  • 3
  • 47
  • 67
  • thank you, but i think this might lose some requirements for my assignment. is this code finding the average of the temps and finding the corresponding month? but im only having to go through the list of highs and lows and output that month. also, im required to use the 3 functions, load/data to get file data and insert them into an array of structs, averagehigh to find the high month, and low the same way, which will return the values to function main to be output. i dont need the averages, but i will need to output the july 82, and december 35. – kyle ellis Jun 06 '20 at 19:05
  • @kyleellis average of max temperature is being returned by `averageHigh` and that of min temperatures is being returned by `averageLow`. You can remove them if you don't need. And then simply rename `highest` to `averageHigh` and `lowest` to `averageLow`. It should do your work! – brc-dd Jun 06 '20 at 19:10
  • @kyleellis I have modified my answer. Check that out now. :) – brc-dd Jun 06 '20 at 19:20