User Tools

Site Tools


haas:fall2017:cprog:projects:cbf0

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
haas:fall2017:cprog:projects:cbf0 [2017/09/09 23:24] wedgehaas:fall2017:cprog:projects:cbf0 [2017/10/15 20:49] (current) wedge
Line 3: Line 3:
 <WRAP><fs 150%>CSCS1320 C/C++ Programming</fs></WRAP> <WRAP><fs 150%>CSCS1320 C/C++ Programming</fs></WRAP>
 </WRAP> </WRAP>
- 
-~~TOC~~ 
  
 ======Project: C Binary Fun (cbf0)====== ======Project: C Binary Fun (cbf0)======
Line 35: Line 33:
  
 The computer works in units of **bytes**, which these days means groups of 8 bits. C has the ability to arbitrarily read and write individual bytes of data, and we will want to make use of that to aid us in our current task. The computer works in units of **bytes**, which these days means groups of 8 bits. C has the ability to arbitrarily read and write individual bytes of data, and we will want to make use of that to aid us in our current task.
 +
 +=====Opening and reading from files=====
 +The nice thing about C is that it tends to embody the "everything is a file" mantra from UNIX.
 +
 +What this means, basically, is that interacting with data in a file is really no different that interacting with data from the keyboard or data to the screen. We merely need a FILE pointer and appropriate resources allocated.
 +
 +To interact with a file, we must first declare a pointer to type FILE that will be our point of transaction.
 +
 +Common names for our file pointer variable are **fp**, **fPtr**, **input**, **inp**, but in reality can be anything you want.
 +
 +The intention is that, of course, you name variables so they are meaningful in the context of the overall implementation.
 +
 +<code c>
 +    FILE *input  = NULL;
 +</code>
 +
 +====Opening a file with fopen()====
 +To attach a file stream to a FILE pointer, we utilize a file opening function such as **fopen()**.
 +
 +It takes two arguments:
 +  - the path and name of file we wish to open (provided as a string)
 +  - the mode we wish to open the file as (provided as a string)
 +
 +There are 3 common file opening modes (and combinations thereof, among others, sometimes dependent on the particular operating system being run). For now, I highly recommend just sticking to ONE mode of operation per FILE pointer. This can avoid messy things like data corruption and indirect logic/runtime errors.
 +
 +The 3 file modes:
 +  * r - open file for reading (start at beginning)
 +  * w - open file for writing (start at beginning)
 +  * a - open file for appending (add to end)
 +
 +If we wanted to open the file "**sample0.txt**" in the current directory for **reading**, using the file pointer **input**, we would do the following:
 +
 +<code c>
 +    input  = fopen ("sample0.txt", "r");
 +</code>
 +
 +Note the double quotes around each argument. They both need to be strings (ie array of char terminated with NULL terminator characters), and the double quotes enables this.
 +
 +====Reading from the file====
 +If the file is filled with a set format of data you'd like to retrieve, such as one short integer per line (basically, a text file filled with numbers), we can just use our trusty and familiar **fscanf()** function. We merely have have to indicate the correct file pointer:
 +
 +<code c>
 +    short int value  = 0;
 +    
 +    ...
 +    
 +    fscanf (input, "%hd", &value);
 +</code>
 +
 +If there is no simple universal "format" to the file, or if the raw information in the file is the information we are interested in, we need to instead look at it as a consecutive collection of bytes, and we can grab a char's worth of data (I would recommend starting out by looking at a file like this as a byte-by-byte or char-by-char endeavor... ignore trying to transact with groups of them until you get the process down with individual chars).
 +
 +The **fscanf()** function is still viable here, but if all we're after is a char value, there's a special purpose input function we can use instead: **fgetc()**
 +
 +To read a byte of data from a file and store it in our variable (called byte), we would do the following:
 +
 +<code c>
 +    char byte  = 0;
 +    
 +    ...
 +    
 +    byte  = fgetc (input);
 +</code>
 +
 +The **fgetc()** function takes the intended FILE pointer it is to read from as its argument, so **input** should be a FILE pointer AND should have previously been **fopen()**'ed (and for **reading**!) prior to calling **fgetc()**.
 +
 +To make things easier, placing logic to read from a file in a loop can be a very powerful combination.
  
 =====Task===== =====Task=====
 Your task is to write a hex viewer, along the lines of the **xxd(1)** tool found on the system. Your task is to write a hex viewer, along the lines of the **xxd(1)** tool found on the system.
  
