#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUFSZ 80
#define OP_QUIT 0
#define OP_ADD 1
#define OP_MUL 2
#define OP_DEL 3
#define OP_INS 4
#define RANGE_INVALID -1
#define RANGE_ALL 0
#define RANGE_ONE 1
#define RANGE_TWO 2
typedef struct Cell_t {
int valid;
int row,col;
} cell;
typedef struct Range_t {
int Type;
cell From;
cell To;
} range;
int getOp(char *cmd) {
if (strcmp(cmd,"QUIT")==0 || strcmp(cmd,"quit")==0) {
return OP_QUIT;
}
if (strncmp(cmd,"ADD",3)==0 || strncmp(cmd,"add",3)==0) {
return OP_ADD;
}
if (strncmp(cmd,"MUL",3)==0 || strncmp(cmd,"mul",3)==0) {
return OP_MUL;
}
if (strncmp(cmd,"DEL",3)==0 || strncmp(cmd,"del",3)==0) {
return OP_DEL;
}
if (strncmp(cmd,"INS",3)==0 || strncmp(cmd,"ins",3)==0) {
return OP_INS;
}
return -1;
}
cell getCell(char *ptr) {
cell c;
char col = (char)*ptr;
char row = (char)*(ptr+1);
// fprintf(stderr, "DEBUG: cell[%s] = (%c,%c)\n", ptr, row, col);
c.valid = 0;
if ( (col >= 'A' && col <= 'E') &&
(row >= '1' && row <= '5') ) {
c.valid = 1;
c.row = row - '1';
c.col = col - 'A';
}
return c;
}
range getRange(char *ptr) {
range r;
cell from, to;
int l=strlen(ptr);
// fprintf(stderr, "DEBUG: range '%s' l=%d\n", ptr, l);
r.Type = RANGE_INVALID;
if (l==3 && strcmp(ptr,"();")==0) {
r.Type = RANGE_ALL;
return r;
}
if (l==5 && *ptr == '(' && strcmp(ptr+3,");")==0) {
from = getCell(ptr+1);
if (from.valid == 1) {
r.From = from;
r.Type = RANGE_ONE;
}
return r;
}
if (l==8 && *ptr == '(' && *(ptr+3) == ':' && strcmp(ptr+6,");")==0) {
r.Type = RANGE_TWO;
from = getCell(ptr+1);
to = getCell(ptr+4);
if (from.valid == 1 && to.valid == 1) {
int f_row = r.From.row;
int t_row = r.To.row;
int f_col = r.From.col;
int t_col = r.To.col;
if ( ((f_row == t_row) && (f_col < t_col)) ||
((f_col == t_col) && (f_row < t_row)) ) {
r.From = from;
r.To = to;
r.Type = RANGE_TWO;
}
}
return r;
}
return r;
}
range getInsRange(char *ptr) {
range r;
cell from, to;
int l=strlen(ptr);
// fprintf(stderr, "DEBUG: range '%s' l=%d\n", ptr, l);
r.Type = RANGE_INVALID;
if (l==2 && strcmp(ptr,"()")==0) {
r.Type = RANGE_ALL;
return r;
}
if (l==4 && *ptr == '(' && strcmp(ptr+3,")")==0) {
from = getCell(ptr+1);
if (from.valid == 1) {
r.From = from;
r.Type = RANGE_ONE;
}
return r;
}
if (l==7 && *ptr == '(' && *(ptr+3) == ':' && strcmp(ptr+6,")")==0) {
r.Type = RANGE_TWO;
from = getCell(ptr+1);
to = getCell(ptr+4);
if (from.valid == 1 && to.valid == 1) {
int f_row = r.From.row;
int t_row = r.To.row;
int f_col = r.From.col;
int t_col = r.To.col;
if ( ((f_row == t_row) && (f_col < t_col)) ||
((f_col == t_col) && (f_row < t_row)) ) {
r.From = from;
r.To = to;
r.Type = RANGE_TWO;
}
}
return r;
}
return r;
}
void doOperation(int op, range r, double insval) {
fprintf(stderr, "OP = %d\t", op);
if (r.Type == RANGE_ALL)
fprintf(stderr, "ALL");
else if (r.Type == RANGE_ONE)
fprintf(stderr, "(%d,%d)", r.From.row, r.From.col);
else if (r.Type == RANGE_TWO)
fprintf(stderr, "(%d,%d)->(%d,%d)",
r.From.row, r.From.col,
r.To.row, r.To.col
);
else fprintf(stderr, "[ERROR]");
if (op == OP_INS) {
fprintf(stderr, " %1.2lf", insval);
}
fprintf(stderr, "\n");
}
int readCmdLoop() {
char buf[BUFSZ];
char cmd[BUFSZ], arg[BUFSZ], *ptr;
int op, res;
double insval;
range r;
while (1) {
printf(">> ");
if (fgets(buf, sizeof(buf), stdin)==NULL) {
// if user press CTRL+D
fprintf(stderr, "Good bye\n");
break;
}
// printf("[%s]\n", buf);
res=sscanf(buf, "%s %s", cmd, arg);
// printf("res=%d cmd='%s' arg='%s'\n", res, cmd, arg);S
op = getOp(cmd);
if (op==-1) {
fprintf(stderr, "Invalid operation (%s)\n", cmd);
continue;
}
if (op==OP_QUIT) {
fprintf(stderr, "Good Bye\n");
break;
}
ptr = cmd+3;
if (op == OP_INS) {
r = getInsRange(ptr);
sscanf(arg, "%lf", &insval);
} else {
r = getRange(ptr);
}
if (r.Type == RANGE_INVALID) {
fprintf(stderr, "Wrong Range [%s]\n", ptr);
continue;
}
doOperation(op, r, insval);
}
return 0;
}
int main(int argc, char **argv) {
readCmdLoop();
return 0;
}
Comments