diff --git a/lab08/Makefile b/lab08/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e604951fc9a4de27cef29e15e3da7bc5486b9f46 --- /dev/null +++ b/lab08/Makefile @@ -0,0 +1,52 @@ +cc = gcc +EXE = foo +JAVAC = javac +JRE = java +PAGER = less +TEST_OUT = test.out +EXP_OUT = expected.out + + +.PHONY: clean run-py run-c read run-java save-java test-java + +foo.o : foo.c foo.h + gcc -c foo.c + +main.o : main.c foo.h + $(cc) -c main.c + +$(EXE): foo.o main.o + $(cc) -o$(EXE) main.o foo.o + +run-c: $(EXE) + ./$(EXE) + +run-py: foo.py + ./foo.py + +read: + @if [ -f README ]; then\ + $(PAGER) README;\ + fi; \ + +foo.class: foo.java + $(JAVAC) foo.java + +run-java: foo.class + $(JRE) foo + +save-java: foo.class + $(JRE) foo > $(TEST_OUT) + +tets-java: $(TEST_OUT) $(EXP_OUT) + -if diff $(TEST_OUT) $(EXP_OUT) &> /dev/null; then\ + echo "Passed!" ;\ + else\ + echo "Not the same!" ;\ + fi + +clean: + -\rm *.o + -\rm *.class + -\rm $(EXE) + -\rm $(TEST_OUT) diff --git a/lab08/README b/lab08/README new file mode 100644 index 0000000000000000000000000000000000000000..b2d38dc1bcf3f5d8b32661738cc7ec284050f05b --- /dev/null +++ b/lab08/README @@ -0,0 +1,2 @@ + +dhouhwouhcew diff --git a/lab08/csv.c b/lab08/csv.c new file mode 100644 index 0000000000000000000000000000000000000000..dd02a07d638aaacd0ef9be8ba6b0b927a48022a5 --- /dev/null +++ b/lab08/csv.c @@ -0,0 +1,193 @@ +/* + * csv.c - Implementation for a csv library + * + * Modified from code in Kernighan & Pike, _The Practice of Programming_ + * Copyright (C) 1999 Lucent Technologies + * Excerpted from 'The Practice of Programming' + * by Brian W. Kernighan and Rob Pike + * + * Kurt Schmidt + * 3/2018 + * + * gcc 5.4.0 20160609 on + * Linux 4.13.0-32-generic + * + * EDITOR: tabstop=2 cols=120 + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "csv.h" + + +static char fieldsep[] = "," ; /* field separator chars */ + + /***** Prototypes for local helper functions ******/ +static char *advquoted( char* ) ; +static int split( csv_t* ) ; + + +csv_t* csv_init( FILE *f ) +{ + csv_t *rv = (csv_t*) malloc( sizeof( csv_t )) ; + rv->fin = f ; + reset( rv ) ; + + return( rv ) ; +} + + +void kill( csv_t* s ) +{ + reset( s ) ; + free( s ) ; +} + +/* TODO + * Copy all the functions (but for main) from csvgetline2 here. Not the prototypes. You already have them in + * csv.h. Functions that access global CSV data need to be modified, take a pointer to a CSV struct as the first + * argument, and any references need to be modified + */ + /* endofline: check for and consume \r, \n, \r\n, or EOF */ +static int endofline( FILE *fin, int c ) +{ + int eol ; + + eol = ( c=='\r' || c=='\n' ) ; + if( c=='\r' ) { + c = getc( fin ) ; + if( c!='\n' && c != EOF ) + ungetc( c, fin ) ; /* read too far; put c back */ + } + return eol ; +} + + /* reset: set variables back to starting values */ +static void reset( void ) +{ + free( line ); /* free(NULL) permitted by ANSI C */ + free( sline ) ; + free( field ) ; + line = NULL ; + sline = NULL ; + field = NULL ; + maxline = maxfield = nfield = 0 ; +} + + /* csvgetline: get one line, grow as needed */ + /* sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625 */ +char* csvgetline( FILE *fin ) +{ + int i, c ; + char *newl, *news ; + + if( line==NULL ) { /* allocate on first call */ + maxline = maxfield = 1 ; + line = (char*) malloc( maxline ) ; + sline = (char*) malloc( maxline ) ; + field = (char**) malloc( maxfield*sizeof( field[0] )) ; + if( line==NULL || sline==NULL || field==NULL) { + reset() ; + return NULL ; /* out of memory */ + } + } + + for( i=0; (c=getc( fin ))!=EOF && ! endofline(fin,c); i++ ) { + if( i>=maxline-1 ) { /* grow line */ + maxline *= 2; /* double current size */ + newl = (char*) realloc( line, maxline ) ; + if( newl==NULL ) { + reset() ; + return NULL ; + } + line = newl ; + news = (char*) realloc( sline, maxline ) ; + if( news==NULL ) { + reset() ; + return NULL ; + } + sline = news ; + } + line[i] = c ; + } /* for i */ + + line[i] = '\0' ; + if( split()==NOMEM ) { + reset() ; + return NULL; /* out of memory */ + } + return (c==EOF && i==0) ? NULL : line ; +} + +/* split: split line into fields */ +static int split( void ) +{ + char *p, **newf ; + char *sepp; /* pointer to temporary separator character */ + int sepc; /* temporary separator character */ + + nfield = 0 ; + if( line[0]=='\0' ) + return 0 ; + strcpy( sline, line ) ; + p = sline ; + + do { + if( nfield>=maxfield ) { + maxfield *= 2; /* double current size */ + newf = (char**) realloc( field, + maxfield * sizeof( field[0] )) ; + if( newf==NULL ) + return NOMEM ; + field = newf ; + } + if( *p=='"' ) + sepp = advquoted( ++p ) ; /* skip initial quote */ + else + sepp = p + strcspn( p, fieldsep ) ; + sepc = sepp[0] ; + sepp[0] = '\0' ; /* terminate field */ + field[nfield++] = p ; + p = sepp + 1 ; + } while( sepc==',' ) ; + + return nfield ; +} + + +/* advquoted: quoted field; return pointer to next separator */ +static char *advquoted( char* p ) +{ + int i, j ; + + for( i=j=0; p[j]!='\0'; ++i, ++j ) { + if( p[j]=='"' && p[++j]!='"' ) { + /* copy up to next separator or \0 */ + int k = strcspn( p+j, fieldsep ) ; + memmove( p+i, p+j, k ) ; + i += k ; + j += k ; + break ; + } + p[i] = p[j] ; + } + p[i] = '\0' ; + return p + j ; +} + +/* csvfield: return pointer to n-th field */ +char* csvfield( int n ) +{ + if( n<0 || n>=nfield ) + return NULL ; + return field[n] ; +} + +/* csvnfield: return number of fields */ +int csvnfield( void ) +{ + return nfield ; +} + diff --git a/lab08/csv.h b/lab08/csv.h new file mode 100644 index 0000000000000000000000000000000000000000..b535b73854eda57c24fadc6af2924391923aca9b --- /dev/null +++ b/lab08/csv.h @@ -0,0 +1,53 @@ +/* + * csv.h - Interface for a csv library + * + * Modified from code in Kernighan & Pike, _The Practice of Programming_ + * Copyright (C) 1999 Lucent Technologies + * Excerpted from 'The Practice of Programming' + * by Brian W. Kernighan and Rob Pike + * + * Kurt Schmidt + * 3/2018 + * + * gcc 5.4.0 20160609 on + * Linux 4.13.0-32-generic + * + * EDITOR: tabstop=2 cols=120 + */ + +#ifndef __KS_CSV_ +#define __KS_CSV_ + +#include <stdio.h> + +enum { NOMEM = 2 }; /* out of memory signal */ + +typedef struct +{ + FILE *fin ; + char *line ; /* input chars */ + char *sline ; /* line copy used by split */ + int maxline ; /* size of line[] and sline[] */ + char **field ; /* field pointers */ + int maxfield ; /* size of field[] */ + int nfield ; /* number of fields in field[] */ +} csv_t ; + + /* return a new CSV object */ +csv_t* csv_init( FILE* f ) ; + + /* read next input line */ +char* csvgetline( csv_t* c ) ; + + /* return field n */ +char* csvfield( csv_t* c, int n ) ; + + /* return number of fields */ +int csvnfield( csv_t* c ) ; + + /* To be called when done with an object * + * Does not close the file handle */ +void kill( csv_t* c ) ; + + +#endif /* __KS_CSV_ */ diff --git a/lab08/csvExample.pl b/lab08/csvExample.pl new file mode 100755 index 0000000000000000000000000000000000000000..d87beabfc1ea98c9de21a185324a00d7eadc6901 --- /dev/null +++ b/lab08/csvExample.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl +# csvExample.pl - simple example, parsing a CSV file +# +# Kurt Schmidt +# +# Mar '06 +# +# DEMONSTRATES - module Text, module Text::CSV, <>, $_, array +# + + +use strict; +use warnings; + +use Text::CSV_XS; + +my $csv = Text::CSV_XS->new(); # create a new object + +while( <> ) +{ + my $status = $csv->parse( $_ ); # parse a CSV string into fields + my @columns = $csv->fields(); # get the parsed fields + + foreach( @columns ) + { + print $_."\n"; + } + print "\n"; +} + diff --git a/lab08/csvExample.py b/lab08/csvExample.py new file mode 100755 index 0000000000000000000000000000000000000000..91f31c71d0f516145475c00709197a7491f6d0b3 --- /dev/null +++ b/lab08/csvExample.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# csvExample.py - simple example, parsing a CSV file +# +# Kurt Schmidt +# +# Oct '07 +# +# DEMONSTRATES - csv, csv.reader, sys.argv +# +# NOTES: reads stdin, or a (single) file from the command line +# + +import csv, sys + +if len( sys.argv ) < 2 : # read stdin + fh = sys.stdin +else : + try : + fh = file( sys.argv[1] ) + except IOError, e : + print "%s: Could not open %s: %s\n" % \ + ( sys.argv[0], sys.argv[1], e[1] ) + sys.exit( 1 ) + +input = csv.reader( fh ) + +for l in input : + for field in l : + print field + print + diff --git a/lab08/csvgetline.cc b/lab08/csvgetline.cc new file mode 100644 index 0000000000000000000000000000000000000000..38bcfafa45bdb19529a48cb8404ac344c20fe7a1 --- /dev/null +++ b/lab08/csvgetline.cc @@ -0,0 +1,146 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +#include <iostream> +#include <fstream> +#include <algorithm> +#include <string> +#include <vector> + +using namespace std; + +class Csv { // read and parse comma-separated values + // sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625 + + public: + Csv( istream& fin=cin, string sep = "," ) : + fin(fin), fieldsep(sep) {} + + int getline(string&); + string getfield(int n); + int getnfield() const { return nfield; } + + private: + istream& fin; // input file pointer + string line; // input line + vector<string> field; // field strings + int nfield; // number of fields + string fieldsep; // separator characters + + int split(); + int endofline(char); + int advplain(const string& line, string& fld, int); + int advquoted(const string& line, string& fld, int); +}; + +// endofline: check for and consume \r, \n, \r\n, or EOF +int Csv::endofline(char c) +{ + int eol; + + eol = (c=='\r' || c=='\n'); + if (c == '\r') { + fin.get(c); + if (!fin.eof() && c != '\n') + fin.putback(c); // read too far + } + return eol; +} + +// getline: get one line, grow as needed +int Csv::getline(string& str) +{ + char c; + + for (line = ""; fin.get(c) && !endofline(c); ) + line += c; + split(); + str = line; + return !fin.eof(); +} + +// split: split line into fields +int Csv::split() +{ + string fld; + int i, j; + + nfield = 0; + if (line.length() == 0) + return 0; + i = 0; + + do { + if (i < line.length() && line[i] == '"') + j = advquoted(line, fld, ++i); // skip quote + else + j = advplain(line, fld, i); + if (nfield >= field.size()) + field.push_back(fld); + else + field[nfield] = fld; + nfield++; + i = j + 1; + } while (j < line.length()); + + return nfield; +} + +// advquoted: quoted field; return index of next separator +int Csv::advquoted(const string& s, string& fld, int i) +{ + int j; + + fld = ""; + for (j = i; j < s.length(); j++) { + if (s[j] == '"' && s[++j] != '"') { + int k = s.find_first_of(fieldsep, j); + if (k > s.length()) // no separator found + k = s.length(); + for (k -= j; k-- > 0; ) + fld += s[j++]; + break; + } + fld += s[j]; + } + return j; +} + +// advplain: unquoted field; return index of next separator +int Csv::advplain(const string& s, string& fld, int i) +{ + int j; + + j = s.find_first_of(fieldsep, i); // look for separator + if (j > s.length()) // none found + j = s.length(); + fld = string(s, i, j-i); + return j; +} + + +// getfield: return n-th field +string Csv::getfield(int n) +{ + if (n < 0 || n >= nfield) + return ""; + else + return field[n]; +} + +// Csvtest main: test Csv class +int main(void) +{ + string line; + Csv csv; + //Csv csv2( ifstream( "harder.csv" )); + + while (csv.getline(line) != 0) { + cout << "line = `" << line <<"'\n"; + for (int i = 0; i < csv.getnfield(); i++) + cout << "field[" << i << "] = `" + << csv.getfield(i) << "'\n"; + } + return 0; +} diff --git a/lab08/csvgetline1.c b/lab08/csvgetline1.c new file mode 100644 index 0000000000000000000000000000000000000000..2a1250ae0fc2c6db8f83617fe0c78f0d971e0d11 --- /dev/null +++ b/lab08/csvgetline1.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ +/* + * EDITOR: cols=80, tabstop=2 + * + * Modified: + * DEC 2015, K Schmidt + * - pulled it all into one file (for demo purposes) + * - changed formatting a wee bit + */ + +#include <stdio.h> +#include <string.h> + +char buf[200]; /* input line buffer */ +char* field[20]; /* fields */ +char* unquote( char* ); + + /* csvgetline: read and parse line, return field count */ + /* sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625,"abc" */ +int csvgetline( FILE* fin ) +{ + int nfield ; + char *p, *q ; + + if( fgets( buf, sizeof( buf ), fin ) == NULL ) + return -1 ; + nfield = 0 ; + for( q=buf; (p=strtok( q, ",\n\r" ))!=NULL; q=NULL ) + field[nfield++] = unquote(p) ; + return nfield ; +} + + /* unquote: remove leading and trailing quote */ +char* unquote( char *p ) +{ + if( p[0] == '"' ) { + if( p[strlen(p)-1] == '"' ) + p[strlen(p)-1] = '\0' ; + p++ ; + } + return p ; +} + +int main( int argc, char* argv[] ) +{ + int i, nf ; + FILE* fp ; + + if( argc < 2 ) + fp = stdin ; + else + fp = fopen( argv[1], "r" ) ; + + while(( nf=csvgetline( fp )) != -1 ) + { + for( i=0 ; i<nf ; i++ ) + printf( "field[%d] = %s\n", i, field[i] ) ; + printf( "\n" ) ; + } + + return 0 ; +} + diff --git a/lab08/csvgetline1.c.lnk b/lab08/csvgetline1.c.lnk new file mode 100644 index 0000000000000000000000000000000000000000..2a1250ae0fc2c6db8f83617fe0c78f0d971e0d11 --- /dev/null +++ b/lab08/csvgetline1.c.lnk @@ -0,0 +1,65 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ +/* + * EDITOR: cols=80, tabstop=2 + * + * Modified: + * DEC 2015, K Schmidt + * - pulled it all into one file (for demo purposes) + * - changed formatting a wee bit + */ + +#include <stdio.h> +#include <string.h> + +char buf[200]; /* input line buffer */ +char* field[20]; /* fields */ +char* unquote( char* ); + + /* csvgetline: read and parse line, return field count */ + /* sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625,"abc" */ +int csvgetline( FILE* fin ) +{ + int nfield ; + char *p, *q ; + + if( fgets( buf, sizeof( buf ), fin ) == NULL ) + return -1 ; + nfield = 0 ; + for( q=buf; (p=strtok( q, ",\n\r" ))!=NULL; q=NULL ) + field[nfield++] = unquote(p) ; + return nfield ; +} + + /* unquote: remove leading and trailing quote */ +char* unquote( char *p ) +{ + if( p[0] == '"' ) { + if( p[strlen(p)-1] == '"' ) + p[strlen(p)-1] = '\0' ; + p++ ; + } + return p ; +} + +int main( int argc, char* argv[] ) +{ + int i, nf ; + FILE* fp ; + + if( argc < 2 ) + fp = stdin ; + else + fp = fopen( argv[1], "r" ) ; + + while(( nf=csvgetline( fp )) != -1 ) + { + for( i=0 ; i<nf ; i++ ) + printf( "field[%d] = %s\n", i, field[i] ) ; + printf( "\n" ) ; + } + + return 0 ; +} + diff --git a/lab08/csvgetline2.c b/lab08/csvgetline2.c new file mode 100644 index 0000000000000000000000000000000000000000..8e377fa2d4216fe1ab2efd0a2cb07407c350bc39 --- /dev/null +++ b/lab08/csvgetline2.c @@ -0,0 +1,186 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ +/* + * EDITOR: cols=80, tabstop=2 + * + * Change History: + * DEC 2015, K Schmidt + * - Pulled it all into one file (for demos) + * - Changed formatting a wee bit + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +enum { NOMEM = -2 }; /* out of memory signal */ + +static char *line = NULL ; /* input chars */ +static char *sline = NULL ; /* line copy used by split */ +static int maxline = 0 ; /* size of line[] and sline[] */ +static char **field = NULL ; /* field pointers */ +static int maxfield = 0 ; /* size of field[] */ +static int nfield = 0 ; /* number of fields in field[] */ + +static char fieldsep[] = "," ; /* field separator chars */ + +static char* advquoted( char* ) ; +static int split( void ) ; + + /* endofline: check for and consume \r, \n, \r\n, or EOF */ +static int endofline( FILE *fin, int c ) +{ + int eol ; + + eol = ( c=='\r' || c=='\n' ) ; + if( c=='\r' ) { + c = getc( fin ) ; + if( c!='\n' && c != EOF ) + ungetc( c, fin ) ; /* read too far; put c back */ + } + return eol ; +} + + /* reset: set variables back to starting values */ +static void reset( void ) +{ + free( line ); /* free(NULL) permitted by ANSI C */ + free( sline ) ; + free( field ) ; + line = NULL ; + sline = NULL ; + field = NULL ; + maxline = maxfield = nfield = 0 ; +} + + /* csvgetline: get one line, grow as needed */ + /* sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625 */ +char* csvgetline( FILE *fin ) +{ + int i, c ; + char *newl, *news ; + + if( line==NULL ) { /* allocate on first call */ + maxline = maxfield = 1 ; + line = (char*) malloc( maxline ) ; + sline = (char*) malloc( maxline ) ; + field = (char**) malloc( maxfield*sizeof( field[0] )) ; + if( line==NULL || sline==NULL || field==NULL) { + reset() ; + return NULL ; /* out of memory */ + } + } + + for( i=0; (c=getc( fin ))!=EOF && ! endofline(fin,c); i++ ) { + if( i>=maxline-1 ) { /* grow line */ + maxline *= 2; /* double current size */ + newl = (char*) realloc( line, maxline ) ; + if( newl==NULL ) { + reset() ; + return NULL ; + } + line = newl ; + news = (char*) realloc( sline, maxline ) ; + if( news==NULL ) { + reset() ; + return NULL ; + } + sline = news ; + } + line[i] = c ; + } /* for i */ + + line[i] = '\0' ; + if( split()==NOMEM ) { + reset() ; + return NULL; /* out of memory */ + } + return (c==EOF && i==0) ? NULL : line ; +} + +/* split: split line into fields */ +static int split( void ) +{ + char *p, **newf ; + char *sepp; /* pointer to temporary separator character */ + int sepc; /* temporary separator character */ + + nfield = 0 ; + if( line[0]=='\0' ) + return 0 ; + strcpy( sline, line ) ; + p = sline ; + + do { + if( nfield>=maxfield ) { + maxfield *= 2; /* double current size */ + newf = (char**) realloc( field, + maxfield * sizeof( field[0] )) ; + if( newf==NULL ) + return NOMEM ; + field = newf ; + } + if( *p=='"' ) + sepp = advquoted( ++p ) ; /* skip initial quote */ + else + sepp = p + strcspn( p, fieldsep ) ; + sepc = sepp[0] ; + sepp[0] = '\0' ; /* terminate field */ + field[nfield++] = p ; + p = sepp + 1 ; + } while( sepc==',' ) ; + + return nfield ; +} + +/* advquoted: quoted field; return pointer to next separator */ +static char *advquoted( char* p ) +{ + int i, j ; + + for( i=j=0; p[j]!='\0'; ++i, ++j ) { + if( p[j]=='"' && p[++j]!='"' ) { + /* copy up to next separator or \0 */ + int k = strcspn( p+j, fieldsep ) ; + memmove( p+i, p+j, k ) ; + i += k ; + j += k ; + break ; + } + p[i] = p[j] ; + } + p[i] = '\0' ; + return p + j ; +} + +/* csvfield: return pointer to n-th field */ +char* csvfield( int n ) +{ + if( n<0 || n>=nfield ) + return NULL ; + return field[n] ; +} + +/* csvnfield: return number of fields */ +int csvnfield( void ) +{ + return nfield ; +} + +/* csvtest main: test CSV library */ +int main( void ) +{ + int i ; + char *line ; + + while( (line=csvgetline(stdin)) != NULL ) { + printf( "line = %s\n", line ) ; + for( i=0; i<csvnfield(); i++ ) + printf( "field[%d] = %s\n", i, csvfield( i )) ; + printf( "\n" ) ; + } + return 0 ; +} + diff --git a/lab08/csvgetline2.c.lnk b/lab08/csvgetline2.c.lnk new file mode 100644 index 0000000000000000000000000000000000000000..8e377fa2d4216fe1ab2efd0a2cb07407c350bc39 --- /dev/null +++ b/lab08/csvgetline2.c.lnk @@ -0,0 +1,186 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ +/* + * EDITOR: cols=80, tabstop=2 + * + * Change History: + * DEC 2015, K Schmidt + * - Pulled it all into one file (for demos) + * - Changed formatting a wee bit + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +enum { NOMEM = -2 }; /* out of memory signal */ + +static char *line = NULL ; /* input chars */ +static char *sline = NULL ; /* line copy used by split */ +static int maxline = 0 ; /* size of line[] and sline[] */ +static char **field = NULL ; /* field pointers */ +static int maxfield = 0 ; /* size of field[] */ +static int nfield = 0 ; /* number of fields in field[] */ + +static char fieldsep[] = "," ; /* field separator chars */ + +static char* advquoted( char* ) ; +static int split( void ) ; + + /* endofline: check for and consume \r, \n, \r\n, or EOF */ +static int endofline( FILE *fin, int c ) +{ + int eol ; + + eol = ( c=='\r' || c=='\n' ) ; + if( c=='\r' ) { + c = getc( fin ) ; + if( c!='\n' && c != EOF ) + ungetc( c, fin ) ; /* read too far; put c back */ + } + return eol ; +} + + /* reset: set variables back to starting values */ +static void reset( void ) +{ + free( line ); /* free(NULL) permitted by ANSI C */ + free( sline ) ; + free( field ) ; + line = NULL ; + sline = NULL ; + field = NULL ; + maxline = maxfield = nfield = 0 ; +} + + /* csvgetline: get one line, grow as needed */ + /* sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625 */ +char* csvgetline( FILE *fin ) +{ + int i, c ; + char *newl, *news ; + + if( line==NULL ) { /* allocate on first call */ + maxline = maxfield = 1 ; + line = (char*) malloc( maxline ) ; + sline = (char*) malloc( maxline ) ; + field = (char**) malloc( maxfield*sizeof( field[0] )) ; + if( line==NULL || sline==NULL || field==NULL) { + reset() ; + return NULL ; /* out of memory */ + } + } + + for( i=0; (c=getc( fin ))!=EOF && ! endofline(fin,c); i++ ) { + if( i>=maxline-1 ) { /* grow line */ + maxline *= 2; /* double current size */ + newl = (char*) realloc( line, maxline ) ; + if( newl==NULL ) { + reset() ; + return NULL ; + } + line = newl ; + news = (char*) realloc( sline, maxline ) ; + if( news==NULL ) { + reset() ; + return NULL ; + } + sline = news ; + } + line[i] = c ; + } /* for i */ + + line[i] = '\0' ; + if( split()==NOMEM ) { + reset() ; + return NULL; /* out of memory */ + } + return (c==EOF && i==0) ? NULL : line ; +} + +/* split: split line into fields */ +static int split( void ) +{ + char *p, **newf ; + char *sepp; /* pointer to temporary separator character */ + int sepc; /* temporary separator character */ + + nfield = 0 ; + if( line[0]=='\0' ) + return 0 ; + strcpy( sline, line ) ; + p = sline ; + + do { + if( nfield>=maxfield ) { + maxfield *= 2; /* double current size */ + newf = (char**) realloc( field, + maxfield * sizeof( field[0] )) ; + if( newf==NULL ) + return NOMEM ; + field = newf ; + } + if( *p=='"' ) + sepp = advquoted( ++p ) ; /* skip initial quote */ + else + sepp = p + strcspn( p, fieldsep ) ; + sepc = sepp[0] ; + sepp[0] = '\0' ; /* terminate field */ + field[nfield++] = p ; + p = sepp + 1 ; + } while( sepc==',' ) ; + + return nfield ; +} + +/* advquoted: quoted field; return pointer to next separator */ +static char *advquoted( char* p ) +{ + int i, j ; + + for( i=j=0; p[j]!='\0'; ++i, ++j ) { + if( p[j]=='"' && p[++j]!='"' ) { + /* copy up to next separator or \0 */ + int k = strcspn( p+j, fieldsep ) ; + memmove( p+i, p+j, k ) ; + i += k ; + j += k ; + break ; + } + p[i] = p[j] ; + } + p[i] = '\0' ; + return p + j ; +} + +/* csvfield: return pointer to n-th field */ +char* csvfield( int n ) +{ + if( n<0 || n>=nfield ) + return NULL ; + return field[n] ; +} + +/* csvnfield: return number of fields */ +int csvnfield( void ) +{ + return nfield ; +} + +/* csvtest main: test CSV library */ +int main( void ) +{ + int i ; + char *line ; + + while( (line=csvgetline(stdin)) != NULL ) { + printf( "line = %s\n", line ) ; + for( i=0; i<csvnfield(); i++ ) + printf( "field[%d] = %s\n", i, csvfield( i )) ; + printf( "\n" ) ; + } + return 0 ; +} + diff --git a/lab08/csvmain.c b/lab08/csvmain.c new file mode 100644 index 0000000000000000000000000000000000000000..9b26693f9b1ae652f0184f92e4e8ffe53d93c066 --- /dev/null +++ b/lab08/csvmain.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +#include "csv.h" + +/* csvtest main: test CSV library */ +int main(void) +{ + int i; + char *line; + + while ((line = csvgetline(stdin)) != NULL) { + printf("line = `%s'\n", line); + for (i = 0; i < csvnfield(); i++) + printf("field[%d] = `%s'\n", i, csvfield(i)); + } + return 0; +} diff --git a/lab08/expected.out b/lab08/expected.out new file mode 100644 index 0000000000000000000000000000000000000000..a710eaf6d01254a5da9cc9ca9a8cd5e11d8c206c --- /dev/null +++ b/lab08/expected.out @@ -0,0 +1,19 @@ +10 -12 +15 -9 +20 -7 +25 -4 +30 -1 +35 2 +40 4 +45 7 +50 10 +55 13 +60 16 +65 18 +70 21 +75 24 +80 27 +85 29 +90 32 +95 35 +100 38 diff --git a/lab08/foo b/lab08/foo new file mode 100755 index 0000000000000000000000000000000000000000..4d44934dd208d527f315e92c30ca2d8dda35d034 Binary files /dev/null and b/lab08/foo differ diff --git a/lab08/foo.c b/lab08/foo.c new file mode 100644 index 0000000000000000000000000000000000000000..969d1abc47c000ee97c8929ae023f4cbeddfc995 --- /dev/null +++ b/lab08/foo.c @@ -0,0 +1,15 @@ +/* foo.c - implementation of functions, definition of global vars + * + * CS265/571 + * + */ + +#include <stdio.h> + +char *myEnvVar = "FOO_ENV"; + +void wallOfVoodoo( char *s ) +{ + printf( "FOO> And the penquin yelled, \"%s\"\n", s ); +} + diff --git a/lab08/foo.h b/lab08/foo.h new file mode 100644 index 0000000000000000000000000000000000000000..525d6200d36ca24952568757a9e4fa0ec924d718 --- /dev/null +++ b/lab08/foo.h @@ -0,0 +1,10 @@ +/* foo.h - header file for functions found in bar + * + * CS265/571 + * + */ + +extern char *myEnvVar; + +void wallOfVoodoo( char* ); + diff --git a/lab08/foo.java b/lab08/foo.java new file mode 100644 index 0000000000000000000000000000000000000000..e4e78088506d03b5c2742700631673cb78d53691 --- /dev/null +++ b/lab08/foo.java @@ -0,0 +1,38 @@ +// foo.java - simple example program +// +// Kurt Schmidt +// 4/08 +// +// javac 1.6.0, on +// Linux 2.6.20-cs-acl.nfsgroups.perfctr i686 GNU/Linux +// + +import java.io.* ; + +/** + * A "hello world"-type program + * + * @author Kurt Schmidt + */ + +public class foo +{ + // a single space + static private final String _field_sep = " "; + + static public void main( String [] argv ) + { + //System.out.println( _msg ); + + // print a conversion table, Fahrenheit to Centigrade + int f, c ; + double a ; + for( f=10; f<=100; f+=5 ) + { + a = (double)( f-32 ) / 9 * 5 ; + c = (int) Math.round( a ); + System.out.println( "" + f + _field_sep + c ) ; + } + } +} + diff --git a/lab08/foo.o b/lab08/foo.o new file mode 100644 index 0000000000000000000000000000000000000000..c702435cb22b527a68db96f25d00b835d692c33f Binary files /dev/null and b/lab08/foo.o differ diff --git a/lab08/foo.py b/lab08/foo.py new file mode 100644 index 0000000000000000000000000000000000000000..c1636b3b61abe6ca9462d87cf3c25e637db01232 --- /dev/null +++ b/lab08/foo.py @@ -0,0 +1,6 @@ +#!/usr/bin/python + +print "This is the foo in Python." +print "Say *that* 5 times, in rapid succession." +print "" + diff --git a/lab08/lab8 b/lab08/lab8 new file mode 100644 index 0000000000000000000000000000000000000000..3b6dafbe8439b6a640e0cba9857800ec5f790ab9 --- /dev/null +++ b/lab08/lab8 @@ -0,0 +1,41 @@ +Q1: +i. means having functions that have comments telling the client what it is used for, not how it achieves that, Using classes with literal-naming methods. Avoid using global variables + +ii. it means not using a lot of function to achieve the same thing, minizing the number of function declared but have to make sure that there are enough function to do everything needed + +iii. It means the functions declared should exactly as its name and comments that goes with it (if applicable). Try to have less side effects as possible, and explicitly comment those things to let the user know. + +iv. Be consistent with programing style: name of arguments/variables are similar, convention of naming function as well as structure of loops should be consistent, use idiomatic expression (ex: isBigger(), isClassX(), isSomthingElse() rather than isBigger(), be_ClassX(), etc.) + + +Q2: +Problems were: +- The program is assuming each line is not more than 199 characters +- The program is assuming each line is not more than 20 fields +- Records are separated by newline --> does not recognize line with nothing on it but thought it is end of file +- Field separator is a comma --> does not recognize commas inside a field +- Does not allow embedded quotes + +Q3: +Improvement: +- Can now handle more than 199 characters +- Can now handle more than 20 fields +- Recognize commas in a field (if wrapped by quotes) and recognize embedded quotes + +Q4: +- It still cannot recognize lines with nothing on it +You cannot parse 2 CSV file at the same time because of the static variables as these can appear as only one instance at a time so there is not enough variables for the task. + +Q5: +The program can now recognize emty line: '', and can parsemore than 1 file + +Q6: +The interface is good +i. It does not require the user to know about the implementation, just need to use the provided methods +ii. It just provide enough methods with no overlapping functionality between them +iii. Does what it said, without +iv. the program have consistency in its variable and fucntion naming + + +Q7: + diff --git a/lab08/main.c b/lab08/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7be41674ba85f041f7c23689ebaa4d8398a2e734 --- /dev/null +++ b/lab08/main.c @@ -0,0 +1,48 @@ +/* + * main.c - Driver for the csv library + * + * Modified from code in Kernighan & Pike, _The Practice of Programming_ + * Copyright (C) 1999 Lucent Technologies + * Excerpted from 'The Practice of Programming' + * by Brian W. Kernighan and Rob Pike + * + * Kurt Schmidt + * 3/2018 + * + * gcc 5.4.0 20160609 on + * Linux 4.13.0-32-generic + * + * EDITOR: tabstop=2 cols=120 + */ + +#include <stdio.h> +#include <stdlib.h> +#include "csv.h" + + +int main( int argc, char** argv ) +{ + int i ; + char *line ; + FILE *f = NULL ; + csv_t *c1 = NULL ; + + if( argc==1 ) + f = stdin ; + else + f = fopen( argv[1], "r" ) ; + + c1 = csv_init( f ) ; + + while( (line=csvgetline( c1 )) != NULL ) + { + printf( "line: %s\n", line ) ; + for( i=0; i < csvnfield(c1); i++ ) + printf( " field[%d]: %s\n", i, csvfield( c1, i )) ; + } + + kill( c1 ) ; + + return 0; +} + diff --git a/lab08/main.o b/lab08/main.o new file mode 100644 index 0000000000000000000000000000000000000000..38c8cd64754948e0e951bb8764518e531af40ee9 Binary files /dev/null and b/lab08/main.o differ diff --git a/lab08/makefile b/lab08/makefile new file mode 100644 index 0000000000000000000000000000000000000000..34d1d985267835673dd742b184c8fc48836ebf0b --- /dev/null +++ b/lab08/makefile @@ -0,0 +1,19 @@ +cc = gcc +flags = + +csv : main.o csv.o + $(cc) $(flags) main.o csv.o -o $@ + +main.o : main.c csv.h + $(cc) -c $(flags) main.c + +csv.o : csv.c csv.h + $(cc) -c $(flags) csv.c + +.PHONY : clean cleanall + +clean : + -\rm *.o + +cleanall : clean + -\rm csv