-=====Grabit===== 
-I have prepared some files to assist in our endeavors, which can be obtained through the use of the special **grabit** tool found on lab46: 
  
 =====Experiencing xxd===== =====Experiencing xxd=====
Line 106: Line 168:
     * a 7-digit hex offset (referring to the first data byte on a given line)     * a 7-digit hex offset (referring to the first data byte on a given line)
     * followed by a colon and a single space     * followed by a colon and a single space
-    * then eight space separated groups of two bytes+    * differently from **xxd(1)**: sixteen space separated groups of bytes
     * however you arrive at it: two total spaces following the hex bytes (again, see output example)     * however you arrive at it: two total spaces following the hex bytes (again, see output example)
     * a 16-character ASCII representation field (no separating spaces between the values)     * a 16-character ASCII representation field (no separating spaces between the values)
Line 114: Line 176:
   * The hex values and rendered ASCII displayed will be sourced from the file specified on the command-line. While the target files for this project are less than 512 bytes, your program should be able to handle larger and smaller files, and update its display accordingly.   * The hex values and rendered ASCII displayed will be sourced from the file specified on the command-line. While the target files for this project are less than 512 bytes, your program should be able to handle larger and smaller files, and update its display accordingly.
   * If a line throttle is given, your program is to stop output of data and ASCII rendering at that line, once it completes.   * If a line throttle is given, your program is to stop output of data and ASCII rendering at that line, once it completes.
