我正在开发一个程序,该程序从作为参数传递的输入文件中读取一些路径,然后递归读取或不读取其中包含的路径,并将其保存到结构中。输入文件如下:
C:\Users\Utente\Desktop\prova r
C:\Users\Utente\Desktop\find\try.txt
C:\Users\Utente\Desktop\find\try1.txt
最后的“ r”告诉程序递归读取此目录,打开所有子目录。
我的程序是这样的:
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include<dirent.h>
struct fileList{ //the structure that will contain the path list
char *path;
char *directory;
struct fileList *next;
};
struct lineList{ //structure with all the line of the input file
char *line;
struct lineList *next;
};
typedef struct lineList llist;
typedef struct fileList fList;
void listFilesRecursively(char *path,char *recursive,int a);
char * getLineOfAnySize(FILE* fp,size_t typicalSize,int *endOfLineDetected,size_t *nrOfCharRead);
int endOfLineDetected = 0; //used the getLineOfAnySize method
size_t nrOfCharRead = 0; //used the getLineOfAnySize method
char *line1; //will store the line of the input file
char *rec; //will store the r that indicates if a file should be read recursively
char *var = NULL; //used to do some check below
int i = 0;
FILE *fInput = NULL;
fList *list = NULL;
fList *listHead = NULL;
fList *listTail = NULL;
llist *head = NULL;
llist *tail = NULL;
llist *curr = NULL;
int main(int argc,char * argv[]){
fInput = fopen(argv[1],"r"); //the file that contains all the paths,line by line.
if(fInput == NULL){
fprintf(stderr,"Cannot open %s,exiting. . .\n",argv[1]);
exit(1);
}
while(!endOfLineDetected){
line1 = getLineOfAnySize(fInput,128,&endOfLineDetected,&nrOfCharRead); //reading line
//saving into the lineList structure
llist *app = malloc (sizeof(llist));
app->line = line1;
app->next = NULL;
if(head == NULL){
tail = head = app;
}else{
tail = tail->next = app;
}
}
fclose(fInput);
curr = head; //take the pointer back to the head
while(curr != NULL){ //traverse the lineList structure
rec = strrchr(curr->line,' ');
if(rec != NULL) {
rec++; //saving into rec the "r" if present
i = 0;
//using this loop the save into line only the path,eliminating the "r" at the end.
while(1){
if(curr->line[i] == ' '){
curr->line[i] = '\0';
break;
}
i++;
}
}
//If there's a dot means that it is a file and we pass to the function a zero to indicates this
if(strrchr(curr->line,'.') != NULL){
listFilesRecursively(curr->line,rec,0);
}else{
//if there isn't a dot means that it is a directory and we pass 1.
listFilesRecursively(curr->line,1);
}
curr = curr->next; //pointing to the next line.
}
list = listHead; //pointer back to the head of fileList
//traversing the fileList structure to print all files and theirs directories
while(list != NULL){
printf("path printing: %s\n",list->path);
printf("dir printing: %s\n",list->directory);
list = list->next;
}
return 0;
}
void listFilesRecursively(char *basePath,int a){
struct dirent *dp;
DIR *dir;
if(a == 0){ //which means is a file
char *str = malloc(sizeof(char)*strlen(basePath));
fList *n = malloc (sizeof(fList));
n->path = basePath; //we save the path of file into a structure
strcpy(str,basePath);
//use this loop the obtain the directory,elimating all the character after the last "\"
for(int i = strlen(str); i>0; i--){
if(str[i] == '\\'){
str[i] = '\0';
i = 0;
}
}
n->directory = str; //save the directory
n->next = NULL;
//creating the structure
if(listHead == NULL){
listTail = listHead = n;
}else{
listTail = listTail->next = n;
}
printf("path structure: %s\r\n",listTail->path);
printf("dirr structure: %s\r\n",listTail->directory);
}else{ //if it's a directory
char *path = malloc(sizeof(char)*1000); //will store the path
dir = opendir(basePath); //open the directory
// Unable to open directory stream
if (!dir)
return;
while ((dp = readdir(dir)) != NULL){ //we traverse the directory
if (strcmp(dp->d_name,".") != 0 && strcmp(dp->d_name,"..") != 0){
// Construct new path from our base path
strcpy(path,basePath);
strcat(path,"\\");
strcat(path,dp->d_name); //adding the file name to the path
var = strrchr(path,'.'); //if there's a dot,var will not be NULL,so we enter into the if
if(var != NULL){ //i do this because i want to store into the structure only file and their directory.
fList *node = malloc (sizeof(fList));
node->path = path; //the file path
node->directory = basePath; //the directory path
node->next = NULL;
if(listHead == NULL){
listTail = listHead = node;
}else{
listTail = listTail->next = node;
}
printf("path structure: %s\r\n",listTail->path);
printf("dirr structure: %s\r\n",listTail->directory);
}
if(recursive == NULL){ //in case we don't need to read recursively
continue;
}
//if we passed a "r" to the function,the program start read recursively
// all the subdirectories
if(strcmp(recursive,"r") == 0){
listFilesRecursively(path,"r",1);
}
}
}
closedir(dir);
}
}
//method used to read line by line a file
char * getLineOfAnySize(FILE* fp,size_t *nrOfCharRead){
char *line; // buffer for our string
int ch; // we will read line character by character
size_t len = 0; // number of characters read (character counter)
size_t linesize = typicalSize; // initial size of the buffer allocated for the line
*nrOfCharRead = 0;
if(!fp) return NULL; // protection
// allocating the buffer
line = realloc(NULL,sizeof(char)*linesize); // expected size of the line is pathHead to typicalSize
if (!line) return line; // protection,if we fail to allocate the memory we will return NULL
while (1) { // loop forever
ch = fgetc(fp); // getting character by character from file
if (ch == '\n') break; // end of line detected - breaking the loop
if( ch == EOF) {
*endOfLineDetected = 1;
break; // end of file detected - breaking the loop
}
line[len++] = ch; // store the character in the line buffer,increase character counter
if (len == linesize){ // we reached the end of line buffer (no more room)
linesize = linesize + 64; // we have to increase the line size
line = realloc(line,sizeof(char)*(linesize)); // line buffer has new size now
if (!line) return line; // if we fail to allocate memory we will return NULL
}
if( (len == 0) && *endOfLineDetected){ // empty file
*endOfLineDetected = 1;
break;
}
}
line[len++] ='\0'; // ending the string (notice there is no '\n' in the string)
*nrOfCharRead = len;
return line; // return the string
}
我不知道为什么,但是在创建新节点后立即使用的 printf 会打印正确的信息。相反,当我们遍历整个结构时,在 main 末尾的 printf 会以错误的顺序显示信息。输出如下:
path structure: C:\Users\Utente\Desktop\prova\AAAAA.doc
dirr structure: C:\Users\Utente\Desktop\prova
path structure: C:\Users\Utente\Desktop\prova\prova1\prova4\testo3.txt
dirr structure: C:\Users\Utente\Desktop\prova\prova1\prova4
path structure: C:\Users\Utente\Desktop\prova\prova1\testo2.txt
dirr structure: C:\Users\Utente\Desktop\prova\prova1
path structure: C:\Users\Utente\Desktop\prova\prova2\testo5.txt
dirr structure: C:\Users\Utente\Desktop\prova\prova2
path structure: C:\Users\Utente\Desktop\prova\testo1.txt
dirr structure: C:\Users\Utente\Desktop\prova
path structure: C:\Users\Utente\Desktop\find\try.txt
dirr structure: C:\Users\Utente\Desktop\find
path structure: C:\Users\Utente\Desktop\find\try1.txt
dirr structure: C:\Users\Utente\Desktop\find
path printing: C:\Users\Utente\Desktop\prova\testo1.txt
dir printing: C:\Users\Utente\Desktop\prova
path printing: C:\Users\Utente\Desktop\prova\prova1\prova4\testo3.txt
dir printing: C:\Users\Utente\Desktop\prova\prova1\testo2.txt
path printing: C:\Users\Utente\Desktop\prova\prova1\testo2.txt
dir printing: C:\Users\Utente\Desktop\prova\testo1.txt
path printing: C:\Users\Utente\Desktop\prova\prova2\testo5.txt
dir printing: C:\Users\Utente\Desktop\prova\testo1.txt
path printing: C:\Users\Utente\Desktop\prova\testo1.txt
dir printing: C:\Users\Utente\Desktop\prova
path printing: C:\Users\Utente\Desktop\find\try.txt
dir printing: C:\Users\Utente\Desktop\find
path printing: C:\Users\Utente\Desktop\find\try1.txt
dir printing: C:\Users\Utente\Desktop\find
感谢所有帮助我的人!