Week 13

Decrypt

/*
 * Example which decrypts files from encrypt, without
 * requiring the password.
 *
 * NB: Will not work without supporting functions
 * from assignment 2
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

#include "encrypt.h"

int main(int argc, char* argv[])
{
    char word[512];
    char buf[512];
    int i;
    int mod;
    int seed;
    int valid;
    FILE *fin;
    FILE *fout;
    FILE *word_file;

    if(argc != 3)
    {
        printf("Usage: decrypt <input> <output>\n");
        exit(1);
    }

    /* Open files, check if successful */
    fin = fopen(argv[1], "r");
    fout = fopen(argv[2], "w+"); /* fout is read and write */
    word_file = fopen("words.txt", "r");
    assert(word_file);
    assert(fin);
    assert(fout);

    /* Loop over each word in dictionary */
    while(fgets(word, sizeof(word), word_file))
    {
        /* Delete trailing newline */
        word[strlen(word) - 1] = '\0';

        /* Loop over each modulo value */
        for(mod = 0; mod < 2; mod++)
        {
            /* Confirm files are ok */
            assert(fin);
            assert(fout);

            /* Rewind to start of files */
            fseek(fin, 0, SEEK_SET);
            fseek(fout, 0, SEEK_SET);

            /* Compute seed based on keyword
             * NB: This means a file encrypted with a non
             * default seed cannot be decrypted */
            for(seed = 0, i = 0; word[i] != '\0'; ++i)
                seed = word[i] + 31 * seed;

            /* Try decryption with given password/modulo combination */
            srand(seed);
            encrypt(fin, fout, word, mod);

            /* Flush fout, seek to start */
            fflush(fout);
            fseek(fout, 0, SEEK_SET);

            /* Loop through fout, assume correct file contains
             * only printable characters */
            valid = 1;
            while(1)
            {
                int c;
                c = fgetc(fout);
                if(c == EOF)
                    break;
                if(!isspace(c) && !isalpha(c) && !isdigit(c) && !ispunct(c))
                {
                    valid = 0;
                    break;
                }
            }

            /* We've found the password */
            if(valid)
            {
                printf("Result = %s\nModulo = %d\nMessage = ", word, mod);
                fseek(fout, 0, SEEK_SET);
                while(fgets(buf, sizeof(buf), fout))
                    printf(buf);
                return 0;
            }
        }
    }
    printf("Could not decrypt file\n");
    return 0;
}

Week 12

Writing test code

/* Test get_next_word() function */
#include <stdio.h>
#include "parser.h"

int main(void)
{
    char *str = "   hello world";
    char word[100];
    char *res;

    res = get_next_word(word, str);

    printf("Input: '%s'\n", str);
    printf("Result: '%s'\n", res);
    printf("Word: '%s'\n", word);

    return 0;
}
/* Tes get_next_number() function */
#include <stdio.h>
#include "parser.h"

int main(void)
{
    char *str = "  222 hello world";
    int num;
    char *res;

    res = get_next_number(&num, str);

    printf("Input: '%s'\n", str);
    printf("Result: '%s'\n", res);
    printf("Number: '%d'\n", num);

    return 0;
}
/* Test parsing multiple fields */
#include <stdio.h>
#include "parser.h"

#define BUFSIZE 255

int main(void)
{
    int n;
    char buffer[BUFSIZE];
    char word[BUFSIZE];
    char *pc;

    /* Example input: i test.txt 123 */
    printf("Enter some input: ");
    fgets(buffer, BUFSIZE, stdin);

    pc = get_next_letter(buffer);
    if (*pc == '\0') return 0;
    printf("First letter: %c\n", *pc);

    pc = get_next_word(word, pc + 1);
    if (*word == '\0') return 0;
    printf("Following word: %s\n", word);

    pc = get_next_number(&n, pc);
    if (*pc == '\0') return 0;
    printf("Following number: %d\n", n);

    return 0;
}

Pointers vs Indices

/* Using pointers */
char *get_next_letter(char *s)
{
    while(!isalpha(*s) && *s != '\0')
        s++;
    return s;
}
int main(void)
{
    char s[] = "  abcde";
    char *r;

    r = get_next_letter(s);
    printf("First letter is '%c'\n", *r);
    printf("String starting here is '%s'\n", r);

    return 0;
}
/* Using indices */
char *get_next_letter(char *s)
{
    int i = 0;
    while(!isalpha(s[i]) && s[i] != '\0')
        i++;
    return &s[i];
}

Week 11

Modular Code

/* main.c */
#include "fileio.h"
#include "encrypt.h"

int main(int argc, char* argv[])
{

    open_file(...);

    encrypt_data(...);

    return 0;
}
            
/* fileio.h */
#include <stdio.h>

FILE *open_file(char *filename);
int check_file(char *filename);
            
/* fileio.c */
#include "fileio.h"

