COMP1511 17s1 Code Examples from Lectures on reading_and_writing_files Introduction to Programming

Simple example of file creation creates file "andrew.txt" containing 1 line ("andrew rules")

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

int main(int argc, char *argv[]) {
    FILE *outputStream;
    outputStream = fopen("andrew.txt", "a");
    if (outputStream == NULL) {
        perror(argv[0]);
        return 1;
    }
    fprintf(outputStream, "andrew rules\n");
    fclose(outputStream);
    return 0;
}

Simple example of file creation appends to file "andrew.txt" the line "andrew rules"

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

int main(int argc, char *argv[]) {
    FILE *outputStream;
    outputStream = fopen("andrew.txt", "a");
    if (outputStream == NULL) {
        perror(argv[0]);
        return 1;
    }
    fprintf(outputStream, "andrew rules\n");
    fclose(outputStream);
    return 0;
}

Simple implementation of reading files passed as command line arguments using fgetc - in other words cat

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

int main(int argc, char *argv[]) {
    FILE *stream;
    int c;
    int i;
    for (i = 1; i < argc; i = i + 1) {
        stream = fopen(argv[i], "r");
        if (stream == NULL) {
            perror(argv[i]);  // prints why the open failed
            exit(1);
        }
        c = fgetc(stream);
        while (c != EOF) {
            fputc(c, stdout);
            c = fgetc(stream);
        }
    }
    return 0;
}

Simple implementation of reading files passed as command line arguments using fgets - in other words cat

#include <stdio.h>
#define MAX_LINE 1024

int main(int argc, char *argv[]) {
    char line[MAX_LINE];
    FILE *stream;
    int i;
    for (i = 1; i < argc; i = i + 1) {
        stream = fopen(argv[i], "r");
        if (stream == NULL) {
            perror(argv[i]);  // prints why the open failed
            return 1;
        }
        while (fgets(line, MAX_LINE, stream) != NULL) {
           printf("%s", line);
        }
    }
    return 0;
}

Simple example of cp command copy contents of file specified as first argument to file specified as 2nd argument 8/5//13

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

int main(int argc, char *argv[]) {
    FILE *inputStream;
    FILE *outputStream;
    int c;

    inputStream = fopen(argv[1], "r");
    if (inputStream == NULL) {
        perror(argv[1]);
        exit(1);
    }

    outputStream = fopen(argv[2], "w");
    if (outputStream == NULL) {
        perror(argv[0]);
        exit(1);
    }

    c = fgetc(inputStream);
    while (c != EOF) {
        fputc(c, outputStream);
        c = fgetc(inputStream);
    }

    fclose(outputStream);
    return 0;
}

Simple implementation of Unix wc command

It counts lines, word & characters in the file specified as an argument

This version uses fgetc, see also wc_fgets.c

See later version for more sophisticated argument handling

#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void processStream(FILE *stream, char streamName[]) {
    int c, lastc, lineCount, wordCount, characterCount;

    lineCount = 0;
    characterCount = 0;
    wordCount = 0;

    lastc = ' ';
    c = fgetc(stream);

    while (c != EOF) {
        if (c == '\n') {
            lineCount = lineCount + 1;
        }
        if (isspace(c) && !isspace(lastc)) {
            wordCount = wordCount + 1;
        }
        characterCount = characterCount + 1;
        lastc = c;
        c = fgetc(stream);
    }

    if (!isspace(lastc)) {
            wordCount = wordCount + 1;
    }

    printf("%s contains %d lines %d words %d characters\n", streamName, lineCount, wordCount, characterCount);
}

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

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    in = fopen(argv[1], "r");
    if (in == NULL) {
        perror(argv[1]);
        return 1;
    }
    processStream(in, argv[1]);

    return 0;
}

/ Simple implementation of Unix wc command

It counts lines, word & characters from the files specified as arguments

If no files are specified instead stdin is processed

This allows use in a pipeline, e.g.: % dcc grep.c -o grep % dcc wc_fgetc1.c -o wc % ./grep return grep.c grep.c:30: return 1; grep.c:38: return 1; grep.c:44: return 0; % ./grep return grep.c | ./wc <stdin> contains 3 lines 9 words 85 characters

#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void processStream(FILE *stream, char streamName[]) {
    int c, lastc, lineCount, wordCount, characterCount;

    lineCount = 0;
    characterCount = 0;
    wordCount = 0;

    lastc = ' ';
    c = fgetc(stream);

    while (c != EOF) {
        if (c == '\n') {
            lineCount = lineCount + 1;
        }
        if (isspace(c) && !isspace(lastc)) {
            wordCount = wordCount + 1;
        }
        characterCount = characterCount + 1;
        lastc = c;
        c = fgetc(stream);
    }

    if (!isspace(lastc)) {
            wordCount = wordCount + 1;
    }

    printf("%s contains %d lines %d words %d characters\n", streamName, lineCount, wordCount, characterCount);
}

