Another array question

Could I have some help with an array. I believe that I need a two-dimensional array.

Here is exactly the assignment "The program should begin by reading the weather data from an input file. Then it should create a report that displays for each month in the last three years, how many days were rainy, how many were cloudy, and how many were sunny. The program should also output the total rainy days, cloudy days, and sunny days in the three years. Moreover, it should report which of the three months had the largest number of rainy days."

Here is the sample file:
(3 columns, June for 3 years(2017, 2018, 2019) and 30 rows for 30 days of June.)
1
2
3
4
5
6
7
Rainy	Rainy	Cloudy
Sunny	Sunny	Sunny
Cloudy	Rainy	Sunny
Sunny	Sunny	Rainy
Cloudy	Sunny	Sunny
Rainy	Rainy	Rainy
...


Here is what i have so far:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

    void initializeWeather();
    void printArray();

int main()
{
///Declare variables


    int year;
    ifstream inFile;
    string weather;


///Open input file
    inFile.open("weather_in_june.txt");

    cout << "Summer Weather Report in June" << endl;
    cout << "*****************************" << endl;
    cout << "12345678901234567890123456789"
    cout << endl << endl;

    cout << "Year" << setw(8) << "Rainy" << setw(8)
         << setw(8) << "Cloudy" << setw(8) << "Sunny" << endl;
    printArray();


    return 0;
}

void initializeWeather()
{
///For loop to initialize input for array
    int weatherArray [30][3]{};
    ifstream inFile;
    string weather;
    
    for (int i{}; i <= 30; i++)
        {
            for (int j{}; j <= 3; j++)
            {
                inFile >> weatherArray[i][j];
            }
        }
}

void printArray()
{
    cout << "_____________________________" << endl;
    cout << year << setw(8) << rainy << setw(8)
         << cloudy << setw(8) << sunny << setw(8) << endl;
    cout << "_____________________________" << endl;
    cout << "Totals" << setw(8) << rSum << setw(80)
         << cSum << setw(8) << sSum << setw(8) << endl;
    cout << endl;
    cout << "The month with the most rainy days was June " 
         << yearMostRain << "." << endl;


}


Output is supposed to look like this:

Year   Rainy   Cloudy   Sunny
-----------------------------
2017      6       13      11
2018     12        5      13
2019      6        7      17
-----------------------------
Totals   24       25      41

Month with the most rainy days is June 2018.
Last edited on
Hello Fayezilla,

There are many things wrong with your program. Some small and trivial others are a big problem.

