CellMate

From IPRE Wiki
Jump to: navigation, search

Programming Paradigms

First Project: cellmate.c

Ideas for cellmate.c

escape means next is literal  (e.g.  "\,")
-strings can be in "..."
-comemnts are marked by the character #
-blank line separates table
-override defaults
 *line
-interactive module(but not GUI)commands
-delimiter --> tabs, spaces, | 
-useful for both reading and writing data

data.cm

Line0

*Lastname, Firstname, Age
*String, String, Number
"Smith, Sally", 18
"Jones, Jim\, Jr.", 19


*Teacher, Grade
"Jones, Jim", 3.7

cellmate.c

#include <stdio.h>

int main() {
    char rows[100][50];
    char c;
    int row_count = 0;
    while ((c = getc(stdin)) !=EOF) {
         printf("c is %c (%i)\n", c, c);
         if (c==10) {
           row_count++;
         }
    }
    printf("You read in %i rows. \n", row_count);
}


cellmate-3.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
  char buffer[1024];
  char *rows[100];
  char c;
  int row_count = 0;
  int col_count = 0;
  int i;
  while ((c = getc(stdin)) !=EOF) {
    //printf("c is %c (%i)\n", c, c);                                                          
    switch(c) {
    case '\n':
      buffer[col_count] = 0;
      rows[row_count] = (char *) malloc(strlen(buffer));
      strcpy(rows[row_count], buffer);
      row_count++;
      col_count = 0;
      break;
    default:
      if (col_count < 1024) {
        buffer[col_count++] = c;
      } else {
        printf("ERROR: row too long!\n");
      }
    }
  }
  printf("You read in %i rows. \n", row_count);
  for (i = 0; i < row_count; i++) {
    printf("\t%s\n", rows[i]);
  }
}

cellmate-4.c

The program that DB handed out in class on February 18, 2008.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
  char buffer[1024];
  char *matrix[500][500];
  char c, delimiter = ',';
  int row_count = 0;
  int max_col = 0;
  int col_count = 0;
  int buf_count = 0;
  int i, row, col;

  while ((c = getc(stdin)) !=EOF) {
      switch(c) {
      case '\n':
	if (row_count < 500) {
	  buffer[buf_count] = 0;
	  matrix[row_count][col_count] = (char *) malloc(strlen(buffer));
	  strcpy(matrix[row_count][col_count], buffer);
	  row_count++;
	  max_col = (col_count + 1) > max_col ? (col_count + 1): max_col;
	  buf_count = 0;
	  col_count = 0;
	}
	break;
      default:
	if (delimiter == c) {
	  if (row_count < 500) {
	    buffer[buf_count] = 0;
	    matrix[row_count][col_count] = (char *) malloc(strlen(buffer));
	    strcpy(matrix[row_count][col_count], buffer);
	    col_count++;
	    max_col = col_count > max_col ? col_count: max_col;
	    buf_count = 0;
	  }
	  continue;
	}
	if (buf_count < 1024) {
	  buffer[buf_count++] = c;
	} else {
	  printf("ERROR: cell string too long!\n");
	}
      }
    }
    printf("You read in %i rows. \n", row_count);
    printf("You read in %i cols. \n", max_col);
    for (row = 0; row < row_count; row++) {
      for (col = 0; col < max_col; col++) {
	printf("\t%s", matrix[row][col]);
      }
      printf("\n");
    }
}

cellmate-6.c hints

We covered two items in class on Monday Feb 18, 2008:

  1. adding arguments (flags) to our program
  2. removing the need for hardcoding any limits to rows and columns

The first part was very easy; we just add:

int main(int argc, char *argv[]) 

to any main, and it will receive our command-line inputs. But, we still need to be able to use them. We wrote some code something like:

  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      switch (argv[i][1]) {
      case 'd':
	delimiter = argv[++i][0];
	break;
      default:
	printf("unknown option: '%s'\n", argv[i]);
      }
    } else {
      printf("unknown option: '%s'\n", argv[i]);
    }
  }

We also added some error checking code, to prevent "Segment Faults". Recall that we added the -d flag to change the delimiter. You can add other flags too to help you debug the next versions. For example, you could add a -v flag to make your program printf "verbose" debugging information. Remember to end debug printf statements with a newline (so that they will print out, rather than being "buffered").

Finally, we discussed the idea of a "struct", a set of data elements that act as a single unit (sort of like an object).

