将数据保存到C中的链接列表时出现问题

我正在开发一个程序,该程序从作为参数传递的输入文件中读取一些路径,然后递归读取或不读取其中包含的路径,并将其保存到结构中。输入文件如下:

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

感谢所有帮助我的人!

w12240cn 回答:将数据保存到C中的链接列表时出现问题

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3085683.html

大家都在问