In "main". A single line comment is 2 forward slashes(//). Your third is unnecessary. A comment should be:
// Declare variables . The space helps in readability, but not required.

You define ifstream inFile; then open the file which is OK, but you never check to know if the file stream did open the file. Mostly irrelevant since you never use the file stream in "main".

It is your choice, but I came up with this when I was first learning to deal with files.
1
2
3
4
5
6
7
8
9
10
const std::string inFileName{ "" };  // <--- Put file name here.

std::ifstream inFile(inFileName);

if (!inFile)
{
	std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
	
	return 1;
}

This works well in "main", but in a function it is slightly different. I will get to that shortly.

"main" never calls the function "initializeWeather".

In the function "initializeWeather" there are several things.

You define your array in the function, but when the function ends so do to variables that were defined in the function.

You define your file stream again in the function, but never open or check the file, but try to use something that does not work.

The array should be defined in "main" and passed to the function and the file stream would work better to be defined and opened in the function where it is only used.

The function would need to be changed to: int initializeWeather(int weatherArray[][MAXCOLS]{}). And the function should return (0) zero to mean that everything worked.

Then in "main" the function call would be:
1
2
3
4
if (initializeWeather(weatherArray)
{
    return 1;
}


Now that I have mentioned it your program would be more useful like this:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

constexpr int MAXROWS{ 30 };
constexpr int MAXCOLS{ 3 };

int initializeWeather();
void printArray();

It may not appear to be much now, but in a larger program you only have 1 place to make a change and it will be changed in the whole program. It saves you from having to find all the magic numbers in your code. And then you will probably miss 1 or 2 until you find the program is not working right.

The for loop have the right concept, but the wrong implementation. Both loops will corrupt the stack beyond the size of the array. Your 2D array has 30 rows numbered from (0) zero to 29 for 30 elements. The part of the for loop i <= 30 The "<=" will cause "i" to become 30 which is past the end of the array and you have no idea what that part of the stack is for. The same holds true for the inner for loop.

I just noticed that you define string weather;, but never use it in the function.

I have not looked at the "printArray" function except to notice that you are using variables that have never been defined anywhere. For now I have put that function call and function in comments to work on later as you should do.

The first thing you need to do is work on opening the file and reading it to fill the array and have something to work with before you continue.

I noticed that if this is your input file:

Rainy	Rainy	Cloudy
Sunny	Sunny	Sunny
Cloudy	Rainy	Sunny
Sunny	Sunny	Rainy
Cloudy	Sunny	Sunny
Rainy	Rainy	Rainy


This is a problem because you have defined the array as an "int", but the file contains only strings. They do not match. First time you try to read a string into an "int" the file stream will be put into a failed state and be unusable until fixed.

If the above is the format of the input file you will need to read the file differently to convert the strings into a number or change the array from "int" to "string".

That should give you a start for now.

Andy
Hello Fayezilla,

Sorry I noticed this after I pressed Submit.

The reason that what you are thinking is output is split because you used "code" tags when you should have used "output" tags.

See http://www.cplusplus.com/articles/z13hAqkS/

About half way down the page just before point 3 you will see how the (---) work in code tags.

I would say what you ended up with is because under the heading names you have a line of ------ and the code tag only dealt with the first 3.

Andy
Thank you for your help. Here is what I have now, with the error messages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

    const int MAXROWS{30};
    const int MAXCOLS{3};
    const string inFileName{"weather_in_june.txt"};

    void initializeWeather();
    void printArray();

int main()
{
// Declare variables

    int year; // for the three years in the output
    string weatherArray;

    ifstream inFile(inFileName);

// Open input file
    inFile.open("weather_in_june.txt");

    if (!inFile)
    {
        cout << "\n File " << quoted(inFileName) << " did not open" <<endl;

        return 1;
    }

    cout << "Summer Weather Report in June" << endl;
    cout << "*****************************" << endl;
    cout << "12345678901234567890123456789";
    cout << endl << endl;

    cout << "Year" << setw(8) << "Rainy" << setw(8)
         << setw(8) << "Cloudy" << setw(8) << "Sunny" << endl;

    if (initializeWeather(string)) // error: expected primary-expression before ')' token|
    {
        return 1;
    }

    printArray();


    return 0;
}

void initializeWeather(int weatherArray[][MAXCOLS]{}) //error: expected ')' before '{' token| // error: expected unqualified-id before ')' token|
{
// For loop to initialize input for array
    string weatherArray [30][3]{};
    ifstream inFile;
    string weather; // to classify the strings within the txt file? "rainy, cloudy, sunny"

    for (int i{}; i < 30; i++)
        {
            for (int j{}; j < 3; j++)
            {
                inFile >> weatherArray[i][j];
            }
        }
}

/* --To print output??
void printArray()
{
    cout << "_____________________________" << endl;
    cout << year << setw(8) << rainy << setw(8)
         << cloudy << setw(8) << sunny << setw(8) << endl;
    cout << "_____________________________" << endl;
    cout << "Totals" << setw(8) << rSum << setw(80)
         << cSum << setw(8) << sSum << setw(8) << endl;
    cout << endl;
    cout << "The month with the most rainy days was June "
         << yearMostRain << "." << endl;


}
*/
Hello Fayezilla,

A little better, but not quite there yet.

1
2
3

void initializeWeather(int weatherArray[][MAXCOLS]{})

In the function definition the {}s are not needed. But more important is the fact that you are defining this array as a local variable to the function, so when the function ends so does the variable.

To define the array in "main" where it belongs you can use int weatherArray[][MAXCOLS]{};. This will define the array and the {}s will initialize the array to all (0) zeros.

Inside the function:
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
void initializeWeather(int weatherArray[][MAXCOLS]{}) //error: expected ')' before '{' token| // error: expected unqualified-id before ')' token|
{
// For loop to initialize input for array
    string weatherArray [30][3]{};
    ifstream inFile;
    string weather; // to classify the strings within the txt file? "rainy, cloudy, sunny"

    for (int i{}; i < 30; i++)
        {
            for (int j{}; j < 3; j++)
            {
                inFile >> weatherArray[i][j];
            }
        }
}

Line 56 creates an array of strings that you read into, but never use and it is lost when the function ends.

Line 57 creates a file stream, but you never open a file, so there is nothing to use.

Line 58 creates a variable that is never used. The compiler should have given at least a warning on this.

In line 53 you define an "int" array then on line 56 you define a string array, but since they are the same name the compiler should have flagged line 56 an an error because you are defining the same variable name twice.

The for loops are good, but you are over working this I think.

Going over what you wrote:

Here is exactly the assignment

1. The program should begin by reading the weather data from an input file.

2. Then it should create a report that displays for each month in the last three years,
how many days were rainy, how many were cloudy, and how many were sunny.

3. The program should also output the total rainy days, cloudy days, and sunny days in the three years.

4. Moreover, it should report which of the three months had the largest number of rainy days.


Either there is information missing or my take on what is there is different.


Point 1 says to read the file. It does not say what to do with what is read or how to store it until you put point 1 and 2 together. After reading 30 days of data all you need if the total for each column. So I am thinking a 3 X 3 array. 1 row for each year and 1 column for each type where the column holds the total for each year not each day.

A 30 X 3 array would mean more code to process the array to get the totals for each column. And after that you also need to deal with the 3 years, so your array would need to be weatherArray[3][30][3]. The first dimension for the year and the next two for the days and categories. I do not think that you want a 3D array.

Unless I am missing something that you have not said this is what I came up with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <iomanip>
#include <string>

#include <fstream>

using namespace std;

constexpr int MAXROWS{ 6 };  // <--- Should be 30.
constexpr int MAXCOLS{ 3 };
constexpr int MAXYEARS{ 3 };
constexpr int YEAR{ 2017 };

int initializeWeather(int weatherArray[][MAXCOLS]);
void printArray(int weatherArray[][3]);
int yearMostRain(int weatherArray[][3]);
void PrintHeading();

int main()
{
    ///Declare variables
    int weatherArray[MAXYEARS][MAXCOLS]{};  // <--- Rainy Cloudy Sunny

    if (initializeWeather(weatherArray))
        return 1;

    PrintHeading();

    printArray(weatherArray);

    return 0;
}

After line 12 you could add const string inFileName{"weather_in_june.txt"}; if you want, but when I came up with the code to deal with opening I just kept it close. What you have done works.

In line 22 notice that I used "MAXYEARS" because the first dimension is for years not days.

The empty {}s will initialize the array to all (0) zeros, so that it does not contain any garbage values.

Next I called the function to read the file because if it returns (1), meaning that the file is not open and usable, there is no point in continuing with the program.

If the function call returns (0) zero then you bypass the if statement and go to the next line.

Since you have shown that you have some idea of how to use functions I put the 2 cout statements in a function.

This way "main" just directs the program flow leaving the real work to the functions.

The " initializeWeathe" function starts with this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int initializeWeather(int weatherArray[][MAXCOLS])
{
    // For loop to initialize input for array
    string weather;

    const std::string inFileName{ "weather_in_june1.txt" };

    std::ifstream inFile(inFileName);

    if (!inFile)
    {
	    std::cout << "\n File " << std::quoted(inFileName) << " did not open!" << '\n';
        //std::cout << "\n File \"" << inFileName << "\" did not open!" << '\n';

        return 1;
    }

Line 6 comes from pasting code in, so I do not usually change where this line is defined, but at the top of the program is good if that is what you like.

Since this function is the only place you use a file stream it makes more sense to define and open the file here. To use what you have done you would have to pass the file stream variable to the function and that is extra work that you do not need to deal with.

The for loops you wrote will work except that the array that you put ith information in is lost when the function and string weatherArray [30][3]{}; is destroyed.

You provided:

Rainy	Rainy	Cloudy
Sunny	Sunny	Sunny
Cloudy	Rainy	Sunny
Sunny	Sunny	Rainy
Cloudy	Sunny	Sunny
Rainy	Rainy	Rainy
...


But did not say if this 2 lines per year or 6 lines for the first month. I am guessing that the proper file is 3 sections of 30 lines to cover the 3 years.

What I did with the for loops is the first one is for the years, the second one is for the days and the third is for the columns.

In the third for loop is where I read the file.

I used a "switch", but if you ate not familiar with that you can use if/else if statements. This was done to add 1 to the correct column of the array based on the name that was read from the file.

Since I took the instructions to mean that you only need to keep track of a total this worked out.

After reading the file I came up with this for output:

Summer Weather Report for June
******************************

Year   Rainy  Cloudy   Sunny
──────────────────────────────
2017     7       3       8
2018     8       2       8
2019    10       1       7
══════════════════════════════
Totals  25       6      23

The month with the most rainy days was June 2019.


I used the array to store the totals to print in the table and for the "Total" line I used the for loop in the print function to add to the variables "rSum", "cSum" and "sSum" before they were needed.

In the last cout statement I called a function to return the proper year which had the highest rain fall for the month.

In addition to working with the program in small steps it also helps to do some planning before you start to code so that you have an idea of what to do.

Andy
Thank you for your help, it worked out.
Topic archived. No new replies allowed.