问题:显示指定目录及其后代目录下所有.c文件中出现指定字符串的行号
算法:
分为两个文件编写 :
display_string_lineno.c , Read_line.c
分为三个函数编写 :
void display_lineno(char* dirname,const char *pstr);
void print_string_line_no(char *path,char *file,const char *pstr);
char *Read_line(FILE* fp,int *plinelen);
代码:
display_string_lineno.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h>
#include <dirent.h>
// 在.c文件中找和打印pstr
void display_lineno(char* dirname,const char *pstr);
// 找出文件夹中的.c文件 并传入display_lineno()函数中
void print_string_line_no(char *path,char *file,const char *pstr);
// 读一整行
char *Read_line(FILE* fp,int *plinelen);
int main(int argc,char* argv[]){
if(argc < 2){
printf("The argument is too few\n");
return 1;
}
display_lineno(argv[1],"stdio");
return 0;
}
void print_string_line_no(char *path,char *file,const char *pstr){
int len = 0;
char *pathfile = NULL;
FILE* fp = NULL;
char *pline = NULL;
int lineno = 0;
len = strlen(path) + strlen(file) + 1 + 1;
pathfile = (char*)malloc(len); // 动态分配
if(pathfile == NULL){
printf("Malloc for %d-char failed\n",len);
return ;
}
memset(pathfile,0,len);
// 构造递归文件夹的路径信息
strcpy(pathfile,path);
strcat(pathfile,"/");
strcat(pathfile,file);
fp = fopen(pathfile,"r");
if(fp == NULL){
printf("r-open %s failed\n",pathfile);
return ;
}
pline = Read_line(fp,NULL); // 读一整行
while(pline != NULL){
lineno++; // 行号+1
if(strstr(pline,pstr) != NULL) printf("%s:%d\n",pathfile,lineno); // 找到了就打印输出
free(pline); // 在读下一行之前free掉空间
pline = NULL;
pline = Read_line(fp,NULL); // 继续读下一行
}
fclose(fp);
fp = NULL;
}
void display_lineno(char* dirname,const char *pstr){
DIR *pd = NULL;
struct dirent *pitem = NULL;
int len = 0;
char* p = NULL;
char *psubdir = NULL;
pd = opendir(dirname);
pitem = readdir(pd);
while(pitem != NULL){
if(pitem->d_type == DT_REG){ // 是否为普通文件
len = strlen(pitem->d_name);
if(len >= 2){
p = pitem->d_name + len - 1 - 1;
if(strcmp(p,".c") == 0) // 判断是否是.c文件
print_string_line_no(dirname,pitem->d_name,pstr);
}
}
else if(pitem->d_type == DT_DIR){
if(strcmp(pitem->d_name,".") != 0 && strcmp(pitem->d_name,"..") != 0){
len = strlen(dirname) + strlen(pitem->d_name) + 1 + 1;
psubdir = (char*)malloc(len);// 动态分配
if(psubdir == NULL){
printf("Malloc %d-char failed\n",len);
return ;
}
memset(psubdir,0,len);
// 构造递归文件夹的路径信息
strcpy(psubdir,dirname);
strcat(psubdir,"/");
strcat(psubdir,pitem->d_name);
display_lineno(psubdir,pstr);
free(psubdir);// 释放空间避免内存泄漏
psubdir = NULL;
}
}
pitem = readdir(pd);
}
closedir(pd);
pd = NULL;
}
Read_line.c (读一整行)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *Read_line(FILE* fp,int *plinelen){
int curloc = 0;
int cnt = 0;
int ret = 0;
char *pout = NULL;
// 1.获取位置指示器当前指示位置----起始位置
curloc = ftell(fp);
// 2.统计指示器当前指示位置到行尾的字符个数(包括\n)
ret = fgetc(fp);
while(ret != '\n' && ret >= 0){
cnt++;
ret = fgetc(fp);
}
// 3.有效字符的个数(不含行尾标记)填入plinelen指向空间里
if(plinelen != NULL) *plinelen = cnt;
if(cnt <= 0) return 0;
if(ret == '\n') cnt++; // 将\n计算在内
// 4.动态分配空间
cnt++; // 留出最后\0的位置
pout = (char*)malloc(sizeof(char)*cnt);
if(pout == NULL){
printf("Malloc for %d-char failed.\n",cnt);
return NULL;
}
memset(pout,0,cnt);
// 5.将位置指示器定位到起始位置
fseek(fp,curloc,0);
// 6.调用fgets
fgets(pout,cnt,fp);
// 7.判断最后一个字符如果是'\n',将其替换成'\0'
if(*(pout + cnt - 2) == '\n') *(pout + cnt - 2) = '\0';
// 8.返回动态空间的地址
return pout;
}
输出:
省略 gcc 过程