该程序基本上在文件中搜索字符串,然后根据提供的选项生成输出。
例如,在命令行上,
cmatch -i hello helloworld.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 option\n",
"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("%s\n",argv[optind+i]);
if(opts.number_lines) printLinesWithNumber(stringToMatch, file);
else printLines(stringToMatch,file);
}
}
return exit_status;
}
答案 0 :(得分:7)
char *buff = fgets(buff, 1024, file); ^^^ ^^^
您需要使用已分配的内存调用fgets
。类似的东西:
char buff[1024];
fgets(buff, sizeof buff, file);
答案 1 :(得分:0)
您永远不会检查fopen()
是否确实有效。
FILE *file=fopen(...);
if (NULL != f) { /* If the file was actually opened */
/* Do the work */
}
另外,你真的有一个名为argv[optind+i]
的文件吗?也许你打算省略引号:
fopen(argv[optind+i],"r");
此外,在连续调用fseek()
http://www.cplusplus.com/reference/cstdio/fseek/之前,您似乎需要使用rewind()
或fgets()
。
最后,从文件读取速度很慢。你真的应该只在一个的地方读取文件一次,然后重复使用内存中的文件。
好的,你已经解决了文件问题。现在使用gdb
,我发现您的第一个细分错误发生在strcmp()
的第18行,因为如果在strstr()
中找不到序列,则NULL
会返回buff
:
if (strcmp(string, strstr(buff, string)) == 0)
return true;
您需要将strstr()
从参数中移出strcmp()
并检查NULL
,然后再将结果传递给strcmp()
。 http://www.cplusplus.com/reference/cstring/strstr/