int main(int argc, char *argv[]) {
    FILE *in;
    int i;

    if (argc == 1) {
        // if no files are specified, process stdin
        processStream(stdin, "<stdin>");
    } else {
        for (i = 1; i < argc; i = i + 1) {
            in = fopen(argv[i], "r");
            if (in == NULL) {
                perror(argv[i]);
                return 1;
            }
            processStream(in, argv[i]);
        }
    }

    return 0;
}

Simple implementation of Unix wc command

It counts lines, word & characters in the file specified as an argument

This version uses fgets

#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void processStream(FILE *stream, char streamName[]) {
    char line[MAX_LINE];
    int i, lineCount, wordCount, characterCount;

    lineCount = 0;
    characterCount = 0;
    wordCount = 0;

    while (fgets(line, MAX_LINE, stream) != NULL) {
        for (i = 0; line[i] != '\0'; i = i + 1) {
            if (i > 0 && isspace(line[i]) && !isspace(line[i - 1])) {
                wordCount = wordCount + 1;
            }
            characterCount = characterCount + 1;
        }

        // this if handles case of line being longer than MAX_LINE
        if (!isspace(line[i - 1])) {
            wordCount = wordCount + 1;
        }  else if (line[i - 1] == '\n') {
            lineCount = lineCount + 1;
        }
    }

    printf("%s contains %d lines %d words %d characters\n", streamName, lineCount, wordCount, characterCount);
}

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

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    in = fopen(argv[1], "r");
    if (in == NULL) {
        perror(argv[1]);
        return 1;
    }
    processStream(in, argv[1]);

    return 0;
}

Print lines containing specified pattern from the files specified as arguments

This version provides the unix filter behaviour where if no files are specified it process stdin

Note this code willproduce incorrect results if matched lines contain >= MAX_LINE characters. Fixing this left as an exercise

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

#define MAX_LINE 65536

void searchStream(FILE *stream, char streamName[], char searchFor[]) {
    char line[MAX_LINE];
    int lineNumber;

    lineNumber = 1;
    while (fgets(line, MAX_LINE, stream) != NULL) {
        if (strstr(line, searchFor) != NULL) {
            printf("%s:%d:%s", streamName, lineNumber, line);
        }
        lineNumber = lineNumber + 1;
    }
}

int main(int argc, char *argv[]) {
    FILE *in;
    int i;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <prefix> <files>\n", argv[0]);
        return 1;
    } if (argc == 2) {
        searchStream(stdin, "<stdin>", argv[1]);
    } else {
        for (i = 2; i < argc; i = i + 1) {
            in = fopen(argv[i], "r");
            if (in == NULL) {
                perror(argv[i]);
                return 1;
            }
            searchStream(in, argv[i], argv[1]);
        }
    }

    return 0;
}

Print lines starting with specified string from specified files

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

#define MAX_LINE 1024

// test if str starts with prefix

int isPrefix(char prefix[], char str[]) {
    int length = strlen(prefix);
    return strncmp(prefix, str, length) == 0;
}

int main(int argc, char *argv[]) {
    char line[MAX_LINE];
    char *searchString;
    FILE *stream;
    int i;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <prefix> <files>\n", argv[0]);
        exit(1);
    }
    searchString = argv[1];
    for (i = 2; i < argc; i = i + 1) {
        stream = fopen(argv[i], "r");
        if (stream == NULL) {
            perror(argv[i]);
            return 1;
        }
        while (fgets(line, MAX_LINE, stream) != NULL) {
            if (isPrefix(searchString, line)) {
                printf("%s", line);
            }
        }
    }
    return 0;
}

print lines form file after replacing specified pattern after replacing specified pattern

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

#define MAX_LINE 1024
#define MAX_REPLACEMENT_LINE 32768

// copy string to new_string replacing all instances of target with replacement

void replace(char string[], char target[], char replacement[], char new_string[], int new_string_len) {
    int i = 0, j = 0;
    int target_length = strlen(target);
    int replacement_length = strlen(replacement);

    i = 0;
    j = 0;
    while (string[i] != '\0' && j < new_string_len - 1) {

        // if we have found the target string

        if (strncmp(target, &string[i], target_length) == 0) {

            // instead copy the replacement string to the new array

            strncpy(&new_string[j], replacement, replacement_length);
            i = i + target_length;
            j = j + replacement_length;
        } else {
            new_string[j] = string[i];
            i = i + 1;
            j = j + 1;
        }
    }

    new_string[j] = '\0';
}

int main(int argc, char *argv[]) {
    char line[MAX_LINE];
    char changed_line[MAX_REPLACEMENT_LINE];
    char *target_string;
    char *replacement_string;
    FILE *stream;
    int i;

    if (argc < 3) {
        fprintf(stderr, "Usage: %s <target> <replacement> <files>\n", argv[0]);
        exit(1);
    }
    target_string = argv[1];
    replacement_string = argv[2];

    i = 0;
    while (i < argc) {
        stream = fopen(argv[i], "r");
        if (stream == NULL) {
            perror(argv[i]);
            return 1;
        }

        while (fgets(line, MAX_LINE, stream) != NULL) {
            replace(line, target_string, replacement_string, changed_line, MAX_REPLACEMENT_LINE);
            printf("%s", changed_line);
        }

        i = i + 1;
    }
    return 0;
}