Reading an input file in C - c

I have an assignment to create a CPU scheduler by reading in process information from an input file like this:
q 1 tq 4 p1 30 p2 10 p3 24 p4 20 p5 17 p6 4 p7 7 p8 11 p9 8 p10 9 p11 5 p12 6 p13 3 p14 2 p15 1
q 2 tq 5 p1 1 p2 2 p3 2 p4 9 p5 8 p6 5 p7 12 p8 11 p9 15 p10 1 p11 4 p12 8 p13 22 p14 21 p15 30
q 3 tq 30 p1 30 p2 10 p3 24 p4 20 p5 17 p6 4 p7 7 p8 11 p9 8 p10 9 p11 5 p12 6 p13 3 p14 2 p15 1
where q x is "ready queue x", tq y is time quantum y and the rest in the line is in the format pv w, where pv is p1, p2, p3,..., p15 and are the process names and w is the CPU burst time. each queue are to be read from the same input file and stored in separate arrays of struct that contains the time quantum, process name and the CPU burst time:
struct process{
char name[4];
int cputime;
int timequantum;
};
How would I accomplish this?
I should mention that I have only just started with this C course and have never been taught how to read input files in C.

Related

Loop though each observation in SAS

Let say I have a table of 10000 observations:
Obs X Y Z
1
2
3
...
10000
For each observation, I create a macro: mymacro(X, Y, Z) where I use X, Y, Z like inputs. My macro create a table with 1 observation, 4 new variables var1, var2, var3, var4.
I would like to know how to loop through 10000 observations in my initial set, and the result would be like:
Obs X Y Z Var1 Var2 Var3 Var4
1
2
3
...
10000
Update:
The calculation of Var1, Var2, Var3, Var4:
I have a reference table:
Z 25 26 27 28 29 30
0 10 000 10 000 10 000 10 000 10 000 10 000
1 10 000 10 000 10 000 10 000 10 000 10 000
2 10 000 10 000 10 000 10 000 10 000 10 000
3 10 000 10 000 10 000 10 000 10 000 10 000
4 9 269 9 322 9 322 9 381 9 381 9 436
5 8 508 8 619 8 619 8 743 8 743 8 850
6 7 731 7 914 7 914 8 102 8 102 8 258
7 6 805 7 040 7 040 7 280 7 280 7 484
8 5 864 6 137 6 137 6 421 6 421 6 655
9 5 025 5 328 5 328 5 629 5 629 5 929
10 4 359 4 648 4 648 4 934 4 934 5 320
And my have set is like:
Obs X Y Z
1 27 4 9
2
3
10000
So for the first observation (27, 4, 9):
Var1 = (8 619+ 7 914+ 7 040 + 6 137 + 5 328)/ 9 322
Var2 = (8 743+ 8 102+ 7 280+ 6 421 + 5 629 )/ 9 381
So that:
Var1 = Sum of all number in column 27 (X), from the observation 5 (Z+1) to the observation 9 (Z), and divided by the value in the (column 27 (X) - observation 4 (Z))
Var2 = Sum of all number in column 28 (X+1), from the observation 5 (Z+1) to the observation 9 (Z), and divided by the value in the (column 28 (X+1) - observation 4 (Z))
I would convert the reference table to a form that lets you do the calculations for all observations at once. So make your reference table into a tall structure, either by transposing the existing table or just reading it that way to start with:
data ref_tall;
input z #;
do col=25 to 30 ;
input value :comma9. #;
output;
end;
datalines;
0 10,000 10,000 10,000 10,000 10,000 10,000
1 10,000 10,000 10,000 10,000 10,000 10,000
2 10,000 10,000 10,000 10,000 10,000 10,000
3 10,000 10,000 10,000 10,000 10,000 10,000
4 9,269 9,322 9,322 9,381 9,381 9,436
5 8,508 8,619 8,619 8,743 8,743 8,850
6 7,731 7,914 7,914 8,102 8,102 8,258
7 6,805 7,040 7,040 7,280 7,280 7,484
8 5,864 6,137 6,137 6,421 6,421 6,655
9 5,025 5,328 5,328 5,629 5,629 5,929
10 4,359 4,648 4,648 4,934 4,934 5,320
;
Now take your list table HAVE:
data have;
input id x y z;
datalines;
1 27 4 9
2 25 2 4
;
And combine it with the reference table and make your calculations:
proc sql ;
create table want1 as
select a.id
, sum(b.value)/min(c.value) as var1
from have a
left join ref_tall b
on a.x=b.col
and b.z between a.y+1 and a.z
left join ref_tall c
on a.x=c.col
and c.z = a.y
group by a.id
;
create table want2 as
select a.id
, sum(d.value)/min(e.value) as var2
from have a
left join ref_tall d
on a.x+1=d.col
and d.z between a.y+1 and a.z
left join ref_tall e
on a.x+1=e.col
and e.z = a.y
group by a.id
;
create table want as
select *
from want1 natural join want2 natural join have
;
quit;
Results:
Obs id x y z var1 var2
1 1 27 4 9 3.75864 3.85620
2 2 25 2 4 1.92690 1.93220
The reference table can be established in an array that makes performing the specified computations easy. The reference values can than be accessed using a direct address reference.
Example
The reference table data was moved into a data set so the values can be changed over time or reloaded from some source such as Excel. The reference values can be loaded into an array for use during a DATA step.
* reference information in data set, x property column names are _<num>;
data ref;
input z (_25-_30) (comma9. &);
datalines;
0 10,000 10,000 10,000 10,000 10,000 10,000
1 10,000 10,000 10,000 10,000 10,000 10,000
2 10,000 10,000 10,000 10,000 10,000 10,000
3 10,000 10,000 10,000 10,000 10,000 10,000
4 9,269 9,322 9,322 9,381 9,381 9,436
5 8,508 8,619 8,619 8,743 8,743 8,850
6 7,731 7,914 7,914 8,102 8,102 8,258
7 6,805 7,040 7,040 7,280 7,280 7,484
8 5,864 6,137 6,137 6,421 6,421 6,655
9 5,025 5,328 5,328 5,629 5,629 5,929
10 4,359 4,648 4,648 4,934 4,934 5,320
;
* computation parameters, might be a thousand of them specified;
data have;
input id x y z;
datalines;
1 27 4 9
;
* perform computation for each parameters specified;
data want;
set have;
array ref[0:10,1:30] _temporary_;
if _n_ = 1 then do ref_row = 0 by 1 until (last_ref);
* load reference data into an array for direct addressing during computation;
set ref end=last_ref;
array ref_cols _25-_30;
do index = 1 to dim(ref_cols);
colname = vname(ref_cols[index]);
colnum = input(substr(colname,2),8.);
ref[ref_row,colnum] = ref_cols[index];
end;
end;
* perform computation for parameters specified;
array vars var1-var4;
do index = 1 to dim(vars);
ref_column = x + index - 1 ; * column x, then x+1, then x+2, then x+3;
numerator = 0; * algorithm against reference data;
do ref_row = y+1 to z;
numerator + ref[ref_row,ref_column];
end;
denominator = ref[y,ref_column];
vars[index] = numerator / denominator; * result;
end;
keep id x y z numerator denominator var1-var4;
run;

