2015-04-15 136 views
-1

我正在C语言中编写一个字数程序,它模拟Linux/Unix中的wc命令。它编译得很好,但是当我尝试运行它时,它给了我一个分段错误消息。该方案应该是这样运行的:为什么我在C程序中出现分段错误?

./mywc -c test.txt 
1 2 12 test.txt /* 1 is number of lines, 2 is number of words, 12 is number of chars */ 

我的代码如下所示:

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

/* Enumerators */ 
enum { FALSE, TRUE }; 
enum { STDIN, STDOUT, STDERR }; 

#define BUFFER_SIZE 4096 
#define NAME_SIZE 12 
#define MAX_LINES 100000 

#define IN 1 
#define OUT 0 

/* Globals */ 
char *fileName = NULL; // File name 
char tmpName [NAME_SIZE]; 
int option = FALSE; // Return true if option is provided in command line 
int charOption = FALSE; // Return true if -c is provided in command line 
int wordOption = FALSE; // Return true if -w is provided in command line 
int lineOption = FALSE; // Return true if -l is provided in command line 
int standardInput = FALSE; 
int c = 0; // Character being scanned 
int nl = 0; // Number of lines in file 
int nw = 0; // Number of words in file 
int nc = 0; // Number of chars in file 
int lineStart[MAX_LINES]; 
int fileOffset = 0; 
int fd; 

parseCommandLine(int argc, char* argv[]) { 
    int i; 

    for (i = 1; i < argc; i++) { 
     if (argv[i][0] == '-') 
     processOptions(argv[i]); 
     else if (fileName == NULL) 
     fileName = argv[i]; 
     else 
     usageError(); 
    } 
    standardInput = (fileName == NULL); 
} 

processOptions(char* str) { 
    int j; 

    for (j = 1; str[j] != '\0'; j++) { 
     switch (str[j]) { 
     case 'c': 
      charOption = TRUE; 
      while (EOF != (str[j] = fgetc(fileName))) 
      nc++; 
      break; 
     case 'l': 
      charOption = TRUE; 
      while (c == fgetc(fileName) != 'Z') 
      if (c == '\n') 
       nl++; 
      break; 
     case 'w': 
      charOption = TRUE; 
      int state = 0; 
      while (c == fgetc(fileName) != 'Z') { 
      ++nc; 
      if (c == '\n') 
       nl++; 
      if (c == ' ' || c == '\n' || c == '\t') 
       state = 0; 
      else if (state == 0) { 
       state = 1; 
       ++nw; 
      } 
      } 
      break; 
     default: 
      usageError(); 
      break; 
     } 
    } 
} 

usageError() { 
    fprintf(stderr, "Usage: mywc -lwc [argv[1]]\n"); 
    exit(1); 
;} 

int main(int argc, char *argv[]) { 
    int i; 

    parseCommandLine(argc, argv); 
    processOptions(argv[1]); 
    fd = open(fileName, O_RDONLY); /* Open file */ 

    int flag[3] = {lineOption,wordOption,charOption}; 
    int stats[3] = {nl,nw,nc}; 

    if (!option) 
     printf("%d %d %d %s\n",nl,nw,nc,fileName); 
    else { 
     for (i = 0; i < 3; i++) { 
      if (flag[i]) 
       printf("%d ",stats[i]); 
     } 
     printf("%s\n",fileName); 
    } 
    return 0; 
} 

如果我能得到什么可能会造成这个错误的一些帮助,所以我的程序能正确运行,我会很感激。另外,我需要在我的程序摆脱一些警告的一些提示:

mywc.c: In function ‘parseCommandLine’: 
mywc.c:41:15: warning: assignment from incompatible pointer type 
     fileName = argv[i]; 
      ^
mywc.c: In function ‘main’: 
mywc.c:96:15: warning: passing argument 1 of ‘open’ from incompatible pointer type 
    fd = open(fileName, O_RDONLY); /* Open file */ 
      ^
In file included from mywc.c:3:0: 
/usr/include/fcntl.h:146:12: note: expected ‘const char *’ but argument is of type ‘struct FILE *’ 
extern int open (const char *__file, int __oflag, ...) __nonnull ((1)); 
      ^
mywc.c:102:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 5 has type ‘struct FILE *’ [-Wformat=] 
     printf("%d %d %d %s\n",nl,nw,nc,fileName); 
     ^
mywc.c:108:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘struct FILE *’ [-Wformat=] 
     printf("%s\n",fileName); 
     ^
+0

尝试“文件名=的argv [I]” – Deanie

+1

看不出来什么毛病出代码,但它似乎编译器认为'fileName'的类型是'struct FILE *',可能要检查是否在头中有多个声明或一些宏魔法。 –

+0

'while(c == fgetc(fileName)!='Z')'这是什么?你的意思是while((c = fgetc(fileName))!='Z')' – wildplasser

回答

1

首先,什么可能是在你的程序段错误的根源是事实,你不当调用fgetc与文件名称作为参数。您需要首先打开一个文件指针,然后通过fgetc读取一个字符:

FILE *fp = fopen(fileName); // open the file 

// ... 

int ch = fgetc(fp); // read a character, using fp instead of fileName 

这是什么原因造成的错误最多。

此外,所有的功能必须在C.返回类型如果你不想返回任何东西,你需要使用返回类型void

// | 
// V 
void parseCommandLine(int argc, char* argv[]) { 
    // ... 
} 

// | 
// V 
void processOptions(char* str) { 
    // ... 
} 

最后,你需要声明或者定义一个函数,然后才能使用它。因此,在您的程序中,您可以在parseCommandLine之内拨打processOptions,即使parseCommandLine发生在您的程序中的processOptions之前。在这种情况下,你需要把的processOptions声明上方某处在你的程序中的parseCommandLine定义:

void processOptions(char* str); // declaration of processOptions() 
           // notice that there's no function body 

void parseCommandLine(int argc, char* argv[]) { // definition of 
               // parseCommandLine() 
    // ... 
} 
相关问题