简体   繁体   English

读入文件并在c中创建一个双向链接列表

[英]Read in a file and Create a double linked list in c

So I'm new to C coding and I'm having trouble with creating a linked list with the following code. 因此,我是C编码的新手,无法使用以下代码创建链表。 The problem I've been having is that the fscanf changes the variables every time when it reads in something. 我一直遇到的问题是,fscanf每次读入某些内容时都会更改变量。 So my head pointer value keeps getting changed. 因此,我的头部指针值不断变化。 Is there a way to fix this? 有没有办法解决这个问题? Thank you! 谢谢!

After a few discussion, I've realized it's because the mnemonic in the struct is a pointer, so the mnemonic of head is going to change since it's just pointing at the pointer. 经过一些讨论,我意识到这是因为struct中的助记符是一个指针,因此head的助记符将发生变化,因为它只是指向指针。 Is there a way to fix this problem without changing the struct itself? 有没有一种方法可以解决此问题而不更改结构本身? (meaning leaving the mnemonic in struct Instr as a pointer) (意味着将助记符保留在struct Instr中作为指针)

void linkTypeInstr(struct InstrType *it, char *c, FILE *mfp){
    int count = 0;
    char type[2], mnemonic[11];
    uint32_t uid = 0, pretty = 0;
    struct Instr *head = NULL;
    struct Instr *ptr = NULL;
    /*read through the file in format*/
    while(fscanf(mfp, "%s %u %s %u ", type, &uid, mnemonic, &pretty) != NULL){
        if(head != NULL)
            printf("head: %s\n", head -> mnemonic);
        /*check if is the match type*/
        if(*type == *c){
            /*make a new struct instr for the item want to add*/
            struct Instr *temp = malloc(sizeof(struct Instr));
            memset(temp, 0, sizeof(struct Instr));
            temp -> uid = uid;
            temp -> pretty = pretty;
            temp -> mnemonic = mnemonic;
            temp -> next = NULL;
            temp -> prev = NULL;
            printf("temp: %s\n", temp -> mnemonic);
            printf("count: %d\n", count);
            /*check if list is empty, set ptr to head*/
            if(count == 0){
                head = temp;
                count++;
            }
            /*if list is not empty, find the place to put the item in alphabetical order*/
            else{
                ptr = head;
                printf("head: %s\n", head -> mnemonic);
                while(ptr != NULL){
                    /*if temp should come after ptr in the order*/
                    if(strcmp(ptr -> mnemonic, temp -> mnemonic) < 0){
                        if(ptr -> next == NULL){
                            ptr -> next = temp;
                            temp -> prev = ptr;
                            count++;
                            ptr = NULL;
                        }
                        else if(strcmp(temp -> mnemonic, ptr -> next -> mnemonic) < 0){
                            temp -> next = ptr -> next; 
                            ptr -> next -> prev = temp;
                            ptr -> next = temp;
                            temp -> prev = ptr;
                            count++;
                            ptr = NULL;
                        }
                        else 
                            /*if should be after ptr -> next*/
                            ptr = ptr -> next;
                    }
                    /*if temp should come before ptr in the order*/
                    else if(strcmp(temp -> mnemonic, ptr -> mnemonic) < 0){
                        if(ptr -> prev == NULL){
                            ptr -> prev = temp;
                            temp -> next = ptr;
                            head = temp;
                            count++;
                            ptr = NULL;
                        }
                        else if(strcmp(ptr -> prev -> mnemonic, temp -> mnemonic) < 0){
                            ptr -> prev -> next = temp;
                            temp -> prev = ptr -> prev;
                            ptr -> prev = temp;
                            temp -> next = ptr;
                            count++;
                            ptr = NULL;
                        }
                        else
                            /*if should be before ptr -> prev*/
                            ptr = ptr -> prev;
                    }
                }
            }
        }
    }
    it -> count = count;
    it -> head = head;
}


struct Instr {
        uint32_t uid; /* Unique identification bits */
        uint32_t pretty; /* The type of pretty print format this Instr is */
        char *mnemonic; /* The human readable mnemonic */
        struct Instr *next; /* Pointer for doubly linked list */
        struct Instr *prev; /* Pointer for doubly linked list */
};

struct InstrType {
        char type; /* Should be R, I, or J */
        size_t count; /* Length of Instr list */
        struct InstrType *next; /* Points to the next InstrType node */
        struct InstrType *prev; /* Points to the next InstrType node */
        struct Instr *head; /* Points to the first Instr node of this type */
};

The file im trying to read look something like this: 我试图读取的文件看起来像这样:

r 00000020 add 3
r 00000021 addu 3
r 00000022 sub 3
r 00000023 subu 3
r 00000018 mult 2
r 00000019 multu 2
r 0000001a div 1
r 0000001b divu 1
r 00000010 mfhi 0
r 00000011 mthi 0
r 00000012 mflo 0
r 00000013 mtlo 0
r 00000000 sll 8
r 00000002 srl 8
r 00000003 sra 8
r 00000004 sllv 3
r 00000006 srlv 3
r 00000007 srav 3
r 00000024 and 3
r 00000025 or 3
r 00000026 xor 3
r 00000027 nor 3
r 0000002a slt 3
r 0000002b sltu 3
r 00000008 jr 0
r 00000009 jalr 2
r 0000000c syscall 5
i 20000000 addi 2
i 24000000 addiu 2
i 3c000000 lui 2
i 28000000 slti 2
i 2c000000 sltiu 2
i 30000000 andi 2
i 34000000 ori 2
i 38000000 xori 2
i 80000000 lb 4
i 84000000 lh 4
i 88000000 lwl 4
i 8c000000 lw 4
i 90000000 lbu 4
i 98000000 lwr 4
i a0000000 sb 4
i a4000000 sh 4
i a8000000 swl 4