We created a struct called "cell" and a short name for "struct cell *" called "Cell":

struct cell {
  char *buffer;
  struct cell *next_row;
  struct cell *next_col;
};
typedef struct cell *Cell;

Finally, we changed matrix to:

Cell matrix = (Cell) malloc(sizeof(struct cell));

In order to complete this next assignment, you'll probably want to keep pointers to the beginning of the current row, and the current cell. Initially, that could be:

Cell current_row = matrix;
Cell current_cell = matrix;

If you want to add a string to the current cell, you allocate space, and copy the string in:

  current_cell->buffer = (char *) malloc(strlen(buffer));
  strcpy(current_cell->buffer, buffer);

If that was the end of a row, you need to make a new row:

  current_row->next_row = (Cell) malloc(sizeof(struct cell));
  current_cell = current_row->next_row;
  current_row = current_cell;

If you just added another column, you'll need to make a new column:

  current_cell->next_col = (Cell) malloc(sizeof(struct cell));
  current_cell = current_cell->next_col;

Finally, you'll need to be able to traverse the rows and cols to print out the data. That might look something like:

  current_row = matrix;
  done = 0;
  while (current_row != NULL) {
    current_cell = current_row;
    while (current_cell != NULL) {
      if (current_cell->buffer != NULL) {
	printf("| %s ", current_cell->buffer);
	current_cell = current_cell->next_col;
      } else {
	done = 1;
	break;
      }
    }
    if (done != 1) {
      printf("|\n");
      current_row = current_row->next_row;
    } else {
      break;
    }
  }

See if you can put all of this together to create a cellmate that will read in a multi-column input, store it, and print it back out.

Please send me email if you have any questions.

cellmate-7.c hints

int sumcol(Cell start, int column) {
   int total = 0;
   // start at start, and go through all of the rows
   while (...) {
      // until you get to the right column
      // use atoi() to turn the string into an int
      total += atoi(buffer);
   }
   return total;
}

cellmate-7a.c

Today, we will do a pair programming exercise. You will be assigned a partner. One of you will type while the other stands behind and watches and talks. Sort of "The Programmer with Two Brains". You will switch about every 20 minutes. Your mission is to:

  1. Take the following code
  2. Fix the formatting
  3. There are three bugs. Fix the following:
    1. There is a compile-time error
    2. There is a runtime-time error
    3. There is an off-by-one error
  4. In order to fix these bugs, you should add a "-v" verbosity flag to cellmate. "-v 0" is the default (don't be verbose), "-v 1" is a little verbose, and "-v 9" is maximally verbose.
  5. Add comments to the code, including both of your names
  6. Print out a copy before the end of class
  7. If you have extra time, add the following functions:
    1. sumrow() - sums a row
    2. countcol() - number of elements in col
    3. avecol() - sum divided by count
    4. sortbycol() - changes the order of the rows by comparing col values
#include <stdio.h>
#include <string.h>
#include <std1ib.h>

  struct cell { char *buffer; struct cell *next_row; struct cell *next_col; };
  typedef struct cell *Cell;

  int sum(Cell matrix, int column) { Cell current_row = matrix;
  int total = 0;  int col_count = 0;  while (current_row != NULL) {
  Cell current_col = current_row;
  col_count = 0;
  while (col_count < column) {
  current_col = current_col->next_col;
  col_count++;} if (current_col->buffer != NULL) {
  total = atoi(current_col->buffer);
}
current_row = current_row->next_row;
}
return total;
}

int main(int argc, char *argv[]) {
char buffer[1024];
Cell matrix = (Cell) malloc(sizeof(struct cell));
Cell current_row = matrix;
Cell current_cell = matrix;
char c, delimiter = ',';
int cell_count = 0;
int max_col = 0;
int col_count = 0;
int buf_count = 0;
int i, done, first;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'd':
delimiter = argv[++i][0];
break;
default:
printf("unknown option: '%s'\n", argv[i]);
}
} else {
printf("unknown option: '%s'\n", argv[i]);
}
}

