Each day of the month is designated as either rainy (‘R’), cloudy (‘C’), or sunny (‘S’). The program should store this information in a 3 × 30 2D array of characters, where the row indicates the month (0 = June, 1 = July, 2 = August) and the column indicates the day of the month. Note that data are not being collected for the 31st day of any month. The program should begin by reading the weather data into the 2D array from a file named RainOrShine.txt. Then it should create a report that displays, for each month and for the whole three-month period, how many days were rainy, how many were cloudy, and how many were sunny. It should also report which of the three months had the largest number of rainy days.
I can only use pointers in this program, and I couldn't compare the value of the char pointer array to a char. I've tried
void print(const char* ptr, int* p, const int days, const int months)
{
int rainy, sunny, cloudy;
int rainySum = 0, sunnySum = 0, cloudySum = 0;
cout << setw(28) << "Summer Weather Report" << endl;
cout << endl;
cout << setw(10) << left << "Month" << "Rainy " << setw(10) << right << "Cloudy" << setw(10) << "Sunny" << endl;
for(int i = 0; i <= 8; i )
{
cout << "____";
}
cout << endl;
for(int i = 0; i < days*months; i )
{
rainy = 0;
sunny = 0;
cloudy = 0;
for(int j = 0; j < days; j )
{
if(*(ptr (i*days) j) == 'R')
{
rainy ;
(*(p (i*months) 0)) = rainy;
}
else if(*(ptr (i*days) j) == 'C')
{
cloudy ;
(*(p (i*months) 0)) = cloudy;
}
else if(*(ptr (i*days) j) == 'S')
{
sunny ;
(*(p (i*months) 0)) = sunny;
}
}
}
for(int i = 0; i < days; i )
{
if(i == 0)
{
cout << setw(10) << left << "June";
}
else if(i == 1)
{
cout << setw(10) << left << "July";
}
else if (i == 2)
{
cout << setw(10) << left << "August";
}
for(int j = 0; j < days; j )
{
cout << setw(10) << right << *(p ((i*3) j));
}
cout << endl;
}
for(int i = 0; i <= 8; i )
{
cout << "____";
}
cout << endl;
for(int i = 0; i < months; i )
{
rainySum = *(p (i*months) 0);
cloudySum = *(p (i*months) 1);
sunnySum = *(p (i*months) 2);
}
cout << setw(10) << left << "Totals" << rainySum << setw(6) << sunnySum << setw(6) << cloudySum << endl;
}
This won't print out what I wanted.
This is my main
char weather[NUM_OF_MONTHS][NUM_OF_DAYS];
int sum[3][30];
char* ptr = &weather[0][0];
int* p = &sum[0][0];
input(ptr);
print(ptr, p, NUM_OF_DAYS, NUM_OF_MONTHS);
This is the assignment prompt and this is what the output is supposed to be.
Edit: This is what the source code contains
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
// add prototypes for your functions
const int NUM_OF_MONTHS = 3;
const int NUM_OF_DAYS = 30;
int main()
{
// this 2D array stores the 90 values from the RainOrShine.txt text file
char weather[NUM_OF_MONTHS][NUM_OF_DAYS];
char* ptr = &weather[0][0]; // this pointer points to the beginning of the 2D
array
// Remember -- no using the brackets/subscripts
([]'s)!
// Everything should be handled with pointer
offset notation
// and/or pointer arithmetic
//implement the rest of main
// system("PAUSE");
return 0;
}
// implement your functions
CodePudding user response:
It is illegal to traverse an array of arrays (a "2D array") as if it were a contiguous "1D" array. The C standard says:
if P points to an array element i of an array object x with n elements ([dcl.array]), the expressions P J and J P (where J has the value j) point to the (possibly-hypothetical) array element i j of x if 0≤i j≤n [...]
Otherwise, the behavior is undefined
In your example, ptr
points to the first element of the char
array weather[0]
. Only elements of that array from weather[0][0]
to (the hypothetical) weather[0][NUM_OF_DAYS]
can be accessed via p
. Other elements of weather
, namely weather[1]
through (the hypothetical) weather[NUM_OF_MONTHS]
, are not legal to access, doing so is undefined behaviour. Similarly, p
points to the first element of sum[0]
, so sum[1]
and the rest of them are all out of bounds.
If the assignment requires you to access your 2D arrays this way, then it is not doable in standard C . You may or may not get lucky violating the C standard and doing the illegal thing anyway. But you probably cannot do it by mixing all of your sizes up. You need a 3x30 source table (months x day-in-month) and a 3x3 summary table (months x day-types, which is one of rainy, sunny and cloudy). Why is sum
a 3x30 array? Speaking of sum
, what is it doing in main
? It is not used there. It should be a local variable in a function that actually uses it.
It is however possible to declare weather
as a 1D array:
weather[NUM_OF_MONTHS * NUM_OF_DAYS];
Same about sum
. This will make pointer arithmetic on their respective pointers legal from the point of view of the C language (but you still need to fix the calculations and loop bounds which are all completely wrong).
I recommend to write it using normal 2D array notation first, debug it, make sure it is fully working, then translate it by hand to the 1D pointer notation, not all at once but statement by statement, checking that it works after every single change, until no array notation remains. Note that you will need to translate only the indexing expressions, not loop bounds. If you encounter problems during the first stage, ask a question about these problems first without mixing the pointer arithmetic notation in. You need to solve one problem at a time rather than all at once.
CodePudding user response:
I tried changing the code to be like this
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
// add prototypes for your functions
void input(char *);
void printDetermine(char*);
const int NUM_OF_MONTHS = 3;
const int NUM_OF_DAYS = 30;
int main()
{
// this 2D array stores the 90 values from the RainOrShine.txt text file
char weather[NUM_OF_MONTHS][NUM_OF_DAYS];
int sum[3][30];
char* ptr = &weather[0][0]; // this pointer points to the beginning of the 2D array
// Remember -- no using the brackets/subscripts ([]'s)!
// Everything should be handled with pointer offset notation
// and/or pointer arithmetic
//implement the rest of main
input(ptr);
cout << ptr;
printDetermine(ptr);
// system("PAUSE");
return 0;
}
// implement your functions
void input(char* ptr)
{
ifstream inputFile;
inputFile.open("RainOrShine.txt");
char x;
if(!inputFile.is_open())
cout << "File cannot be opened!" << endl;
while(inputFile >> x)
{
*ptr = x;
*ptr ;
}
inputFile.close();
}
void printDetermine(char* ptr)
{
cout << setw(28) << "Summer Weather Report" << endl;
cout << endl;
cout << setw(10) << left << "Month" << "Rainy " << setw(10) << right << "Cloudy" << setw(10) << "Sunny" << endl;
int rainy, sunny, cloudy;
int rainySum = 0, sunnySum = 0, cloudySum = 0;
int mostRainyMonth = 0;
for(int i = 0; i <= 8; i )
{
cout << "____";
}
cout << endl;
for(int i = 0; i < NUM_OF_MONTHS; i )
{
rainy = 0;
sunny = 0;
cloudy = 0;
for(int j = 0; j < NUM_OF_DAYS; j )
{
if(*ptr == 'R')
{
rainy ;
rainySum ;
}
else if(*ptr == 'C')
{
cloudy ;
cloudySum ;
}
else if(*ptr == 'S')
{
sunny ;
sunnySum ;
}
ptr ;
}
if(rainy > 0)
{
mostRainyMonth = i;
}
if(i == 0)
{
cout << setw(10) << left << "June";
}
else if (i == 1)
{
cout << setw(10) << left << "July";
}
else if (i == 2)
{
cout << setw(10) << left << "August";
}
cout << setw(5) << right << rainy << cloudy << sunny << endl;;
}
for(int i = 0; i <= 8; i )
{
cout << "____";
}
cout << endl;
cout << setw(10) << left << "Totals" << rainySum << setw(6) << sunnySum << setw(6) << cloudySum << endl;
}
I altered this part
if(*(ptr (i*days) j) == 'R')
{
rainy ;
(*(p (i*months) 0)) = rainy;
}
else if(*(ptr (i*days) j) == 'C')
{
cloudy ;
(*(p (i*months) 0)) = cloudy;
}
else if(*(ptr (i*days) j) == 'S')
{
sunny ;
(*(p (i*months) 0)) = sunny;
}
I also tried to print out the pointer array, and it successfully imported the file
cout << ptr;
Currently this is what my code prints out
SRRSRRRRSSSSCSCCRCRRSCRCCSCSSRSCCCSCRRRSRCSRSCCRCCCCCRRRCRRCCRSSCRRCRRSCRRSSRRRRRCSCCRSRRR Summer Weather Report
Month Rainy Cloudy Sunny
____________________________________
June 11811
July 11145
August 1677
____________________________________
Totals 3823 29
I'm almost completely out of idea on what to do next.