Issues Regarding SAS

I was working on a homework problem regarding using arrays and looping to create a new variable to identify the date of when the maximum blood lead value was obtained but got stuck. For context, here is the homework problem:
In 1990 a study was done on the blood lead levels of children in Boston. The following variables for twenty-five children from the study have been entered on multiple lines per subject in the file lead_sum2018.txt in a list format:
Line 1
ID Number (numeric, values 1-25)
Date of Birth (mmddyy8. format)
Day of Blood Sample 1 (numeric, initial possible range: -9 to 31)
Month of Blood Sample 1 (numeric, initial possible range: -9 to 12)
Line 2
ID Number (numeric, values 1-25)
Day of Blood Sample 2 (numeric, initial possible range: -9 to 31)
Month of Blood Sample 2 (numeric, initial possible range: -9 to 12)
Line 3
ID Number (numeric, values 1-25)
Day of Blood Sample 3 (numeric, initial possible range: -9 to 31)
Month of Blood Sample 3 (numeric, initial possible range: -9 to 12)
Line 4
ID Number (numeric, values 1-25)
Blood Lead Level Sample 1 (numeric, possible range: 0.01 – 20.00)
Blood Lead Level Sample 2 (numeric, possible range: 0.01 – 20.00)
Blood Lead Level Sample 3 (numeric, possible range: 0.01 – 20.00)
Sex (character, ‘M’ or ‘F’)
All blood samples were drawn in 1990. However, during data entry the order of blood samples was scrambled so that the first blood sample in the data file (blood sample 1) may not correspond to the first blood sample taken on a subject, it could be the first, second or third. In addition, some of the months and days and days of blood sampling were not written on the forms. At data entry, missing month and missing day values were each coded as -9.
The team of investigators for this project has made the following decisions regarding the missing values. Any missing days are to set equal to 15, any missing months are to be set equal to 6. Any analyses that are done on this data set need to follow those decisions. Be sure to implement the SAS syntax as indicated for each question. For example, use SAS arrays and loops if the item states that these must be used.
Here is the data that the HW references (it is in list format and was contained in a separate file called lead_sum2018.txt):
1 04/30/78 6 10
1 -9 7
1 14 1
1 1.62 1.35 1.47 F
2 05/19/79 27 11
2 20 -9
2 5 6
2 1.71 1.31 1.76 F
3 01/03/80 11 7
3 6 6
3 27 2
3 3.24 3.4 3.83 M
4 08/01/80 5 12
4 28 -9
4 3 4
4 3.1 3.69 3.27 M
5 12/26/80 21 5
5 3 7
5 -9 12
5 4.35 4.79 5.14 M
6 06/20/81 7 10
6 11 3
6 22 1
6 1.24 1.16 0.71 F
7 06/22/81 19 6
7 3 12
7 29 8
7 3.1 3.21 3.58 F
8 05/24/82 26 7
8 31 1
8 9 10
8 2.99 2.37 2.4 M
9 10/11/82 2 7
9 25 5
9 28 3
9 2.4 1.96 2.71 F
10 . 10 8
10 30 12
10 28 2
10 2.72 2.87 1.97 F
11 11/16/83 19 4
11 15 11
11 7 -9
11 4.8 4.5 4.96 M
12 03/02/84 17 6
12 11 2
12 17 11
12 2.38 2.6 2.88 F
13 04/19/84 2 12
13 -9 6
13 1 7
13 1.99 1.20 1.21 M
14 02/07/85 4 5
14 17 5
14 21 11
14 1.61 1.93 2.32 F
15 07/06/85 5 2
15 16 1
15 14 6
15 3.93 4 4.08 M
16 09/10/85 12 10
16 11 -9
16 23 6
16 3.29 2.88 2.97 M
17 11/05/85 12 7
17 18 1
17 11 11
17 1.31 0.98 1.04 F
18 12/07/85 16 2
18 18 4
18 -9 6
18 2.56 2.78 2.88 M
19 03/02/86 19 4
19 11 3
19 19 2
19 0.79 0.68 0.72 M
20 08/19/86 21 5
20 15 12
20 -9 4
20 0.66 1.15 1.42 F
21 02/22/87 16 12
21 17 9
21 13 4
21 2.92 3.27 3.23 M
22 10/11/87 7 6
22 1 12
22 -9 3
22 1.43 1.42 1.78 F
23 05/12/88 12 2
23 21 4
23 17 12
23 0.55 0.89 1.38 M
24 08/07/88 17 6
24 27 11
24 6 2
24 0.31 0.42 0.15 F
25 01/12/89 4 7
25 15 -9
25 23 1
25 1.69 1.58 1.53 M
A) Input the data and in the data step:
1) make sure that Date of Birth variable is recorded as a SAS date;
2) use SAS arrays and looping to create a SAS date variable for each of the three blood samples and to address the missing data in accordance to the decisions of the investigators. Hint: use a single array and do loop to recode the missing values for day and month, separately, and an array/do loop for creating the SAS date variable;
3) use a SAS function to create a variable for the highest, i.e., maximum, blood lead value for each child;
4) use SAS arrays and looping to identify the date on which this largest value was obtained and create a new variable for the date of the largest blood lead value;
5) determine the age of the child in years when the largest blood lead value was obtained (rounded to two decimal places);
6) create a new variable based on the age of the child in years when the largest lead value was obtained (call it, “agecat”) that takes on three levels: for children less than 4 years old, agecat should equal 1; for children at least 4 years old, but less than 8, agecat should equal 2; and for children at least 8 years of age, agecat should be 3.;
7) print out the variables for the date of birth, date of the largest lead level, age at blood sample for the largest blood lead level, agecat, sex, and the largest blood lead level (Only print out these requested variables). All dates should be formatted to use the mmddyy10. format on the output.
The code I used in response to this was:
libname HW3 'C:\Users\johns\Desktop\SAS';
filename HW3new 'C:\Users\johns\Desktop\SAS\lead_sum2018.txt';
data one;
infile HW3new;
informat dob mmddyy8.;
input #1 id dob dbs1 mbs1
#2 dbs2 mbs2
#3 dbs3 mbs3
#4 bls1 bls2 bls3 sex;
array dbs{3} dbs1 dbs2 dbs3;
array mbs{3} mbs1 mbs2 mbs3;
do i=1 to 3;
if dbs{i}=-9 then dbs{i}=15;
end;
do i=4 to 6;
if mbs{i}=-9 then mbs{i}=6;
end;
array date{3} mdy1 mdy2 mdy3;
do i=1 to 3;
date{i}=mdy(mbs{i}, dbs{i}, 1990);
end;
maxbls=max(of bls1-bls3);
array bls{3} bls1 bls2 bls3;
array maxdte{3} maxdte1 maxdte2 maxdte3;
do i=1 to i=3;
if bls{i}=maxbls then maxdte=i;
end;
agemax=maxdte-dob;
ageest=round(agemax/365.25,2);
if agemax=. then agecat=.;
else if agemax < 4 then agecat=1;
else if 4 <= agemax < 8 then agecat=2;
else if agemax ge 8 then agecat=3;
run;
I received this error:
22 maxbls=max(of bls1-bls3);
23 array bls{3} bls1 bls2 bls3;
24 array maxdte{3} maxdte1 maxdte2 maxdte3;
25 do i=1 to i=3;
26 if bls{i}=maxbls then maxdte=i;
ERROR: Illegal reference to the array maxdte.
27 end;
Does anyone have any tip is regards to this issue? What did I do wrong? Was I supposed to create an additional array for the date of when the maximum blood lead sample value was collected? Thanks!
**I'm stuck on #4 of Part A, but I included the other parts for context. Thanks!
**Edits: I included the data that I had to read into SAS and the file name of the file it came from
Just from looking at the code immediately prior to the error, you have a problem on this line:
26 if bls{i}=maxbls then maxdte=i;
You are getting the error because you are attempting to assign a value to the array maxdte. Arrays cannot be assigned values like that (unless you are using the deprecated do over syntax...) Instead, choose an element of the array and assign the value to the element. E.g. you could do:
26 if bls{i}=maxbls then maxdte{1}=i;
Or instead of a literal 1, you could use a variable containing the relevant array index.
You are not properly handling ID field from lines #2-4
input #1 id dob dbs1 mbs1
#2 dbs2 mbs2
#3 dbs3 mbs3
#4 bls1 bls2 bls3 sex;
For example you need to skip field 1 on line 2-3 or read the ids into array perhaps to check they are all the same.
input #1 id dob dbs1 mbs1
#2 id2 dbs2 mbs2
#3 id3 dbs3 mbs3
#4 id4 bls1 bls2 bls3 sex;
This example show how to check that you have 4 lines with the same ID and if you do read the rest of the variables or execute LOSTCARD. ID 3 has a missing record;
353 data ex;
354 infile cards n=4 stopover;
355 input #1 id #2 id2 #3 id3 #4 id4 #;
356 if id eq id2 eq id3 eq id4
357 then input #1 id dob:mmddyy. dbs1 mbs1
358 #2 id2 dbs2 mbs2
359 #3 id3 dbs3 mbs3
360 #4 id4 bls1 bls2 bls3 sex :$1.;
361 else lostcard;
362 format dob mmddyy.;
363 cards;
NOTE: LOST CARD.
RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
372 3 01/03/80 11 7
373 3 27 2
374 3 3.24 3.4 3.83 M
375 4 08/01/80 5 12
NOTE: LOST CARD.
376 4 28 -9
NOTE: LOST CARD.
377 4 3 4
NOTE: The data set WORK.EX has 3 observations and 15 variables.
data ex;
infile cards n=4 stopover;
input #1 id #2 id2 #3 id3 #4 id4 #;
if id eq id2 eq id3 eq id4
then input #1 id dob:mmddyy. dbs1 mbs1
#2 id2 dbs2 mbs2
#3 id3 dbs3 mbs3
#4 id4 bls1 bls2 bls3 sex :$1.;
else lostcard;
format dob mmddyy.;
cards;
1 04/30/78 6 10
1 -9 7
1 14 1
1 1.62 1.35 1.47 F
2 05/19/79 27 11
2 20 -9
2 5 6
2 1.71 1.31 1.76 F
3 01/03/80 11 7
3 27 2
3 3.24 3.4 3.83 M
4 08/01/80 5 12
4 28 -9
4 3 4
4 3.1 3.69 3.27 M
;;;;
run;
proc print;
run;

