So i have an assignment to due for my UNIX class were I need to implement these features to a program I already made which was suppose to read and write a file given by the user: ( I also need to put the functions for this in a seperate file. My main concern is being able to understand how to do this because as of right now I am having trouble understanding all of this exactly
• The ability to specify a command line parameter (-b x ) to change the size of the buffer use with read and write to x.
• The ability to specify a command line parameter (-n x ) to change the number of bytes read from each file to ex. (Instead of reading the entire file.)
• The ability to specify a command line parameter (-c x ) to change the shift to x when applying a simple Caesar cipher to text within the file (described below).
• The ability to specify a command line parameter (-r x ) to specify the shift to x when applying a similar rotation to binary data within the file.
• The ability to specify a command line parameter (-x ) to output the data in the file as hexadecimal numbers.
Personally I would start at the beginning of main by parsing out the commands that you need.
So you can use strcmp(argv[i], "-b") from the cstring library so in a while loop you can compare arg[i] against an expected commands, and then arg[i + 1] will be the value, right?
After that just tackle each command one at a time.
I think using getopt and using switch statements would be easier but what type of functions would I make for the arguments and what would i pass in is my main concern. UNIX coding is very confusing to me
Using getopt as your parser is fine (and probably what your teacher expects/wants), that doesn't change that you need a while loop to parse out those commands.
It's actually basic C/C++ coding after that. You make modifications to a function by passing inputs. The key difference is that you are getting your inputs from the user using getopt() instead of cin/cout. What I thought was really throwing you is that the user is choosing what question they are answering and when instead of you choosing the order of things. That's why I suggested getting them all worked out before deciding what your functions should look like (ouput some dummy text to show that the command was received). Make sure the required questions are answered and that optional ones are set to default values if they aren't modified by the user.
I've written these so that a small function is called as soon as a command is encountered in the loop, and I've written so that I collect all the commands and then run a large function that takes most of the inputs and executes in the order that makes most sense. In this case you will want the latter option (though you should still write smaller functions that build into the larger one).
Does your teacher use objects/classes/structs when they write examples, or are they sticking to functions only?
The most difficult option I see up there is the binary shift:
You might want to ask your teacher what exactly they expect with the binary shift, what size of variable are they expecting for starters. And if you need to anticipate description headers in the binary file (like bmp files), should the headers get the shift applied as well.
#include <iostream>
#include <unistd.h>
#include <sstream>
usingnamespace std;
void usage(constchar *argv0)
{
cout << "Usage: " << argv0
<< " [options]\n"
<< "where options are:\n"
<< "-b <num> set buffer size to num\n"
<< "-n <num> Read num bytes\n"
<< "-c <num> set shift to num\n"
<< "-r <num> set rotation amount to num\n"
<< "-x\n";
}
int main(int argc, char **argv)
{
int opt; // be sure to use an int, not a char
size_t bufSize {1024}; // buffer size (change with -b)
size_t numRead {512}; // num bytes to read (change with -n)
unsigned shift{2}; // amount to shift (change with -c)
unsigned rotation{2}; // amount to rotate (change with -r)
bool hexOutput=false; // output in hex: set with -x
// Do the getopt loop. The 3rd parameter gives the legal options.
// a colon after a letter means that option takes an argument
while ((opt = getopt(argc, argv, "b:n:c:r:x")) != EOF) {
if (optarg == nullptr) optarg = const_cast<char *>(""); // so istringstream will work
istringstream ss(optarg);
switch(opt) {
case'b':
ss >> bufSize;
break;
case'n':
ss >> numRead;
break;
case'c':
ss >> shift;
break;
case'r':
ss >> rotation;
break;
case'x':
hexOutput = true;
break;
default:
cout << "unknown option " << static_cast<char>(opt)
<< ".\n";
usage(argv[0]);
return 1;
}
if (!ss) {
// conversion failed
cout << "illegal value \"" << optarg << "\" for -"
<< static_cast<char>(opt)
<< " option\n";
usage(argv[0]);
return 1;
}
}
cout << " buf size = " << bufSize << '\n';
cout << " numRead = " << numRead << '\n';
cout << " shift = " << shift << '\n';
cout << " rotation = " << rotation << '\n';
cout << "hexOutput = " << (hexOutput ? "true" : "false") << '\n';
// global optind is the index of the first command line argument after
// the options.
cout << "The remaining command line arguments are:\n";
for (int i = optind; i < argc; ++i) {
cout << argv[i] << '\n';
}
}
dhayden@DHAYDEN4WLGPF2 ~/tmp
$ ./foo -n 33 -x 22 -c hello world
buf size = 1024
numRead = 33
shift = 2
rotation = 2
hexOutput = true
The remaining command line arguments are:
22
-c
hello
world
dhayden@DHAYDEN4WLGPF2 ~/tmp
$ ./foo -n 33 -x -c 22 hello world
buf size = 1024
numRead = 33
shift = 22
rotation = 2
hexOutput = true
The remaining command line arguments are:
hello
world
dhayden@DHAYDEN4WLGPF2 ~/tmp
$ ./foo -?
unknown option ?.
Usage: ./foo [options]
where options are:
-b <num> set buffer size to num
-n <num> Read num bytes
-c <num> set shift to num
-r <num> set rotation amount to num
-x
dhayden@DHAYDEN4WLGPF2 ~/tmp
$ ./foo -n 33 -- -x -c 22 hello world
buf size = 1024
numRead = 33
shift = 2
rotation = 2
hexOutput = false
The remaining command line arguments are:
-x
-c
22
hello
world
Pay particular attention to the last example which uses the "--" command line argument. This tells getopt to stop parsing options. It's useful when a command line argument isn't an option, such as when the command takes a filename as an argument and the file name starts with "-".