我正在用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()
// ...
}