Software Construction


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

// write bytes of stream to stdout
void process_stream(FILE *stream) {
    int byte;
    while ((byte = fgetc(stream)) != EOF) {
        if (fputc(byte, stdout) == EOF) {
            perror("cat:");
            exit(1);
        }
    }
}

// process files given as arguments
// if no arguments process stdin
int main(int argc, char *argv[]) {

    if (argc == 1) {
        process_stream(stdin);
    } else {
        for (int i = 1; i < argc; i++) {
            FILE *in = fopen(argv[i], "r");
            if (in == NULL) {
                fprintf(stderr, "%s: %s: ", argv[0], argv[i]);
                perror("");
                return 1;
            }
            process_stream(in);
            fclose(in);
        }
    }

    return 0;
}


import sys


def process_stream(stream):
    """
    copy bytes of f to stdout
    """
    for line in stream:
        print(line, end="")


def main():
    """
    process files given as arguments, if no arguments process stdin
    """
    if not sys.argv[1:]:
        process_stream(sys.stdin)
    else:
        for pathname in sys.argv[1:]:
            with open(pathname, "r") as f:
                process_stream(f)


if __name__ == "__main__":
    main()


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

// print lines containing the specified substring
void process_stream(FILE *stream, char *name, char *substring) {
    char *line = NULL;
    size_t line_size = 0;
    int line_number = 1;

    while (getline(&line, &line_size, stream) > 0) {
        if (strstr(line, substring) != NULL) {
            printf("%s:%d:%s", name, line_number, line);
        }
        line_number++;
    }

    free(line);
}

// process files given as arguments
// if no arguments process stdin
int main(int argc, char *argv[]) {

    if (argc == 2) {
        process_stream(stdin, "<stdin>", argv[1]);
    } else {
        for (int i = 2; i < argc; i++) {
            FILE *in = fopen(argv[i], "r");
            if (in == NULL) {
                fprintf(stderr, "%s: %s: ", argv[0], argv[i]);
                perror("");
                return 1;
            }
            process_stream(in, argv[i], argv[1]);
            fclose(in);
        }
    }

    return 0;
}


import sys


def process_stream(f, name, substring):
    """
    print lines containing substring
    """
    for (line_number, line) in enumerate(f, start=1):
        if substring in line:
            print(f'{name}:{line_number}:{line}', end='')


def main():
    """
    process files given as arguments, if no arguments process stdin
    """
    if len(sys.argv) == 2:
        process_stream(sys.stdin, "<stdin>", sys.argv[1])
    elif len(sys.argv) > 2:
        for pathname in sys.argv[2:]:
            with open(pathname, 'r') as f:
                process_stream(f, pathname, sys.argv[1])


if __name__ == '__main__':
    main()

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

// count lines, words, chars in stream
// assumes Unix-like line separator '\n'
// breaks on other platforms, see https://en.wikipedia.org/wiki/Newline

void process_stream(FILE *in, char *name) {
    int n_lines = 0;
    int n_words = 0;
    int n_chars = 0;
    int in_word = 0;
    int c;

    while ((c = fgetc(in)) != EOF) {
        n_chars++;

        if (c == '\n') {
            n_lines++;
        }

        if (isspace(c)) {
            in_word = 0;
        } else if (!in_word) {
            in_word = 1;
            n_words++;
        }
    }

    printf("%d %d %d %s\n", n_lines, n_words, n_chars, name);
}

// process files given as arguments
// if no arguments process stdin
int main(int argc, char *argv[]) {
    if (argc == 1) {
        process_stream(stdin, "stdin");
    } else {
        for (int i = 1; i < argc; i++) {
            FILE *in = fopen(argv[i], "r");
            if (in == NULL) {
                fprintf(stderr, "%s: %s: ", argv[0], argv[i]);
                perror("");
                return 1;
            }
            process_stream(in, argv[i]);
            fclose(in);
        }
    }
    return 0;
}


import sys
import os