How to create a Power BI pivot table without drill-down?

I have data of the following form for several categories and years. The data is too large for Import so I am using DirectQuery.
Id Cat1 Cat2 Cat3 Year Value
1 A X Q 2000 1
2 A X R 2000 2
3 A Y Q 2000 3
4 A Y R 2000 4
5 A X Q 2000 1
6 A X R 2000 2
7 A Y Q 2000 3
8 A Y R 2000 4
9 A X Q 2001 1
10 A X R 2001 2
11 A Y Q 2001 3
12 A Y R 2001 4
13 A X Q 2001 1
14 A X R 2001 2
15 A Y Q 2001 3
16 A Y R 2001 4
I would like construct a pivot table similar to what can be done in Excel.
Cat1 Cat2 Cat3 2000 2001
A X Q 2 2
A X R 4 4
A Y Q 6 6
A Y R 8 8
I tried this with the Matrix option by; placing columns Cat1, Cat2, and Cat3 in the Rows, placing Year in the Columns, and placing Value in the Values. Unfortunately, this produces a hierarchical view.
Cat1 2000 2001
A 20 20
X 6 6
Q 2 2
R 4 4
Y 14 14
Q 6 6
R 8 8
How do I get the simpler Excel pivot table view of the data instead of the hierarchical view?
I'm not sure if it's possible to get the row headers to repeat like in your example, but if you go to Format > Row headers > Stepped layout and toggle that off, then your matrix should change from what you are seeing (below left) to something closer to what you want (below right).