and the result when i run this always end up changing my head ptr to the new temp created: 而当我运行此命令时,结果总是最终将我的头部温度更改为创建的新温度:

temp: add
count: 0
head: addu
temp: addu
count: 1
head: addu
...

code calling the function looks like this: 调用该函数的代码如下所示:

int main(int argc, char *argv[]){
    int c;
    int iFlag = 0, oFlag = 0;
    char mFileName[256] = "instruction_mapping.txt";
    char oFileName[256];
    char iFileName[256];
    extern char *optarg;
    FILE *mfp, *ifp, *ofp;

    /*create three struct instrtype nodes*/
    struct InstrType *itR = malloc(sizeof(struct InstrType));
    struct InstrType *itI = malloc(sizeof(struct InstrType));
    struct InstrType *itJ = malloc(sizeof(struct InstrType));

    memset(itR, 0, sizeof(struct InstrType));
    memset(itI, 0, sizeof(struct InstrType));
    memset(itJ, 0, sizeof(struct InstrType));

    /*link the struct instrtype together*/
    if(itR != NULL && itI != NULL && itJ != NULL){
        itR -> prev = NULL;
        itR -> next = itI;
        itI -> prev = itR;
        itI -> next = itJ;
        itJ -> prev = itI;
        itJ -> next = NULL;
    }

    /*set up instrtypes*/
    itR -> type = 'R';
    itI -> type = 'I';
    itJ -> type = 'J';

    /* parse arguments */
    while ((c = getopt(argc, argv, "m:i:o:h")) != -1){
        switch(c){
            case 'h':
                USAGE(argv[0]);
                return EXIT_SUCCESS;
            case 'm':
                strcpy(mFileName, optarg);
                break;
            case 'i':
                iFlag = 1;
                strcpy(iFileName, optarg);
                break;
            case 'o':
                oFlag = 1;
                strcpy(oFileName, optarg);
                break;
            default:
                USAGE(argv[0]);
                return EXIT_FAILURE;
        }
    }

    /*check -i and -o must be in argv*/
    if(iFlag == 1 && oFlag == 1){
        mfp = fopen(mFileName, "r");
        if(mfp == NULL){
            printf("Cannot open instruction mapping file\n");
            EXIT_FAILURE;
        }
        printf("mapping file: %s\n", mFileName);
        ifp = fopen(iFileName, "r");
        if(ifp == NULL){
            printf("Cannot open input file\n");
            EXIT_FAILURE;
        }
        printf("input file: %s\n", iFileName);
        ofp = fopen(oFileName, "w");
        if(ofp == NULL){
            printf("Error creating or writing file\n");
            EXIT_FAILURE;
        }
        printf("output file: %s\n", oFileName);

        /* make linked lists of instr in R, I, J instrtype */
        linkTypeInstr(itR, "r", mfp);
        linkTypeInstr(itI, "i", mfp);
        linkTypeInstr(itJ, "j", mfp);


        if(mfp != NULL)
            fclose(mfp);
        if(ifp != NULL)
            fclose(ifp);
        if(ofp != NULL)
            fclose(ofp);
    }   
    else{
        printf("Must have both input and output files\n");
        return EXIT_FAILURE;
    }
    free(itR);
    free(itI);
    free(itJ);
    return EXIT_SUCCESS;
}

Your problem is this line: 您的问题是这一行:

temp -> mnemonic = mnemonic;

The fact that temp->mnemonic is a pointer means that it will allways point to the same 11 chars of the mnemonic array. temp-> mnemonic是指针的事实意味着它始终指向助记符数组的相同11个字符。 As head is assigned from temp also head->mnemonic will point to the same 11 chars which will be overwritten at the next call to fscanf. 当从temp分配head时,head-> mnemonic也将指向相同的11个字符,在下一次调用fscanf时将被覆盖。

The solution is to change your 解决方案是更改您的

struct Instr { uint32_t uid; /* Unique identification bits */ uint32_t pretty; /* The type of pretty print format this Instr is */ char *mnemonic; /* The human readable mnemonic */ struct Instr *next; /* Pointer for doubly linked list */ struct Instr *prev; /* Pointer for doubly linked list */ };

to

struct Instr { uint32_t uid; /* Unique identification bits */ uint32_t pretty; /* The type of pretty print format this Instr is */ char mnemonic[11]; /* The human readable mnemonic */ struct Instr *next; /* Pointer for doubly linked list */ struct Instr *prev; /* Pointer for doubly linked list */ };

and instead assign it with strncpy: 而是给它分配strncpy:

strncpy(temp -> mnemonic, mnemonic, 11);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM