该程序基本上在文件中搜索字符串,然后根据提供的选项生成输出。
例如,在命令行上,
Cmatch-我你好你好世界.txt
即使我注释掉了所有 printf 语句,我也不断遇到分段错误。但是我是C的新手,在这里找不到任何不合适的指针。帮助?
#include <errno.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
int exit_status = EXIT_SUCCESS;
bool checkIfMatch(char *string, FILE *file) {
while (true) {
char buff[1024];
fgets(buff, 1024, file);
if (buff == NULL)
break;
if (strcmp(string, strstr(buff, string)) == 0)
return true;
}
return false;
}
bool checkIfMatchIgnoreCase(char *string, FILE *file){
while (true) {
char buff[1024];
fgets(buff, 1024, file);
if (buff == NULL)
break;
if (strcasecmp(string, strstr(buff, string))== 0)
return true;
}
return false;
}
void printLines(char *string, FILE *file){
while (true) {
char buff[1024];
fgets(buff, 1024, file);
if (buff == NULL)
break;
if (strcmp(string, strstr(buff, string)) == 0)
printf("%s",buff);
}
}
void printLinesWithNumber(char *string, FILE *file){
int ln;
for(ln=1;;ln++) {
char buff[1024];
fgets(buff, 1024, file);
if (buff == NULL)
break;
if (strcmp(string, strstr(buff, string)) == 0)
printf("%d: %s",ln,buff);
}
}
typedef struct options {
bool ignore_case;
bool filenames_only;
bool number_lines;
} options;
void scan_options(int argc, char **argv, options *opts) {
opts->ignore_case = false;
opts->filenames_only = false;
opts->number_lines = false;
opterr = false;
for (;;) {
int opt = getopt(argc, argv, "iln");
if (opt == EOF)
break;
switch (opt) {
case 'i':
opts->ignore_case = true;
break;
case 'l':
opts->filenames_only = true;
break;
case 'n':
opts->number_lines = true;
break;
default:
exit_status = EXIT_FAILURE;
fflush(NULL);
fprintf(stderr, "%s: -%c: invalid optionn",
"cmatch.c", optopt);
break;
}
}
}
int main(int argc, char **argv) {
options opts;
scan_options(argc, argv, &opts);
char *stringToMatch = argv[optind];
int i;
for(i=1;i<=argc-optind-1;i++){
bool matched;
FILE *file=fopen(argv[optind+i],"r");
if(opts.ignore_case) matched=checkIfMatch(stringToMatch, file);
else matched=checkIfMatchIgnoreCase(stringToMatch, file);
if(matched){
if(opts.filenames_only) printf("%sn",argv[optind+i]);
if(opts.number_lines) printLinesWithNumber(stringToMatch, file);
else printLines(stringToMatch,file);
}
}
return exit_status;
}
char *buff = fgets(buff, 1024, file); ^^^ ^^^
您需要使用已分配的内存调用fgets
。像这样:
char buff[1024];
fgets(buff, sizeof buff, file);
你从不检查fopen()
是否真的有效。
FILE *file=fopen(...);
if (NULL != f) { /* If the file was actually opened */
/* Do the work */
}
另外,你真的有一个名为 argv[optind+i]
的文件吗?也许你的意思是省略引号:
fopen(argv[optind+i],"r");
此外,看起来您需要在连续调用fgets()
http://www.cplusplus.com/reference/cstdio/fseek/之前使用 fseek()
或 rewind()
。
最后,从文件读取速度很慢。您实际上应该在一个地方读取一次文件,然后重用内存中的内容。
好的,您已经解决了文件问题。现在使用 gdb
,我发现您的第一个分段错误发生在 strcmp()
的第 18 行,因为如果在buff
中找不到序列strstr()
则返回NULL
:
if (strcmp(string, strstr(buff, string)) == 0)
return true;
您需要将strstr()
移出参数以strcmp()
并检查NULL
,然后再将结果传递给 strcmp()
。 http://www.cplusplus.com/reference/cstring/strstr/