
Big S.
asked 11/26/20program implements a simplistic version of the Linux cut command
Assignment 2.
Note: See assign2Updates.txt for changes, updates and/or clarifications
to this assignment. Check regularly before submitting to make sure you
haven't missed anything.
Part 0. Completing your Iam.txt file and Groups
-----------------------------------------------
Copy Iam.txt to your own space and complete it by replacing "XXXXXXX" with
YOUR appropriate information.
You may do the assignment alone, or in groups of 2 or 3 students. Your
group may comprise members from different CPS393 sections/classes.
IF you are part of a group, designate a "submit person" and that student
will be THE ONLY ONE to submit the other files. If you work alone, YOU
are the submit person.
Every student submits her/his OWN Iam.txt file, whether working alone
or in a group.
Part 1. assign2.c
------------------
Write a C program in 3 files as follows:
assign2.c -main function
assign2funcs.c -functions used by main
assign2funcs.h -prototypes for functions defined in assign2funcs.c
Your program implements a simplistic version of the Linux cut command.
It is "simplistic" in that:
-it only cuts FIELDS (not characters, bytes, etc).
-it requires between 1 and 100 fields (inclusive)
-it requires fields to be unique, and specified in increasing order
-it does not implement any functionality of cut other than cutting
fields with given input delimiter and output delimiter
-the format of its command line arguments are simpler than cut's
DO NOT call the cut command itself, nor any other Linux command from
your code (e.g., with a system call). Any such calls result in zero on
the assignment.
Your program expects command line arguments (CLAs) specifying the
following, in this order:
-input delimiter (a single character)
-output delimiter (a single character)
-field(s) (at least one, and at most 100, unique positive integers,
given in increasing order of size)
Examples of proper calls to your program:
> a.out , . 2 4 5 6 9 <inputFile
> a.out , , 3 <inputFile
> a.out x y 1 4 32 33 37 42 57 77 86 204 337 <inputFile
Examples of improper calls:
> a.out ,, . 2 4 5 6 9 <inputFile #wrong input delimiter
> a.out , . 2 4-6 9 <inputFile #wrong field(s)
> a.out , '.' 2 4 <inputFile #wrong output delimiter
> a.out <inputFile #CLAs missing
> a.out , . 4 4 5 6 9 <inputFile #wrong field(s)
> a.out , . 4 2 5 <inputFile #wrong field(s)
If CLAs are not as required above, print the following message on
stderr and exit with exit code 1:
a.out: specify input_delimiter output_delimiter and 1-100 fields in order
Note that in the above error message, the following are NOT hard-coded,
but are obtained from appropriate arguments: "a.out", "100". Also,
"a.out" must be obtained from argv[0] and "100" must be from a
#define preprocessor directive.
If the program run does not result in error, exit with exit code 0.
Your program reads input from stdin only, with fields separated by a
single input delimiter. e.g., the following file contains 3 lines,
where line 1 has 4 fields, line 2 has 2 fields, and line 3 has 6
fields (with input delimiter ","):
abc,de,f,ghi
a b,cd
a,,cdefg,hi jkl, m ,
Your program writes output to stdout (and error message to stderr).
For each line of input, your program displays the required fields
on stdout using the output delimiter to separate fields.
e.g., if the above input file was named "thefile", then the following
run of your program produces the following output:
> ./a.out , , 1 3 <thefile
abc,f
a b
a,cdefg
>
Part 2. assign2funcs.[ch]
-------------------------
Your main function must be in assign2.c. You must write & use
appropriate additional functions, with their declarations and
definitions in files assign2funcs.h and assign2funcs.c,
respectively. The TAs will compile your program as follows:
> gcc assign2.c assign2funcs.c
Part 3. Testing Your Program:
----------------------------
Your program must produce the same output as the Linux cut command
does for "the same" input. E.g., the following two must produce
identical output (files "actual" and "expected" must be identical):
>a.out , . 16 17 25 <input >actual
>cut -d, --output-delimiter=. -f16,17,25 <input >expected
The Linux "diff" command can verify actual and expected are identical.
I.e., the following should produce no output:
>diff actual expected
A simple testing shell program named "testit" is included in this
directory, along with input file "input", which is used by testit.
When a.out is a correct program, testit outputs:
all tests successful
If, for example, test 4 fails, then testit outputs:
FAILED test 4
NOTE: The tests in testit are examples of a few very basic tests.
Do not rely upon ONLY those tests. The TAs will test your program
much more thoroughly. "testit" was supplied simply to help you
test your code. You do NOT submit any testing program(s).
Part 4. Marking:
---------------
The TAs will grade your assignment according to the following scheme.
You may get a zero on the assignment for any reason mentioned in this
document, including, but not limited to:
-Iam.txt file not submitted (every student submits this file)
-a file is missing (not submitted)
-a file is named incorrectly
-your code calls a Linux command (e.g., a system call)
-a file submitted late
Out of 17 marks total, as follows:
----------------------------------
17 Correct output for TA tests (i.e., same as cut's)
The following mark reductions are possible. Maximum deductions
in each category are as follows:
-02 Style; Efficiency; Documentation (see
/usr/courses/cps393/dwoit/labs/doc.txt)
-02 CLA processing
-02 error message and exit codes
-03 processing of stdin input
-02 division into files
-03 appropriate design/use of functions
-03 a good attempt which compiles and runs
Note that your program may produce the same output as cut, but
may obtain a mark of 0/17 because of mark reductions for not
following instructions, as above.
Your TAs may ask you to answer questions about your assignment in a
one-on-one zoom session. In addition, they may ask you to write code
during the session in order to demonstrate that you completely
understand your solution. If the TA is not satisfied with your
code/explanations, your mark can be reduced all the way down to zero.
1 Expert Answer

Patrick B. answered 11/26/20
Math and computer tutor/teacher
//cut.h
#ifndef _CUT
typedef struct _TCutParams
{
char inputDelim;
char outputDelim;
int * fieldNums;
int fieldCount;
} * TCutParams;
#define CUT_PARAMS_SIZE (sizeof(struct _TCutParams))
typedef struct _Tokens
{
int numTokens;
char tokens[256][256];
} * Tokens;
#define TOKENS_SIZE (sizeof(struct _Tokens))
int Go(int argc, char ** argv);
int validateCommandLineArgs(int argc, char ** argv, TCutParams cutParams);
int _strtok(char * inbuff,char delim, Tokens);
#endif
//cut.c
#ifndef _CUT
#include "cut.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void LOG_ERROR(char * strErrMsg)
{
fprintf(stderr,strErrMsg);
printf(strErrMsg);
printf("---------------------\n");
printf(" USAGE: at the command prompt... \n");
printf(" assign2 single-char-input-delimieter single-char-output-delimieter field#1 field#2 .... \n");
printf("--------------------------------------------------\n");
printf(" at least one field # is REQUIRED! Limit of 100 field numbers \n");
printf(" field numbers must be sorted \n");
printf("--------------------------------------------------------------\n");
printf(" Ex. assign2 , , 3 5 6 7 \n");
}
int Go( int argc, char ** argv)
{
struct _TCutParams cutParams;
struct _Tokens Tokens;
int iReturn;
char inbuff[256];
iReturn = validateCommandLineArgs(argc,argv,&cutParams);
if (iReturn==0)
{
//** debug: dumps the params
printf("input delim %c \n",cutParams.inputDelim);
printf("output delim %c \n",cutParams.outputDelim);
printf(" # of fields : %d \n",cutParams.fieldCount);
int N=cutParams.fieldCount;
for (int iLoop=0; iLoop<N; iLoop++)
{
printf("%d \n",cutParams.fieldNums[iLoop]);
}
while (true)
{
if (fgets(inbuff,256,stdin)==NULL) { break; }
_strtok(inbuff,cutParams.inputDelim,&Tokens);
for (int iLoop=0; iLoop<cutParams.fieldCount; iLoop++)
{
if (cutParams.fieldNums[iLoop]<Tokens.numTokens)
{
int iIndexPos = cutParams.fieldNums[iLoop]-1;
printf("%s%c\n",Tokens.tokens[iIndexPos],cutParams.outputDelim);
}
}
}
}
return(iReturn);
}
//strtok in string.h has known issues and chokes on empty tokens caused by double delimiters: Ex. one,two,,four,five,,seven
// tokens #3 and 6 should be empty with string length zer0
int _strtok( char * inbuff, char chDelim, Tokens _tokens)
{
char * beginToken = inbuff;
char * endToken = beginToken;
_tokens->numTokens=0;
for (int iLoop=0; iLoop<256; iLoop++)
{
while (
((*endToken)!=chDelim) && ((*endToken)!=0)
)
{
endToken++;
}
int N = endToken-beginToken;
//printf(" token size= %d\n",N);
memset(&_tokens->tokens[iLoop],0,256);
memcpy(&_tokens->tokens[iLoop],beginToken,N);
//printf("%s \n",_tokens->tokens[iLoop]) ;
_tokens->numTokens++;
if ((*endToken)==0)
{
break;
}
beginToken=endToken+1;
endToken=beginToken;
} //for
}
int validateCommandLineArgs(int argc, char ** argv, TCutParams cutParams)
{
int iReturn=0;
if ((argc<3) || (argc>103) )
{
iReturn=1;
cutParams->fieldCount=0;
cutParams->fieldNums=NULL;
LOG_ERROR((char*)"invlid # of command line args \n");
}
else
{
if (
(strlen(argv[1])!=1) || (strlen(argv[2])!=1)
)
{
iReturn=1;
LOG_ERROR((char*)"invalid delimiters\n");
}
cutParams->inputDelim = argv[1][0];
cutParams->outputDelim = argv[2][0];
int iFieldNum=0;
int N=cutParams->fieldCount = argc-3;
cutParams->fieldNums = (int *) malloc(N*sizeof(int));
for (int iLoop=0; iLoop<N; iLoop++)
{
int curFieldNum = atoi(argv[iLoop+3]);
if (curFieldNum<=iFieldNum)
{
iReturn=1;
LOG_ERROR((char*)"field # out of sequence\n");
free(cutParams->fieldNums);
break;
}
cutParams->fieldNums[iLoop]=curFieldNum;
iFieldNum = curFieldNum;
}
}
return(iReturn);
}
//main
//using namespace std;
//#include <iostream>
#ifndef _CUT
#include "cut.h"
#endif
int main(int argc, char** argv)
{
return (Go(argc,argv));
return 0;
}
/********************************************
test main: tests _strtok
int main()
{
char inbuff[] = {"The,quick,brown,,jumped,over,the,lazy,dogs"};
struct _Tokens tokens;
_strtok(inbuff,',',&tokens);
cout << tokens.numTokens << endl;
for (int iLoop=0; iLoop<tokens.numTokens; iLoop++)
{
cout << tokens.tokens[iLoop] << endl;
}
}
***********************************/
//input file
The, quick, brown
fox, jumped, over
the, lazy, dogs
Roxy N.
can you format the code better pls? Like show which code goes in which file11/30/20
Still looking for help? Get the right answer, fast.
Get a free answer to a quick problem.
Most questions answered within 4 hours.
OR
Choose an expert and meet online. No packages or subscriptions, pay only for the time you need.
Patrick B.
this source code uploaded to RESOURCES section11/26/20