Need help understanding what to do(read, write, getopt)

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**************************************

2/10/2017

Assignment 3
**************************************/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define NBYTES 7991 //constant
using namespace std;

int main(int argc, char* argv[]){
int opt, fd, writecheck;//delcaring my ints
ssize_t howmany;
char buffer[NBYTES];


fd = open(argv[1], O_RDWR);//opening my file
if (fd == -1) {
        perror("error");// print error
exit(1); }


while(howmany = read(fd, buffer, NBYTES)){ // reading  the file
write(fd, buffer, howmany);
cout << buffer << endl;//displaying the buffer
}


int close(fd);//closing the file

return 0;


Its not letting me format this into code either..?
Last edited on
Well I fixed the code part
I'm guessing you fixed line 18; size_t

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.

* Just make sure you read what strcmp() returns when the two strings are equal... http://www.cplusplus.com/reference/cstring/

* The Cesar cipher should be pretty easy to implement, make the default offset 13 and make sure that the -c command changes the offset accordingly.

* NBYTES can no longer be a constant since it needs to be modified by the -b command.
Last edited on
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.
Last edited on
Here is code to parse the command line using getopt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <unistd.h>
#include <sstream>

using namespace std;

void usage(const char *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 "-".
Topic archived. No new replies allowed.