while ((c = getc(stdin)) !=EOF) { //printf("c is %c (%i)\n", c, c);
switch(c) {
case '\n':
buffer[buf_count] = 0;
if (strlen(buffer) > 0) {
current_cell->buffer = (char *) malloc(strlen(buffer));
strcpy(current_cell->buffer, buffer);
cell_count++;
max_col = (col_count + 1) > max_col ? (col_count + 1): max_col;
buf_count = 0;
col_count = 0;
current_row->next_row = (Cell) malloc(sizeof(struct cell));
current_cell = current_row->next_row;
current_row = current_cell;
}
break;
default:
if (delimiter == c) 
{
buffer[buf_count] = 0;
if (strlen(buffer) > 0) {
current_cell->buffer = (char *) malloc(strlen(buffer));
strcpy(current_cell->buffer, buffer);
col_count++;
max_col = col_count > max_col ? col_count: max_col;
buf_count = 0;
current_cell->next_col = (Cell) malloc(sizeof(struct cell));
current_cell = current_cell->next_col;
}
continue;
}
if (buf_count < 1024) {
buffer[buf_count++] = c;
} else {
printf("ERROR: cell string too long!\n");
}
}
}
printf("You read in %i rows. \n", cell_count);
printf("You read in %i cols. \n", max_col);
current_row = matrix;
done = 0;
i = 0;
while (current_row != NULL) {
current_cell = current_row;
while (current_cell != NULL) {
if (current_cell->buffer != NULL) {
printf("| %s ", current_cell->buffer);
current_cell = current_cell->next_col;
} else {
done = 1;
break;
}
}
if (done != 1) {
printf("|\n");
current_row = current_cell->next_row;
} else {
break;
}
}
printf("Sum of column %d is %d\n", 0, sum(matrix, 0));
}

cellmate-8.c

cellmate-8.c:

