Search code examples
clinuxtailhead

C Basic Head Command


I'm trying to recreate the head, and tail commands from linux for my programming class. We just started using C so I'm new to the idea of allocating memory and pointers. I'm wondering why this doesn't work.

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

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

    /* Checks if correct amount of arguements */

    if(argc != 2 || argc != 4){
        printf("Usage: %s head <file> \n Or: head <file> -n <number of characters>", argv[0]);
        exit(-1);
    }

    if(strcmp(argv[1], "-n" != 0)){
        char fileName[strlen(argv[1])] = argv[1];
    }
}

//Compile error on char fileName[strlen(argv[1])] = argv[1];

Any additional insight would also be helpful.


Solution

  • First things first, your usage doesn't match your argument checking. According to the usage, you must use one of:

    head <filename>
    head <filename> -n <count>
    

    In other words, argv[1] is always the filename, argv[2] is the one that needs to be set to -n if there are more than two arguments.

    Secondly, unless you want to use VLAs (variable length arrays), you should probably just set up a pointer to the filename argument with something like:

    char *fileName = argv[1];
    

    You don't need to change it at all (you'll just be passing it to fopen, presumably), so it's a waste trying to make another copy.

    In addition, your if statement is wrong as an or, it should be an and. It's guaranteed that argc will either not be 2 or not be 4, since it can't be both at the same time.

    I would start with something like:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int usage (void) {
        printf ("Usage: head <file>\n");
        printf ("   or: head <file> -n <number of characters>\n");
        return -1;
    }
    
    int main (int argc,char *argv[]) {
        char *fileName;
        int lineCount;
    
        // Checks if correct arguments
    
        if ((argc != 2) && (argc != 4)) return usage();
    
        if ((argc == 4) && (strcmp(argv[2], "-n" != 0)) return usage();
    
        // Get file spec and line count
    
        fileName = argv[1];
    
        lineCount = (argc == 2) ? 10 : atoi (argv[3]); // or strtol for purists
        if (linecount < 0) lineCount = 0;
    
        // Now go ahead and implement the logic for head.
    
    }