Fill the matrix entries using an array

I have a vector of elements
p1 p2 p3 p4 ...
and I'm trying to build, from them, the following matrix
p1 p2 p3 1 1 1 1 1 1 1 1 1 ...
p1 p2 p3 p4 p5 p6 1 1 1 1 1 1 ...
p1 p2 p3 p4 p5 p6 p7 p8 p9 1 1 1 ...
p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 ...
and so on. I tried to use
blockmatrix
For example
p<-1:6
A<-head(p,3)
B<-c(1,1,1)
D<-tail(p,3)
blockmatrix(names=c("A","B","C","D"),A=A,C=B,B=A,D=D,dim=c(2,2))
But the problem is to obtain block matrices of larger size. (This code works only for two blocks, for three block I would add other labels in the field "names", and so on for four blocks, five...)
This is another solution, written after the read of answers:
x<-2:10
mat<- t(replicate(3, x))
mat[col(mat)>3*row(mat)] <- 1
This will give you a dataframe output, but you can transform it into a matrix.
library(dplyr)
library(tidyr)
# example vector
x = c(10,11,12,13,14,15)
expand.grid(id_row=1:length(x), x=x) %>% # combine vector values and a sequence of numbers (id = row positions)
group_by(id_row) %>% # for each row position
mutate(id_col = row_number()) %>% # create a vector of column positions (needed for reshaping later)
ungroup() %>% # forget the grouping
mutate(x = ifelse(id_col > id_row, 1, x), # replace values with 1 where necessary
id_col = paste0("Col_", id_col)) %>% # update names of this variable
spread(id_col, x) %>% # reshape data
select(-id_row) # remove unnecessary column
# # A tibble: 6 x 6
# Col_1 Col_2 Col_3 Col_4 Col_5 Col_6
# * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 10 1 1 1 1 1
# 2 10 11 1 1 1 1
# 3 10 11 12 1 1 1
# 4 10 11 12 13 1 1
# 5 10 11 12 13 14 1
# 6 10 11 12 13 14 15
It is not clear about all the conditions. Here is a base R option
m1 <- t(replicate(length(x), x))
m1[upper.tri(m1)] <- 1
m1
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 10 1 1 1 1 1
#[2,] 10 11 1 1 1 1
#[3,] 10 11 12 1 1 1
#[4,] 10 11 12 13 1 1
#[5,] 10 11 12 13 14 1
#[6,] 10 11 12 13 14 15
data
x <- c(10,11,12,13,14,15)
this should give you desired output, in Base R
a<- c("p1","p2","p3","p4","p5","p6","p7","p8","p9","p10","p11","p12")
lena <- length(a)
b<- matrix(data=rep(a,lena%/%3),nrow=lena%/%3,ncol = lena,byrow=T)
for (i in (1:(nrow(b)-1)))
{
for (j in ((3*i+1):ncol(b)))
{
b[i,j] <- 1
}
}

