RosettaCodeData/Task/CSV-data-manipulation/ALGOL-68/csv-data-manipulation.alg

89 lines
2.1 KiB
Plaintext

# count occurrances of a char in string #
PROC char count = (CHAR c, STRING str) INT:
BEGIN
INT count := 0;
FOR i TO UPB str DO
IF c = str[i] THEN count +:= 1
FI
OD;
count
END;
# split string on separator #
PROC char split = (STRING str, CHAR sep) FLEX[]STRING :
BEGIN
INT strlen := UPB str, cnt := 0;
INT len, p;
INT start := 1;
[char count (sep, str) + 1] STRING list;
WHILE start <= strlen ANDF char in string (sep, p, str[start:]) DO
p +:= start - 1;
list[cnt +:= 1] := str[start:p-1];
start := p + 1
OD;
IF cnt = 0 THEN list[cnt +:= 1] := str
ELIF start <= UPB str + 1 THEN list[cnt +:= 1] := str[start:]
FI;
list
END;
PROC join = ([]STRING words, STRING sep) STRING:
IF UPB words > 0 THEN
STRING str := words [1];
FOR i FROM 2 TO UPB words DO
str +:= sep + words[i]
OD;
str
ELSE
""
FI;
# read a line from file #
PROC readline = (REF FILE f) STRING:
BEGIN
STRING line;
get (f, line); new line (f);
line
END;
# Add one item to tuple #
OP +:= = (REF FLEX[]STRING tuple, STRING item) VOID:
BEGIN
[UPB tuple+1]STRING new;
new[:UPB tuple] := tuple;
new[UPB new] := item;
tuple := new
END;
# convert signed number TO INT #
OP TOINT = (STRING str) INT:
BEGIN
INT n := 0, sign := 1;
FOR i TO UPB str WHILE sign /= 0 DO
IF is digit (str[i]) THEN n := n * 10 + ABS str[i] - ABS "0"
ELIF i = 1 AND str[i] = "-" THEN sign := -1
ELIF i /= 1 OR str[i] /= "+" THEN sign := 0
FI
OD;
n * sign
END;
OP STR = (INT i) STRING: whole (i,0);
# The main program #
FILE foo;
open (foo, "CSV_data_manipulation.data", stand in channel);
FLEX[0]STRING header := char split (readline (foo), ",");
header +:= "SUM";
print ((join (header, ","), new line));
WHILE NOT end of file (foo) DO
FLEX[0]STRING fields := char split (readline (foo), ",");
INT sum := 0;
FOR i TO UPB fields DO
sum +:= TOINT fields[i]
OD;
fields +:= STR sum;
print ((join (fields, ","), new line))
OD;
close (foo)