-  * Once the data in the file has been exhausted, you need to wrap up as appropriate; finish the current line (even if you have to pad spaces), display the corresponding ascii field (padding spaces as appropriate), and display the closing footer.+  * Once the data in the file has been exhausted, you need to wrap up as appropriate; finish the current line (even if you have to pad spaces), and display the corresponding ascii field (padding spaces as appropriate).
   * Don't forget to **fclose()** any open file pointers! And **free()** any **malloc()**'ed or **calloc()**'ed memory.   * Don't forget to **fclose()** any open file pointers! And **free()** any **malloc()**'ed or **calloc()**'ed memory.
  
 +Sample output of your program should be as follows (compared to the **xxd(1)** output above):
 +
 +<cli>
 +0000000: 3e 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  >ABCDEFGHIJKLMNO
 +0000010: 50 51 52 53 54 55 56 57 58 59 5a 3c 0a 5b 61 62  PQRSTUVWXYZ<.[ab
 +0000020: 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72  cdefghijklmnopqr
 +0000030: 73 74 75 76 77 78 79 7a 5d 0a 30 31 3a 09 09 20  stuvwxyz].01:..
 +0000040: 42 49 4e 41 52 59 0a 30 31 32 33 34 35 36 37 3a  BINARY.01234567:
 +0000050: 09 20 4f 43 54 41 4c 0a 30 31 32 33 34 35 36 37  . OCTAL.01234567
 +0000060: 38 39 3a 09 20 44 45 43 49 4d 41 4c 0a 30 31 32  89:. DECIMAL.012
 +0000070: 33 34 35 36 37 38 39 41 42 43 44 45 46 3a 48 45  3456789ABCDEF:HE
 +0000080: 58 41 44 45 43 49 4d 41 4c 0a 29 21 40 23 24 25  XADECIMAL.)!@#$%
 +0000090: 5e 26 2a 28 0a 2e 0a                             ^&*(...
 +</cli>
 =====Detecting Terminal Size===== =====Detecting Terminal Size=====
 To detect the current size of your terminal, you may make use of the following code, provided in the form of a complete program for you to test, and then adapt into your code as appropriate. To detect the current size of your terminal, you may make use of the following code, provided in the form of a complete program for you to test, and then adapt into your code as appropriate.
Line 143: Line 219:
  
 Compile and run the above code to see how it works. Try it in different size terminals. Then incorporate the logic into your hex viewer for this project. Compile and run the above code to see how it works. Try it in different size terminals. Then incorporate the logic into your hex viewer for this project.
- 
-=====Bonus Opportunities===== 
-The following can be considered a bonus point opportunity: 
- 
-  * Enhance the program to accept up to 6 pairs of additional values (offset followed by its length), where each offset through length will be colored using ANSI text escape sequences. 
-  * For any line containing this colorized text, highlight the address in bold white. 
- 
-====Sample output==== 
- 
-As an example, running the program with the following arguments could produce results like this: 
- 
-<cli> 
-lab46:~/src/cprog/cbf0$ ./cbf0 sample0.txt 0 0x1be 1 0x1c2 1 0x1c6 4 0x1ca 4 0x1fe 2 
-</cli> 
- 
-{{:haas:spring2016:cprog:projects:hexviewer.png?640|}} 
- 
-====ANSI escape sequences for color==== 
-This probably isn't very portable, and depending on the terminal, it may not work for some people. 
- 
-It may be most convenient to set up preprocessor #define statements near the top of your code, as follows: 
- 
-<code c> 
-#define  ANSI_RESET             "\x1b[0m" 
-#define  ANSI_BOLD              "\x1b[1m" 
-#define  ANSI_FG_BLACK          "\x1b[30m" 
-#define  ANSI_FG_RED            "\x1b[31m" 
-#define  ANSI_FG_GREEN          "\x1b[32m" 
-#define  ANSI_FG_YELLOW         "\x1b[33m" 
-#define  ANSI_FG_BLUE           "\x1b[34m" 
-#define  ANSI_FG_MAGENTA        "\x1b[35m" 
-#define  ANSI_FG_CYAN           "\x1b[36m" 
-#define  ANSI_FG_WHITE          "\x1b[37m" 
-#define  ANSI_BG_BLACK          "\x1b[40m" 
-#define  ANSI_BG_RED            "\x1b[41m" 
-#define  ANSI_BG_GREEN          "\x1b[42m" 
-#define  ANSI_BG_YELLOW         "\x1b[43m" 
-#define  ANSI_BG_BLUE           "\x1b[44m" 
-#define  ANSI_BG_MAGENTA        "\x1b[45m" 
-#define  ANSI_BG_CYAN           "\x1b[46m" 
-#define  ANSI_BG_WHITE          "\x1b[47m" 
-</code> 
- 
-To use, you output them: 
- 
-<code> 
-fprintf(stdout, ANSI_FG_GREEN); 
-fprintf(stdout, "This text is green\n"); 
-fprintf(stdout, ANSI_RESET); 
-</code> 
- 
-You have to remember to turn the color or setting off (resetting it) to revert back to the original color. 
- 
-You can mix and match as well: 
- 
-<code> 
-fprintf(stdout, ANSI_FG_YELLOW); 
-fprintf(stdout, ANSI_BG_BLUE); 
-fprintf(stdout, ANSI_BOLD); 
-fprintf(stdout, "This text is bold yellow on blue\n"); 
-fprintf(stdout, ANSI_RESET); 
-</code> 
- 
-While there are 8 available foreground colors, bolding can double that range to 16. 
  
 =====Submission===== =====Submission=====
haas/fall2017/cprog/projects/cbf0.1504999488.txt.gz · Last modified: 2017/09/09 23:24 by wedge