def process_stream(stream):
    """
    count lines, words, chars in stream
    """
    lines = 0
    words = 0
    characters = 0
    for line in stream:
        lines += line.endswith(os.linesep)
        words += len(line.split())
        characters += len(line)
    print(f"{lines:>6} {words:>6} {characters:>6}", end="")


def main():
    """
    process files given as arguments, if no arguments process stdin
    """
    if not sys.argv[1:]:
        process_stream(sys.stdin)
    else:
        for pathname in sys.argv[1:]:
            with open(pathname, "r") as f:
                process_stream(f)
                print(f" {pathname}")


if __name__ == "__main__":
    main()

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

// cope stream to stdout except for repeated lines
void process_stream(FILE *stream) {
    char *line = NULL;
    size_t line_size = 0;
    char *last_line = NULL;
    size_t last_line_size = 0;

    while (getline(&line, &line_size, stream) > 0) {
        if (last_line == NULL || strcmp(line, last_line) != 0) {
            fputs(line, stdout);
        }

        // grow last_line if line has grown
        if (last_line_size != line_size) {
            last_line = realloc(last_line, line_size);
            assert(last_line != NULL);
            last_line_size = line_size;
        }

        strncpy(last_line, line, line_size);
    }

    free(line);
    free(last_line);
}

// process files given as arguments
// if no arguments process stdin
int main(int argc, char *argv[]) {
    if (argc == 1) {
        process_stream(stdin);
    } else {
        FILE *in = fopen(argv[1], "r");
        if (in == NULL) {
            fprintf(stderr, "%s: %s: ", argv[0], argv[1]);
            perror("");
            return 1;
        }
        process_stream(in);
        fclose(in);
    }

    return 0;
}


import sys


def process_stream(stream):
    """
    copy stream to stdout except for repeated lines
    """
    last_line = None
    for line in stream:
        if last_line is None or line != last_line:
            print(line, end='')
        last_line = line


def main():
    """
    process files given as arguments, if no arguments process stdin
    """
    if not sys.argv[1:]:
        process_stream(sys.stdin)
    else:
        for pathname in sys.argv[1:]:
            with open(pathname, 'r') as f:
                process_stream(f)


if __name__ == '__main__':
    main()

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

static int cmpstringp(const void *p1, const void *p2)
{
   return strcmp(* (char * const *) p1, * (char * const *) p2);
}


// print lines of stream in sorted order
void process_stream(FILE *stream) {
    char *line = NULL;
    size_t line_size = 0;
    char **lines = NULL;
    size_t lines_size = 0;

    while (getline(&line, &line_size, stream) > 0) {
        lines = realloc(lines, ++lines_size*sizeof(lines[0]));
        lines[lines_size-1] = line;
        line = NULL;
        line_size = 0;
    }
    free(line);

    qsort(lines, lines_size, sizeof(lines[0]), cmpstringp);

    for (size_t i = 0; i < lines_size; i++) {
        fputs(lines[i], stdout);
        free(lines[i]);
    }
    free(lines);
}

// process files given as arguments
// if no arguments process stdin
int main(int argc, char *argv[]) {

    if (argc == 1) {
        process_stream(stdin);
    } else {
        for (int i = 1; i < argc; i++) {
            FILE *in = fopen(argv[i], "r");
            if (in == NULL) {
                fprintf(stderr, "%s: %s: ", argv[0], argv[i]);
                perror("");
                return 1;
            }
            process_stream(in);
            fclose(in);
        }
    }

    return 0;
}


import sys


def process_stream(f):
    """
    print lines of stream in sorted order
    """
    print("".join(sorted(f)), end="")


def main():
    """
    process files given as arguments, if no arguments process stdin
    """
    if len(sys.argv) == 1:
        process_stream(sys.stdin)
    else:
        with open(sys.argv[1], 'r') as f:
            process_stream(f)


if __name__ == '__main__':
    main()


import subprocess
import sys

# the real xargs runs the command multiple times if input is large
# the real xargs treats quotes specially


def main():
    input_words = [w for line in sys.stdin for w in line.split()]
    command = sys.argv[1:]
    subprocess.run(command + input_words)


if __name__ == "__main__":
    main()