/* 
   cellmate-8.c
   Doug Blank
 
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "cellfuncs.h"

int main(int argc, char *argv[]) {
  int i;
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      switch (argv[i][1]) {
      case 'd':
	delimiter = argv[++i][0];
	break;
      case 'v':
	verbosity = atoi(argv[++i]);
	break;
      default:
	printf("unknown flag: '%s'\n", argv[i]);
      }
    } else {
      printf("unknown option: '%s'\n", argv[i]);
    }
  }
  Table table = read_table();
  if (verbosity > 0) {
    printf(" 1: You read in a (%i x %i) matrix. \n", 
	   table->max_rows,
	   table->max_cols);
  } 
  printTable(table);
  for (i = 0; i < table->max_cols; i++) 
    printf("Sum of column %d is %d\n", i+1, sumcol(table, i+1));
}


cellfuncs.h:

int verbosity;
char delimiter;

struct cell { 
  char *buffer; 
  struct cell *next_row; 
  struct cell *next_col; 
};
typedef struct cell *Cell;

struct table {
  Cell matrix;
  int max_cols;
  int max_rows;
};
typedef struct table *Table;

void printTable(Table table);
int sumcol(Table table, int column);
Table read_table();

cellfuncs.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "cellfuncs.h"

int verbosity = 0;
char delimiter = ',';

void printTable(Table table) {
  Cell start = table->matrix;
  Cell current_row = start;
  Cell current_cell = NULL;
  // For each row:
  while (current_row != NULL) {
    current_cell = current_row;
    printf("|");
    // For each col:
    while (current_cell != NULL) {
      if (current_cell->buffer != NULL) {
	printf(" %s |", current_cell->buffer);
      } else {
	printf(" (empty) |");
      }
      current_cell = current_cell->next_col;
    }
    printf("\n");
    current_row = current_row->next_row;
  }
}

int sumcol(Table table, int column) { 
  Cell current_row = table->matrix;
  int total = 0;  
  int col_count = 0;  
  while (current_row != NULL) {
    Cell current_col = current_row;
    col_count = 0;
    while (col_count < column - 1) {
      if (current_col != NULL) {
	current_col = current_col->next_col;
	col_count++;
      } else {
	printf("ERROR: invalid col: %d\n", column);
	return 0;
      }
    }
    if (current_col == NULL) {
      printf("ERROR: invalid col: %d\n", column);
      return 0;
    }
    if (col_count == column - 1 ) {
      if (current_col->buffer != NULL) {
	total += atoi(current_col->buffer);
      }
    } else {
      printf("ERROR: invalid col: %d\n", column);
      return 0;
    }
    current_row = current_row->next_row;
  }
  return total;
}

Table read_table() {
  Table table = (Table) malloc(sizeof(struct table));
  char c, buffer[1024];
  Cell current_row = NULL;
  Cell current_cell = NULL;
  int col_count = 0;
  int buf_count = 0;
  int i, newrow = 0;
  while ((c = getc(stdin)) != EOF) { 
    if (c == '\n') {
      if (verbosity > 8) 
	printf("         9: c is '\\n' (%i)\n", c, c);
      buffer[buf_count] = 0;
      if (current_cell == NULL) {
	if (verbosity > 0) printf(" 1: setting matrix1\n");
	current_cell = (Cell) malloc(sizeof(struct cell));
	table->matrix = current_cell;
	current_row = table->matrix;
      } else {
	if (newrow) {
	  newrow = 0; // set = 1 below because newline
	  current_row->next_row = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_row->next_row;
	  current_row = current_cell;
	} else {
	  current_cell->next_col = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_cell->next_col;
	}
      }
      if (strlen(buffer) > 0) {
	current_cell->buffer = (char *) malloc(strlen(buffer));
	strcpy(current_cell->buffer, buffer);
      }
      table->max_rows++;
      table->max_cols = (col_count + 1) > table->max_cols ? 
	(col_count + 1): table->max_cols;
      buf_count = 0;
      col_count = 0;
      newrow = 1;
    } else if (c == delimiter) {
      if (verbosity > 8) 
	printf("         9: c is '%c' (%i) [delimiter]\n", c, c);
      buffer[buf_count] = 0;
      if (newrow) {
	newrow = 0;
	if (current_cell == NULL) {
	  if (verbosity > 0) printf(" 1: setting matrix with newrow\n");
	  current_cell = (Cell) malloc(sizeof(struct cell));
	  table->matrix = current_cell;
	} else {
	  current_row->next_row = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_row->next_row;
	}
	current_row = current_cell;
      } else {
	if (current_cell == NULL) {
	  if (verbosity > 0) printf(" 1: setting matrix\n");
	  current_cell = (Cell) malloc(sizeof(struct cell));
	  table->matrix = current_cell;
	  current_row = table->matrix;
	} else {
	  current_cell->next_col = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_cell->next_col;
	}
      }
      if (strlen(buffer) > 0) {
	current_cell->buffer = (char *) malloc(strlen(buffer));
	strcpy(current_cell->buffer, buffer);
      }
      col_count++;
      table->max_cols = col_count > table->max_cols ? col_count: table->max_cols;
      buf_count = 0;
    } else if (c == '#' && buf_count == 0) {
      // read to end of line
      while ((c = getc(stdin)) != '\n');
    } else if (buf_count < 1024) {
      if (verbosity > 8) 
	printf("         9: c is '%c' (%i)\n", c, c);
      buffer[buf_count++] = c;
    } else {
      printf("ERROR: cell string too long!\n");
    }
    if (verbosity > 0) 
      if (current_cell == NULL) {
	printf(" 1: current_cell = NULL\n");
      } else {
	printf(" 1: current_cell->buffer = '%s'\n", current_cell->buffer);
      }
  }
  return table;
}

cellmate-9

This version adds commands.

cellfuncs.c:

//cellfuncs.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "cellfuncs.h"

int verbosity = 0;
char delimiter = ',';

void printTable(Table table) {
  Cell start = table->matrix;
  Cell current_row = start;
  Cell current_cell = NULL;
  // For each row:
  while (current_row != NULL) {
    current_cell = current_row;
    printf("|");
    // For each col:
    while (current_cell != NULL) {
      if (current_cell->buffer != NULL) {
	printf(" %s |", current_cell->buffer);
      } else {
	printf(" (empty) |");
      }
      current_cell = current_cell->next_col;
    }
    printf("\n");
    current_row = current_row->next_row;
  }
}

int sumcol(Table table, int column) { 
  Cell current_row = table->matrix;
  int total = 0;  
  int col_count = 0;  
  while (current_row != NULL) {
    Cell current_col = current_row;
    col_count = 0;
    while (col_count < column - 1) {
      if (current_col != NULL) {
	current_col = current_col->next_col;
	col_count++;
      } else {
	printf("ERROR: invalid col: %d\n", column);
	return 0;
      }
    }
    if (current_col == NULL) {
      printf("ERROR: invalid col: %d\n", column);
      return 0;
    }
    if (col_count == column - 1 ) {
      if (current_col->buffer != NULL) {
	total += atoi(current_col->buffer);
      }
    } else {
      printf("ERROR: invalid col: %d\n", column);
      return 0;
    }
    current_row = current_row->next_row;
  }
  return total;
}

char *get_string(void) {
  char buffer[1024];
  char *temp;
  int count = 0;
  char c;
  while ((c = getc(stdin)) == ' ');
  buffer[count++] = c;
  while ((c = getc(stdin)) != ' ' && c != '\n') {
    buffer[count++] = c;
  }
  buffer[count] = '\0';
  temp = (char *) malloc(strlen(buffer));
  strcpy(temp, buffer);
  return temp;
}

Table read_table() {
  Table table = (Table) malloc(sizeof(struct table));
  char c, buffer[1024];
  Cell current_row = NULL;
  Cell current_cell = NULL;
  int col_count = 0;
  int buf_count = 0;
  int i, newrow = 0;
  while ((c = getc(stdin)) != EOF) { 
    if (((newrow == 1) || ((newrow == 0) && (table->matrix == NULL))) 
	&& c == '*') {
      if (verbosity > 0) 
	printf(" 1: processing function...\n");
      char * function_name = get_string();
      if (verbosity > 0) 
	printf(" 1: function name = '%s'\n", function_name);
      char * arg = get_string();
      if (verbosity > 0) 
	printf(" 1: arg = '%s'\n", arg);
      if (strcmp(function_name, "sumcol") == 0) {
	printf("# sumcol(%d) => %d\n", atoi(arg), sumcol(table, atoi(arg)));
      }
    } else if (c == '\n') {
      if (verbosity > 8) 
	printf("         9: c is '\\n' (%i)\n", c, c);
      buffer[buf_count] = 0;
      if (current_cell == NULL) {
	if (verbosity > 0) printf(" 1: setting matrix1\n");
	current_cell = (Cell) malloc(sizeof(struct cell));
	table->matrix = current_cell;
	current_row = table->matrix;
      } else {
	if (newrow) {
	  newrow = 0; // set = 1 below because newline
	  current_row->next_row = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_row->next_row;
	  current_row = current_cell;
	} else {
	  current_cell->next_col = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_cell->next_col;
	}
      }
      if (strlen(buffer) > 0) {
	current_cell->buffer = (char *) malloc(strlen(buffer));
	strcpy(current_cell->buffer, buffer);
      }
      table->max_rows++;
      table->max_cols = (col_count + 1) > table->max_cols ? 
	(col_count + 1): table->max_cols;
      buf_count = 0;
      col_count = 0;
      newrow = 1;
    } else if (c == delimiter) {
      if (verbosity > 8) 
	printf("         9: c is '%c' (%i) [delimiter]\n", c, c);
      buffer[buf_count] = 0;
      if (newrow) {
	newrow = 0;
	if (current_cell == NULL) {
	  if (verbosity > 0) printf(" 1: setting matrix with newrow\n");
	  current_cell = (Cell) malloc(sizeof(struct cell));
	  table->matrix = current_cell;
	} else {
	  current_row->next_row = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_row->next_row;
	}
	current_row = current_cell;
      } else {
	if (current_cell == NULL) {
	  if (verbosity > 0) printf(" 1: setting matrix\n");
	  current_cell = (Cell) malloc(sizeof(struct cell));
	  table->matrix = current_cell;
	  current_row = table->matrix;
	} else {
	  current_cell->next_col = (Cell) malloc(sizeof(struct cell));
	  current_cell = current_cell->next_col;
	}
      }
      if (strlen(buffer) > 0) {
	current_cell->buffer = (char *) malloc(strlen(buffer));
	strcpy(current_cell->buffer, buffer);
      }
      col_count++;
      table->max_cols = col_count > table->max_cols ? col_count: table->max_cols;
      buf_count = 0;
    } else if (c == '#' && buf_count == 0) {
      // read to end of line
      while ((c = getc(stdin)) != '\n');
    } else if (buf_count < 1024) {
      if (verbosity > 8) 
	printf("         9: c is '%c' (%i)\n", c, c);
      buffer[buf_count++] = c;
    } else {
      printf("ERROR: cell string too long!\n");
    }
    if (verbosity > 0) 
      if (current_cell == NULL) {
	printf(" 1: current_cell = NULL\n");
      } else {
	printf(" 1: current_cell->buffer = '%s'\n", current_cell->buffer);
      }
  }
  return table;
}

cellmate-9.c:

...
int main(int argc, char **argv) {
  ...
  Table table = read_table();
  if (verbosity > 0) {
    printf(" 1: You read in a (%i x %i) matrix. \n", 
	   table->max_rows,
	   table->max_cols);
    printTable(table);
  }