为什么我在写入文件时神秘地发生段错误?

问题描述:

我希望我能提供更多信息,但我真的不知道这里发生了什么。此代码根据用户参数打开文件以进行appension或覆盖(默认情况下为appension)。它可以达到用户输入的fgets,然后只要输入了输入,它就会进行段错误并转储核心。这就奇怪了,因为之前我实现了论点(即这只是./a.out文件),它工作得很好,所以我想它是与有关参数的新东西......为什么我在写入文件时神秘地发生段错误?

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

int printhelp(void); 

int main(int argc, char *argv[]) 
{ 
    char input[256]; 
    int loopstat = 0; 
    FILE *inputfile; 

    if (argc < 2) /* Check argc for minimum 2 arguments (i.e. cw FILE) */ 
    { 
    printf("ca: missing file operand\n"); 
    return 0; 
    } 
    else if (argc > 2) /* Check argc for more than 2 arguments (i.e. cw -o FILE) */ 
    { 
    if (strncmp(argv[1], "-", 1) == 0) /* if first argument begins with "-", it must be an option, so descend into option checking */ 
    { 
     if (strcmp(argv[1], "-a") == 0) /* If -a option is given, open for appending */ 
     { 
     FILE *inputfile = fopen(argv[2], "a"); 
     } 
     else if (strcmp(argv[1], "-o") == 0) /* If -o option is given, open for overwriting */ 
     { 
     FILE *inputfile = fopen(argv[2], "w"); 
     } 
     else if (strcmp(argv[1], "--help") == 0) /* If --help option is given, print help and quit */ 
     { 
     printhelp(); 
     return 0; 
     } 
     else 
     { 
     printf("cw: invalid option\n"); /* If invalid option is given, print the fact and quit*/ 
     return 0; 
     } 
    } 
    } 
    else /* if argc is equal to 2 (i.e. "cw FILE" or "cw -o")...*/ 
    { 
    if (strncmp(argv[1], "-", 1) == 0) /* Check if user has specified an option but no file (i.e. "cw -o") */ 
    { 
     printf("cw: missing file operand\n"); /* If they have, print that no file is spec'd and quit */ 
     return 0; 
    } 
    else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */ 
    { 
     FILE *inputfile = fopen(argv[2], "a"); 
    } 
    } 

    /* Writing loop */ 
    printf("Enter input...\n"); 
    while (loopstat == 0) /* Get user input and write to file until they give exit command */ 
    { 
    fgets(input, 256, stdin); /* Get user input */ 

    if (strcmp(input, ":x\n") == 0) /* If input == exit command, quit */ 
    { 
     printf("co: exit received, terminating...\n"); 
     loopstat++; 
    } 
    else /* Write to file */ 
    { 
     fprintf(inputfile, "%s", input); 
    } 
    } 
    fclose(inputfile); 
} 

int printhelp(void) /* Print help on --help command */ 
{ 
    printf(
     "Usage: ca FILE\nContinuously append input to the FILE\nca does not currently support multiple file appension.\nReport bugs to [email protected]\n"); 
    return 0; 
} 

附:对不起,如果我搞砸了缩进,这真是令人困惑,必须在这个代码中的所有内容之前添加四个空格。

+0

顺便说一句,你应该使用'getoptlong',而不是自己解析。 – Linuxios

+0

@Linuxios,我一直在阅读,是基本上处理选项,而不必diy? – wobbataco

+0

为避免将来出现类似问题,请在命令行选项中添加-Wall,-Wextra和-Werror以启用大量警告并将警告视为错误。 – NovaDenizen

在这里,你是你的阴影变量:

else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */ 
{ 
    FILE *inputfile = fopen(argv[2], "a"); 
} 

应该

else /* If not, it's a legit file with no other arguments (e.g. "cw FILE") so open it in append mode by default */ 
{ 
    inputfile = fopen(argv[2], "a"); 
} 

你有这样几个实例,所以删除声明那里。

+0

oooh,所以你只需要在第一个声明中加上“int”,“char”,“FILE”等变量和前缀?抱歉打扰你,我不知道。非常感谢你! – wobbataco

+0

当你在变量的前面写入类型时,这意味着创建了一个X类型的新变量。通常你会得到一个编译器错误,因为你不能多次使用相同的名字,但是由于你使用了花括号,每个新变量都是一个单独的新实例,并且可以有不同的值。新实例只在当前的大括号内可见,大括号外的代码将看到它自己的副本。 – Devolus

+0

顺便说一句:如果你接受这个答案,那将会很好。我明白了,Aaaah, – Devolus

几次声明标识符inputfile,但每次都不会是同一个对象。

请参阅本程序的行为,例如(从Wikipedia):

#include <stdio.h> 

int main(void) 
{ 
    char x = 'm'; 

    printf("%c\n", x); 

    { 
     printf("%c\n", x); 
     char x = 'b'; 
     printf("%c\n", x); 
    } 

    printf("%c\n", x); 
} 

您必须声明inputfile只有一次,然后在if语句分配给它。

FILE *inputfile; 

if (/* ... */) 
    inputfile = /* ... */ 
else if (/* ... */) 
    inputfile = /* ... */ 
else 
    inputfile = /* ... */ 

int main(int argc, char *argv[]) 
{ 
    char input[256]; 
    int loopstat = 0; 
    FILE *inputfile; 

,那么你必须:

if (strcmp(argv[1], "-a") == 0) 
    { 
     FILE *inputfile = fopen(argv[2], "a"); 
    } 

你不应该重新声明一个新的对象inputfile而是重用你inputfile在你的函数的顶部声明。

例子:

inputfile = fopen(argv[2], "a"); 

的问题是存在的:

FILE *inputfile; 
.... 
if (strcmp(argv[1], "-a") == 0)    
{ 
    FILE *inputfile = fopen(argv[2], "a"); 
} 

通过写这样你是隐藏变量inputfile从编译器。因此,在开始定义的变量保持未初始化。所以,现在

if (strcmp(argv[1], "-a") == 0)   
{ 
    inputfile = fopen(argv[2], "a"); 
} 

您将使用在函数的顶部定义的变量:

你应该写它下面的方式。

您应该阅读有关variable scope