Man Person
Man Person

Reputation: 1130

C Segmentation Fault

Hi sorry for all the questions, but I am getting a "Segmentation fault(core dumped)" on my terminal window when I run this code.

#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");
    printf("   Or: head -n <number of characters> <file>\n"); 
    return -1;
}

int main (int argc,char **argv) {
    if ((argc != 2) && (argc != 4)) return usage();

    char *fileName = argv[1];
    int lineCount = 10;
    FILE *src;

    if ((argc == 4) && (strcmp(argv[1], "-n" != 0))){
        fileName = argv[1];
        lineCount = argv[3]; 
        puts("-n in last position");
    }else{
        fileName = argv[3];
        lineCount = argv[1];
        puts("-n in first position");
    }

    if((src = fopen(fileName, "r")) == NULL){
        puts("Can't open input file.");
        exit(-1);
    }
}

I'm pretty sure it's with the fopen function, but I'm not exactly sure why this is happening.

Upvotes: 0

Views: 1489

Answers (4)

paxdiablo
paxdiablo

Reputation: 881653

You have one of the closing parentheses in the wrong place:

(strcmp (argv[1], "-n" != 0))

should be:

(strcmp (argv[1], "-n") != 0)

However, even once that's fixed, your argument processing is still not quite right.

In your previous question, the head -n COUNT FILE was not a possibility, that made the argument checking reasonably easy.

Here's the logic you need to follow now that you allow for a "floating" -n count section:

int linecount
char *filename = NULL

if argc == 2:
    linecount = 10
    filename = argv[1]
else:
    if argc == 4:
        if argv[1] == "-n":
            linecount = argv[2]
            filename = argv[3]
        else:
            if argv[2] == "-n":
                linecount = argv[3]
                filename = argv[1]

if filename = NULL:
    generate some error

It basically catches the two-argument version first. If it's a four-argument version, it then finds out where the "-n" is so it can intelligently decide which argument is which value.

As you can see, that's not quite what you have (your code looks for linecount in argv[1] which is never the case). You should use something like this as a guide:

argc  argv[0]  argv[1]  argv[2]  argv[3]
----  -------  -------  -------  -------
   2  head     <file>
   4  head     <file>   -n       <count>
   4  head     -n       <count>  <file>

Once you refer to that, it should be easy to write the code for the different situations.

You'll have to turn that pseudo-code of mine back into C of course (using strcmp instead of == for strings, and ensuring you use atoi/strtol for converting the string linecount argument to an integer), but that's the basic flow you should follow.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754110

Are you allowed to use the getopt() function? On Linux, the getopt() function would handle the -n option in either location with aplomb (unless the POSIXLY_CORRECT environment variable is set). It would make life easier for you:

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

int main(int argc, char **argv)
{
    int numLines = 10;
    char *fileName = 0;
    int opt;

    while ((opt = getopt(argc, argv, "n:")) != -1)
    {
        switch (opt)
        {
        case 'n':
            numLines = atoi(optarg);  /* Could check for positive answer */
            break;
        default:
            usage();  /* Assuming usage() does not return */
            break;
        }
    }

    if (optind != argc - 1)  /* Insist on one filename argument */
        usage();

    fileName = argv[optind];

    ...open file and process it...

    return(0);
}

Note that it would be easy to process standard input instead of a file; the condition after the loop would need to be adjusted, of course. You can also easily add a -? or -h option for help, and so on.

Upvotes: 0

Adrian Cornish
Adrian Cornish

Reputation: 23866

There are a few things wrong first off - the comparison is inside the function

strcmp(argv[1], "-n" != 0)

You are assigning an char * to a int

lineCount = argv[3];

And here

lineCount = argv[1];

Here are the compile errors I get

[adrian@iceweasel ~]$ gcc -Wall -ansi -pedantic uu.c
uu.c: In function ‘main’:
uu.c:15: warning: ISO C90 forbids mixed declarations and code
uu.c:19: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
/usr/include/string.h:143: note: expected ‘const char *’ but argument is of type ‘int’
uu.c:21: warning: assignment makes integer from pointer without a cast
uu.c:25: warning: assignment makes integer from pointer without a cast
uu.c:33: warning: control reaches end of non-void function

Upvotes: 5

ddyer
ddyer

Reputation: 1786

it looks like if argc==2 you immediately access argv[3]. That's gotta hurt.

Upvotes: 6

Related Questions