SAS: Stuck in a loop even with changes made? Any pointers?

This is the code that I am using, I have tried changing a few things around but I think I am getting stuck in an endless loop.
DATA songs;
INFILE datalines;
INPUT City $ 1-15 Age domk wj hwow simbh kt aomm libm tr filp ttr;
ARRAY song (10) domk wj hwow simbh kt aomm libm tr filp ttr;
DO i = 1 TO 10;
IF song(i) = 9 THEN song(i) = .;
END;
datalines;
Albany 54 4 3 5 9 9 2 1 4 4 9
Richmond 33 5 2 4 3 9 2 9 3 3 3
Oakland 27 1 3 2 9 9 9 3 4 2 3
Richmond 41 4 3 5 5 5 2 9 4 5 5
Berkeley 18 3 4 9 1 4 9 3 9 3 2
;
PROC PRINT DATA = songs;
TITLE 'WBRK Song Survey';
RUN;
Can you point out what is wrong here? I have already tried changing the DO loop by adding an incremental i.
DO i = 1 TO 10;
IF song(i) = 9 THEN song(i) = .;
i+1;
END;
but the result is the same. I am new to SAS although not new to programming. I am wondering if I am making a syntax error here. Either way, any help is appreciated.
As I suspected, there was an issue with your import statement, at least for me. The following code worked for me:
DATA songs;
INFILE datalines;
informat city $20.;
INPUT City $ Age domk wj hwow simbh kt aomm libm tr filp ttr;
ARRAY song (10) domk wj hwow simbh kt aomm libm tr filp ttr;
DO i = 1 TO 10;
IF song(i) = 9 THEN song(i) = .;
END;
datalines;
Albany 54 4 3 5 9 9 2 1 4 4 9
Richmond 33 5 2 4 3 9 2 9 3 3 3
Oakland 27 1 3 2 9 9 9 3 4 2 3
Richmond 41 4 3 5 5 5 2 9 4 5 5
Berkeley 18 3 4 9 1 4 9 3 9 3 2
;
PROC PRINT DATA = songs;
TITLE 'WBRK Song Survey';
RUN;

Resources