#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLIST 1024
#define MAXLINE 1024
static int getline(char *s, int lim, FILE *fp);
static char *stringcopy(char *dest, char *source, int n);
static char* getword(char *s, const char *sep);
int cut(int argc, char *argv[])
{
FILE *fp;
char c, delim[] = "\t";
int field = 0, character = 0;
char line[MAXLINE], *charpos = NULL, *fieldpos = NULL;
/* parse the optional arguments */
while(--argc && (*++argv)[0] == '-')
{
c = *++argv[0];
switch(c)
{
case 'c':
if(field) /* -f option already given in command line */
{
printf("cut: providing both options -c and -f is illegal usage\n");
argc = 0;
break;
}
character = 1;
charpos = &*++argv[0];
break;
case 'f':
if(character) /* -c option already given in command line */
{
printf("cut: providing both options -c and -f is illegal usage\n");
argc = 0;
break;
}
field = 1;
fieldpos = &*++argv[0];
break;
case 'd':
if(character)
{
printf("cut: -d option can only be provided with -f option\n");
argc = 0;
break;
}
if(!field)
{
printf("cut: -d option can only be provided with -f option\n");
argc = 0;
break;
}
delim[0] = *++argv[0];
break;
default:
printf("cut: illegal option %c\n", c);
argc = 0;
break;
}
}
if(argc != 1 || (!field && !character))
{
printf("(Usage: cut -clist [file ...] or cut -flist [-dchar] [file ...].\n");
return 1;
}
/* open file in read mode*/
if((fp = fopen(*argv, "r")) == NULL)
{
printf("cut: cannot open file %s\n", *argv);
return 1;
}
if(field) /* -f option is given */
{
/* read line from input file */
while(getline(line, sizeof(line), fp))
{
char copy[MAXLIST], *pos, *word;
int wordpos;
/* copy field options in seperate memory */
stringcopy(copy, fieldpos, sizeof(copy));
/* cut line according to the field options given */
for(pos = strtok(copy, ","), word = getword(line, (const char*)delim), wordpos = 1; pos; pos = strtok(NULL, ",")) /* get the field value by tokenizing the copied string */
{
int k;
if((k = atoi(pos)) < 1) /* get the field pos. field position should be greater then 0 */
continue;
/* find the word in line at position given by j */
for(; wordpos < k; wordpos++)
word = getword(NULL, (const char*)delim);
fprintf(stdout, "%s ", word);
}
fprintf(stdout, "\n");
}
}
else /* -c option is given */
{
/* read line from input file */
while(getline(line, sizeof(line), fp))
{
char copy[MAXLIST], *pos, *linepos = &line[0];
/* copy field options in seperate memory */
stringcopy(copy, charpos, sizeof(copy));
for(pos = strtok(copy, ","); pos; pos = strtok(NULL, ",")) /* get character range by tokenizing the copied string */
{
char *dashpos;
/* check if it is a range or a single character */
for(dashpos = pos; *dashpos != '\0' && *dashpos != '-'; dashpos++);
if(*dashpos == '-') /* it is a character range */
{
int start_char_pos, end_char_pos;
char *start_char_p, *end_char_p;
if((start_char_pos = atoi(pos)) < 1)
continue;
if((end_char_pos = atoi(++dashpos)) < 1)
continue;
/* bring linepos to start */
for(start_char_p = &line[start_char_pos-1]; *linepos != '\n' && linepos < start_char_p; linepos++);
if(*linepos == '\n')
continue;
/* print the character range */
for(end_char_p = &line[end_char_pos-1]; *linepos != '\n' && linepos <= end_char_p; linepos++)
fprintf(stdout, "%c", *linepos);
}
else /* it is a character pos */
{
int cur_char_pos;
char *cur_pos_p;
if((cur_char_pos = atoi(pos)) < 1)
continue;
for(cur_pos_p = &line[cur_char_pos-1]; *linepos != '\n' && linepos < cur_pos_p; linepos++);
if(*linepos != '\n')
fprintf(stdout, "%c", *linepos);
}
}
fprintf(stdout, "\n");
}
}
return 0;
}
static int getline(char *s, int lim, FILE *fp)
{
int i;
char c;
for(i = 0; i < (lim-1) && (c = getc(fp)) != EOF && c != '\n'; i++)
s[i] = c;
if(c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
static char *stringcopy(char *dest, char *source, int n)
{
int i;
for(i = 0; (i < (n-1)) && ((dest[i] = source[i]) != '\0'); i++);
dest[i] = '\0';
return dest;
}
static char* getword(char *s, const char *sep)
{
char *p, *tokenptr;
/* static pointer pointing to the current position in s */
static char *currentp = NULL;
/* if s is not NULL, point currentp to starting of NULL */
if(s != NULL)
currentp = s;
/* when the function is called for the first time and s is NULL, return NULL */
if(s == NULL && currentp == NULL)
return NULL;
/* bypass the initial seperator characters */
for(p = currentp; *p != '\0'; p++)
{
const char *sep_p;
/* check if the character is seperator */
for(sep_p = sep; *sep_p != '\0'; sep_p++)
{
if(*sep_p == *p)
break;
}
if(*sep_p == '\0')
break; /* if character other then separator is found, break out of the loop */
}
/* end of string is reached */
if(*p == '\0')
{
currentp = NULL;
return NULL;
}
/* find the next seperator character */
for(tokenptr = p; *p != '\0'; p++)
{
const char *sep_p;
for(sep_p = sep; *sep_p != '\0'; sep_p++)
{
if(*sep_p == *p)
break;
}
if(*sep_p != '\0')
break; /* if the character is separator then break out of loop */
}
if(*p == '\0')
currentp = p;
else
{
currentp = p+1;
*p = '\0';
}
return tokenptr;
}