带有 CSV 输入的 REXX 编码

问题描述

我刚开始使用 REXX 进行编码,我需要编写一个程序来查找每个月的最高、最低和平均温度。

输入以逗号分隔,如下所示:

DAY/MONTH,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec      
1st,25.9,25.4,31.3,22.4,8.1,7.3,12.9,13.1,11.3,15.2,19.2,21    
2nd,27.2,22.3,18,14.6,10.2,10.9,13.5,15.9,24.9,26.2,17.2  
3rd,34.9,16.6,19.1,20.8,10.6,10.7,7,11.1,14.5,25.1,28.9,22.9   
4th,24.4,19.8,21.7,12.6,11.5,13,10.5,22.5,16.8,21.7   
5th,14.1,21.8,18.9,14.4,15.4,11.7,8.4,14,11.4,13.8,23.4
... etc

我需要创建 REXX 代码来查找每个月的最高、最低和平均温度,并将其显示如下

User,Dec
Max,22.9   
Min,21.7   
Mean,23.4

在创建 REXX 代码方面的任何帮助,或任何有关它的文献/方向将不胜感激。

到目前为止我的代码

/*REXX*/                                                                
/* TRACE ?I */                                                          
ADDRESS SYSCALL "READFILE /u/inputdata RECS."                      
                                                                        
IF RC <> 0 THEN DO                                                      
  SAY "ERROR READING FILE"                                              
  EXIT                                                                  
 END                                                                    
                                                                        
 FS=",";  MAXTEMP=""; MINTEMP=""; AVGTEMP=""                            
 DO I = 2 TO RECS.0                                                     
   PARSE VAR RECS.I DAY","JAN","FEB","MAR","APR","JUN","JUL","AUG","SEP","OCT","NOV,"DEC
     DO J = 2 TO RECS.I                                                 
           MAXTEMP = MAX(RECS.I)    /*Needs to add another VAR into MaxtemP*/
           MINTEMP = MIN(RECS.I)    /*same but Min                         */
           AVGTEMP = SUM(RECS.I)/COUNT(RECS.I)  /*Total/The amount of days*/ 
        END                                                                
    END                                                                    
 SAY user,JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC
 SAY MAX,MAXTEMP        /*MAX for each month fill out*/               
 SAY MIN,MINTEMP        /*Min                        */               
 SAY MEAN,AVGTEMP       /*Avg                        */               
END                                                                    

我正在尝试为 MaxTemp、MinTemp 和 MeanTemp 创建一个变量,并在循环进行时添加月份。

解决方法

这是一个可能的实现。它像您一样遍历每条记录;这是外循环(循环变量 ii)。那么每个月的当前温度是

  1. 与该月的当前最大值相比,如果更大则存储
  2. 与该月的当前最小值相比,如果较低则存储
  3. 添加到当月的平均汇总字段

这是内部循环(lop 变量 jj)。 注意这个内部循环中的代码会注意不要处理超过每月最大天数的天数。

由于数据的年份似乎未知,因此无法计算 2 月的正确天数。如果年份已知,您需要添加它。

/*REXX*/                                                                
/* TRACE ?I */
address syscall "readfile /u/inputdata Recs."

if RC <> 0 
then do                                                      
    say "ERROR READING FILE"                                              
    exit 16                                                                  
    end                                                                    
                                                                        
ifs = ","  /* Field separator for parsing input records */
ofs = ","  /* field separator for writing output records */

/* Initialize arrays to aggregate temperature data by month */
MaxTemp. = 0
MinTemp. = 99999
AvgTemp. = 0                           

/* Initialize array of number of days per month */
/* We do not know the year,so we cannot calculate whether February has 28 or 29 days */
DaysPerMonth.1  = 31
DaysPerMonth.2  = 28 /* Need to be adjusted for leap years */
DaysPerMonth.3  = 31
DaysPerMonth.4  = 30
DaysPerMonth.5  = 31
DaysPerMonth.6  = 30
DaysPerMonth.7  = 31
DaysPerMonth.8  = 31
DaysPerMonth.9  = 30
DaysPerMonth.10 = 31
DaysPerMonth.11 = 30
DaysPerMonth.12 = 31
 
/* Split (parse) each input record and fill the DayTemp array with daily temperatures by month */ 

do ii = 2 to Recs.0
    parse var Recs.ii DayNum (ifs) DayTemp.1 (ifs) DayTemp.2  (ifs) DayTemp.3  (ifs) DayTemp.4,(ifs) DayTemp.5 (ifs) DayTemp.6  (ifs) DayTemp.7  (ifs) DayTemp.8,(ifs) DayTemp.9 (ifs) DayTemp.10 (ifs) DayTemp.11 (ifs) DayTemp.12 .
                
    /* For each month,adjust min and max values,and sum up for building average later on */
    do jj =  1 to 12

        /* Don't process values for day numbers greater that number of days in month */
        if ( ii - 1 ) <= DaysPerMonth.jj
        then do

            if MaxTemp.jj < DayTemp.jj
            then MaxTemp.jj = DayTemp.jj
        
            if MinTemp.jj > DayTemp.jj
            then MinTemp.jj = DayTemp.jj
        
            AvgTemp.jj = AvgTemp.jj + DayTemp.jj
                          
            end /* if ( ii - 1 ) ... */
            
        end /* do jj = 1 to 12 */
                            
    end /* do ii = 1 to 12 */
    

Heading = "User,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
Maxima  = "Max"
Minima  = "Min"
Means   = "Mean"

/* Build the min,max and average records by appending value by value */

do ii = 1 to 12
    Maxima = Maxima || ofs || format( MaxTemp.ii,2,1 )
    Minima = Minima || ofs || format( MinTemp.ii,1 )
    Means  = Means  || ofs || format( ( AvgTemp.ii / DaysPerMonth.ii ),1 )
    end 
  
/* Write heading,min,max,and average records */  
say Heading
say Maxima
say Minima
say Means 

提示:不要使用单字母变量名称,因为您无法搜索或搜索并替换此类名称。我总是对循环变量或临时变量使用双字母变量名,例如 ii、jj、kk 等。这些(很可能)从未出现在任何其他上下文的代码中,因此可以轻松完成搜索和替换.