/** * Structs and weather data * This program takes three approaches to filling structs * Two of which actually work! * @author gtowell * Created: Fall 2019 * Considerably changed: March 2021 * **/ /** * to select between three methods * gcc -D METHOD=[123] weather.c **/ // select among the various struct fillers #ifndef METHOD #define METHOD 1 #endif #ifndef NULL #define NULL (void *)0 #endif #include #include #include #define WFILE "temps.txt" /** * A struct for grouping together weather data * **/ typedef struct { char time[10]; int temp; int dewPoint; int relHum; char windDir[10]; int windSpeed; } WeatherData; // An array holding lots of weather data WeatherData weather[100]; /** * A print representation of weather data * @param w -- the weather data to be printed * **/ void wprinter(WeatherData* w) { printf("%d Time:%s Temp:%d F\n", w, w->time, w->temp); } // Point here is the structs are pass by value!!!! /** * Parse the passed in line into the passed in struct * This really fills the struct, but it does not * matter because the struct is passed by value! * @param line -- the data to be parsed * @param w -- the struct to be filled * **/ void parseA(char* line, WeatherData w) { //printf("WaP %d\n", &w); char* c = strtok(line, " \t"); strcpy(w.time, c); strtok(NULL, " \t"); // AM / PM skipped c = strtok(NULL, " \t"); w.temp = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.dewPoint = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.relHum = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); strcpy(w.windDir, c); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.windSpeed = (int)strtol(c, NULL, 10); } /** * Parse the passed in line a struct * This really fills the struct, * which is then returned by value. * @param line -- the data to be parsed * @return a filled structure * **/ WeatherData parseB(char* line) { WeatherData w; char* c = strtok(line, " \t"); strcpy(w.time, c); strtok(NULL, " \t"); // AM / PM skipped c = strtok(NULL, " \t"); w.temp = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.dewPoint = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.relHum = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); strcpy(w.windDir, c); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w.windSpeed = (int)strtol(c, NULL, 10); return w; } /** * Parse the passed in line into a WeatherData object * that is passed as a pointer! * @param line -- the data to be parsed * @param w -- a pointer to a struct to be filled * **/ void parseC(char* line, WeatherData * w) { char* c = strtok(line, " \t"); strcpy(w->time, c); strtok(NULL, " \t"); // AM / PM skipped c = strtok(NULL, " \t"); w->temp = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w->dewPoint = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w->relHum = (int)strtol(c, NULL, 10); c = strtok(NULL, " \t"); strcpy(w->windDir, c); c = strtok(NULL, " \t"); c = strtok(NULL, " \t"); w->windSpeed = (int)strtol(c, NULL, 10); //printf("WbP %d\n", &w); } /** * Print a header to identify the method being used * **/ void doHeader() { for (int i = 0; i < 10; i++) printf("%d", METHOD); printf("\n"); } int main(void) { doHeader(); char line[256]; FILE* f = fopen(WFILE, "r"); if (f==NULL) { fprintf(stderr, "Could not open %s -- quitting\n", WFILE); return 1; } int c = 0; while (NULL != fgets(line, 256, f)) { switch (METHOD) { case 1: parseA(line, weather[c]); break; case 2: weather[c] = parseB(line); break; case 3: default: parseC(line, &weather[c]); break; } c++; } for (int i=0; i