ICS 451 Assignment 3: C strings and pointers

Assigned January 27th, to be completed by February 3rd. Turn in this exercise by e-mailing to jmoroney@hawaii.edu all your code described below.

You are encouraged to work in teams of two for this exercise. Your team cannot include anyone that was on your team in any of the prior exercises.

  1. Strings and Pointers
  2. This program must take a single argument on the command line. That is, defining main as

    int main (int argc, char ** argv)
    
    your program must: The argument will be a set of strings separated by '/', for example,
    edoardo/biagioni/jon/moroney/foo/bar/baz
    
    Your program must create a pointer p and point it to the first character of the argument. For each string, it should:

    For example, given the above string, your program should print

    edoardo (8)
    biagioni (9)
    jon (4)
    moroney (8)
    foo (4)
    bar (4)
    baz (4)
    

    Your file name for this part of the assignment should be strings.c.

  3. Structs, Pointers, and Buffers
  4. Include the following in your code:
    
    #include <stdio.h>
    #include <netinet/in.h>  /* gives htons and friends */
    
    struct hw3
      char x;
      char y;
      short z;
      int w;
    };
    
    char buffer [] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 };
    
    struct hw3 * sp = (struct hw3 *) buffer;
    
    Write a function print_buffer to print all the bytes in the buffer, in hex. For the above example, your code should print:
    12 34 56 78 9a bc de f0
    
    The function print_buffer takes two parameters, a pointer to the buffer, and the number of bytes to print.

    Write another function print_struct to print all of the values in a struct of type struct hw3. If x is 0x12, y is 0x34, z is 0x5678, and w is 0x9abcdef0, your function should print:

    sp->x is 0x12, sp->y is 0x34, sp->z is 0x5678, sp->w is 0x9abcdef0
    
    The values in the struct will be in network byte order, but you MUST print them in host byte order.

    The function print_struct takes a single parameter -- a pointer to a struct hw3. The prototypes of these two functions are:

    void print_buffer (char * buffer, int num_bytes);
    void print_struct (struct hw3 * sp);
    
    From your main function, call print_buffer and print_struct on buffer and buffer and sp. Your output should be as in the examples above.

    Next, use sp to set the value of the buffer as follows (every value in sp should be in big-endian byte order, that is, in network byte order):

    If you did this correctly, when you print the buffer, you should see:

    77 92 43 89 ab c8 90 32
    

    Be aware that when printing a char field, it gets automatically sign extended. So for example,

      char foo [1] = { 0x89 };
      printf ("%02x\n", foo [0]);
    
    prints ffffff89. To get the desired behavior, you have to have:
      char foo [1] = { 0x89 };
      printf ("%02x\n", foo [0] & 0xff);
    
    Similarly (but with 16 bits) for a short.

    Your file name for this part of the assignment should be sp.c.

  5. Bit Manipulation
  6. Write a function
    unsigned int set_bits (unsigned int value);
    
    to set to 1 the top two bits of the single-byte value. set_bits should print the result in hex, and return it.

    For example, set_bits (0x5) should print and return 0xc5, and set_bits (0x72) should print and return 0xf2.

    If the value is greater than 255 (0xff, the maximum single-byte value), set_bits should only print and return the low-order 8 bits. Use a bit mask to do this (the & operator), not a conditional (if) statement.

    Write a function

    unsigned int combine_bits (int top, int middle, int low);
    
    to compute a 16-bit result where: Your function should both print the result (in hex) and return it.

    For example, combine_bits (0x2, 0x5, 0x123) should print and return 0x9523, combine_bits (0x1, 0x9, 0x321) should print and return 0x6721.

    If you get confused about how to do this, you may want to convert the hex to binary, write out the binary of the desired result (on paper), and convert the binary back to hex. FYI, the value 0x123 is decimal 291, the value 0x321 is decimal 801.

    Note that your program should not do any binary conversion (numbers in C are already in binary -- printf converts binary ints to decimal or hex), but just use the shift (<< and >>) and bitwise (| & ~) operations.

    Again, if the value is greater than 65,535 (0xffff, the maximum two-byte value), combine_bits should only print and return the low-order 16 bits. Use a bit mask to do this (the & operator), not a conditional (if) statement.

    These functions should all be in the same C file, named bits.c.





Computer Networks, ICS 451
Instructor: Edo Biagioni