FILE *open_file(char *filename)
{
    FILE* file = ...;
    return file;
}

int check_file(char *filename)
{
    return 1;
}
             
/* encrypt.h */
#include <stdio.h>
#include <stdlib.h>

void encrypt_data(...);
void decrypt_data(...);

            
/* encrypt.c */
#include "encrypt.h"

void encrypt_data(...)
{
    /* Do something */
}

void decrypt_data(...)
{
    /* Do something */
}

            

Flag array

/*
 * Using an array to store 'flag' values
 */

#include <stdio.h>

#define BUF_SIZE 100

enum flag_t
{
    APPLE,
    BANANA,
    CARROT,
    NUM_FRUIT
};

void print_message(unsigned int flags[]);
void parse_input(char* input, unsigned int flags[]);

int main(void)
{
    unsigned int flags[NUM_FRUIT];
    char buf[BUF_SIZE];

    printf("Input request: ");
    fgets(buf, sizeof(buf), stdin);
    parse_input(buf, flags);
    print_message(flags);

    return 0;
}

void print_message(unsigned int flags[])
{
    printf("You asked for: ");
    if(flags[APPLE])
        printf("%d apples, ", flags[APPLE]);
    if(flags[BANANA])
        printf("%d bananas, ", flags[BANANA]);
    if(flags[CARROT])
        printf("%d carrots, ", flags[CARROT]);
    printf("\n");
}

void parse_input(char* input, unsigned int flags[])
{
    do
    {
        switch(*input)
        {
            case 'a':
                flags[APPLE] += 1;
                break;
            case 'b':
                flags[BANANA] += 1;
                break;
            case 'c':
                flags[CARROT] += 1;
                break;
        }
    } while(*++input != '\0');
}

Week 10

Assignment 1

Example solution: https://gist.github.com/3855587

Flags

/*
 * Using bit fields to store 'flag' values
 *
 * | operator is used to set a value
 * & operator is used to check a value
 */

#include <stdio.h>

#define BUF_SIZE 100

enum flag_t
{
    APPLE = 1,
    BANANA = 2,
    CARROT = 4
};

void print_message(unsigned int flags);
unsigned int parse_input(char* input);

int main(void)
{
    unsigned int flags;
    char buf[BUF_SIZE];

    printf("Input request: ");
    fgets(buf, sizeof(buf), stdin);
    flags = parse_input(buf);
    print_message(flags);

    return 0;
}

void print_message(unsigned int flags)
{
    printf("You asked for: ");
    if(flags & APPLE)
        printf("apple ");
    if(flags & BANANA)
        printf("banana ");
    if(flags & CARROT)
        printf("carrot ");
    printf("\n");
}


unsigned int parse_input(char* input)
{
    unsigned int flags = 0;

    do
    {
        switch(*input)
        {
            case 'a':
                flags |= APPLE;
                break;
            case 'b':
                flags |= BANANA;
                break;
            case 'c':
                flags |= CARROT;
                break;
        }
    } while(*++input != '\0');
    return flags;
}

Command line

/*
 * Reading values from the command line
 */

#include <stdio.h>
#include <string.h>

void print_inputs(char* str)
{
    printf("You input: %s\n", str);
}

int main(int argc, char* argv[])
{
    char input[200];
    int i;

    if(argc > 1)
    {
        strcpy(input, "");
        for(i = 1; i < argc; i++)
        {
            strcat(input, argv[i]);
            strcat(input, " ");
        }
        print_inputs(input);
    }
    else
    {
        printf("Type something: ");
        fgets(input, sizeof(input), stdin);
        print_inputs(input);
    }

    return 0;
}

File Output

/*
 * Print to file and stdout from the same function
 */

#include <stdio.h>
#include <assert.h>

void print_table(FILE* fout, int rows)
{
    int i;
    fprintf(fout, "Header\n");
    for(i = 0; i < rows; i++)
    {
        fprintf(fout, "Row %d\n", i);
    }
}

int main(void)
{
    FILE* fout;
    fout = fopen("out.txt", "w");
    assert(fout);

    print_table(fout, 10);
    print_table(stdout, 10);

    fclose(fout);

    return 0;
}

Week 9

Malloc

/* Week 9 Task 1
 * Malloc
 */

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int i;
    int num = -1;
    double *arr;

    printf("Array size: ");
    if(scanf("%d", &num) != 1 || num < 1)
    {
        printf("Input error\n");
        exit(1);
    }

    /* Create empty array */
    /*arr = (double *)malloc(num * sizeof(double));*/
    arr = (double *)calloc(num, sizeof(double));
    if(!arr)
    {
        printf("Failed to allocate memory\n");
        exit(1);
    }

    for(i = 0; i < num; i++) {
        printf("%f ", arr[i]);
    }
    printf("\n");

    free(arr);

    return 0;
}