为什么我的 C 程序出现分段错误



我正在用C语言开发字数统计程序。它模拟Linux/Unix中的wc命令。它编译得很好,但是当我尝试运行它时,它给了我一个分段错误消息。该程序应该像这样运行:

./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] != ''; 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 %sn",nl,nw,nc,fileName);
    else {
        for (i = 0; i < 3; i++) {
            if (flag[i])
                printf("%d ",stats[i]);
        }
        printf("%sn",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 %sn",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("%sn",fileName);
         ^

首先,程序中分段错误的根源可能是您不正确地调用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之前。在这种情况下,您需要在程序中parseCommandLine定义上方放置一个processOptions声明:

void processOptions(char* str); // declaration of processOptions()
                                // notice that there's no function body
void parseCommandLine(int argc, char* argv[]) {  // definition of
                                                 // parseCommandLine()
  // ...
}

相关内容

  • 没有找到相关文章

最新更新