C分段故障

时间:2012-09-11 02:25:06

标签: c linux file fopen head

对不起所有的问题,但是当我运行此代码时,我的终端窗口上出现了“Segmentation fault(core dumped)”。

#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);
    }
}

我很确定它与fopen函数有关,但我不确定为什么会发生这种情况。

4 个答案:

答案 0 :(得分:6)

看起来如果argc == 2你立即访问argv [3]。那会受伤。

答案 1 :(得分:5)

首先出现了一些问题 - 比较是在函数内部

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

您正在将char *分配给int

lineCount = argv[3];

在这里

lineCount = argv[1];

以下是我得到的编译错误

[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

答案 2 :(得分:1)

你在错误的地方有一个右括号:

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

应该是:

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

然而,即使一旦修复,你的论证处理仍然不太正确。

your previous question中,head -n COUNT FILE不可能,这使得论证检查相当容易。

以下是您需要遵循的逻辑,即您允许“浮动”-n count部分:

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

它基本上首先捕获了两个参数版本。如果它是一个四参数版本,它会找出“-n”的位置,以便它可以智能地决定哪个参数是哪个值。

正如您所看到的那样,这并不是您所拥有的(您的代码在argv[1]中查找的行数是从不的情况)。你应该使用这样的东西作为指南:

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

一旦你提到它,就应该很容易为不同的情况编写代码。

你必须将我的伪代码转回C当然(使用strcmp而不是==作为字符串,并确保使用atoi/strtol来转换字符串linecount参数为整数),但这是你应该遵循的基本流程。

答案 3 :(得分:0)

您是否可以使用getopt()功能?在Linux上,getopt()函数将使用aplomb处理任一位置的-n选项(除非设置了POSIXLY_CORRECT环境变量)。它会让你的生活更轻松:

#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);
}

请注意,处理标准输入而不是文件很容易;当然,需要调整循环后的条件。您也可以轻松添加-?-h选项以获取帮助,依此类推。