C:如何动态分配& char数组的空闲内存?

时间:2016-02-08 02:36:36

标签: c arrays char free

如何为char数组动态分配和释放内存?

我的malloc下面不起作用。抛出的错误是预期的&#39 ;;'在声明清单的末尾。'

char *string_buffer = malloc(128 * sizeof(char));

以下是我尝试释放string_buffer [128]字符数组:

void rmv(struct tree_node *cwd) {
    struct list_node *child = cwd -> first_child;
    free(string = child -> tree -> string_buffer);

    printf("String memory free successful\n");
    //free(cwd -> first_child -> tree);
    //free(cwd -> first_child);
}

其余代码:

Shell命令:

cd =当前目录

ls = list

mkdir = make目录

rmdir =删除目录(未实现 - 需要释放内存)

#include <stdio.h> /* For fgets(), fprintf() and printf() */
#include <stdlib.h> /* For EXIT_FAILURE */
#include <ctype.h> /* For isspace() */
#include <string.h>
#include <stddef.h>

// COMMANDS
char exitProgram[] = "exit";
char listDirectory[] = "ls";
char commandDirectory[] = "cd";
char makeDirectory[] = "mkdir";
char removeDirectory[] = "rmdir";

// holds a string buffer of length 128
// a pointer to its parent
// a pointer to the first node of the list of children
typedef struct tree_node {
    char string_buffer[128];
    struct tree_node *parent;
    struct list_node *first_child; // first node of list of children?
} tree_node;

// pointer to tree node
// pointer to next item in the list
typedef struct list_node {
    struct tree_node *tree;
    struct list_node *next;
} list_node;

// allocates the right amount of space for a tree node
// sets the pointers to NULL
// initialises the string buffer with the given name
// returns a pointer to the tree node
struct tree_node *make_tree_node(char *name) {
    tree_node *instance = malloc(sizeof(*instance));
    instance -> parent = NULL;
    instance -> first_child = NULL;
    strcpy(instance -> string_buffer, name);
    return instance;
}

// allocates a new list node
// assigns the fields for the tree node it references and the next list node
// returns a pointer to the new list node
struct list_node *make_list_node(struct tree_node *v, struct list_node *next) {
    list_node *instance = malloc(sizeof(*instance));
    instance -> tree = v;
    instance -> next = next;
    return instance;
}

// checks whether directory named arg already exists in current working directory
// creates the directory if it does not exist
// if arg is NULL, the function should print an error message
void do_mkdir(struct tree_node *cwd, char *arg) {

    //printf("Making Directory with name %s\n", arg);

    if (NULL == arg || !strcmp(arg, "")) {
        printf("Please specify directory name that is not NULL: mkdir directoryName\n");
    }
    else {
        // check if directory exists
        struct list_node *subDir = cwd->first_child;

        while (subDir != NULL) {
            if (strcmp(subDir -> tree -> string_buffer, arg) == 0) {
                printf("Directory with that name exists. Please provide another name.\n");
                return;
            }
            subDir = subDir -> next;
        }

        // adding new directory
        struct tree_node *newSubDir = make_tree_node(arg);
        newSubDir -> parent = cwd;
        struct list_node *newListNode = make_list_node(newSubDir, NULL);

        // putting new node in alphabetical order
        struct list_node *prev = NULL;
        if (subDir == NULL) {
            newListNode -> next = cwd -> first_child;
            cwd -> first_child = newListNode;
        } else {
            while (subDir != NULL) {
                // TODO: use case insensitive compare
                if (strcmp(arg, subDir -> tree -> string_buffer) > 0) {
                    // inserting in front
                    newListNode -> next = subDir -> next;
                    prev->next = newListNode;
                    break;
                }
                prev = subDir;
                subDir = subDir -> next;
            }
            if (subDir == NULL) {
                subDir->next = newListNode;
            }
        }
    }
}

// prints all children of the directory cwd (not recursively)
void do_ls(struct tree_node *cwd) {
    printf("Listing Directories...\n");
    struct list_node *subDir = cwd -> first_child;
    while (subDir != NULL) {
        printf("%s\n", subDir ->tree -> string_buffer);
        subDir = subDir->next;
    }
}

// *checks whether cwd has a subdirectory named arg
// *if yes, the function returns the corresponding tree node (and become new working directory)
// *if no, prints an error message
// *handle cd and cd ..
struct tree_node *do_cd(struct tree_node *cwd, struct tree_node *root, char *arg) {

    // initialising subDir to cwd's first child
    struct list_node *subDir = cwd -> first_child;

    // initialising parDir to cwd's parent
    struct tree_node *parDir = cwd -> parent;

    if (parDir != NULL) { // root directory does not have a parent directory
        if (strcmp(arg, "..") == 0) {
            cwd = parDir;
            printf("Returning to parent directory.\n");
            return cwd;
        }
    }
    // checks if user input argument is "."
    if (strcmp(arg, ".") == 0) {
        return cwd;
    }

    // checks if user input argument is NULL or ""
    if (NULL == arg || !strcmp(arg, "")) {
        printf("Returning to root directory.\n");
        return root;
    }

    // checks if cwd has a subdirectory named arg
    while (subDir != NULL) {
        if (strcmp(subDir -> tree -> string_buffer, arg) == 0) {
            printf("Subdirectory exists!\n");
            cwd = subDir-> tree;
            printf("Making & entering subdirectory: %s\n", arg);
            return cwd;
        }
        subDir = subDir-> next;
    }
    printf("Directory does not exist!\n");
    return cwd;
}

// *prints the prompt (e.g. /bar/baz/ >) in every iteration of the main loop
// *show all directories on the path in correct order
void show_prompt(struct tree_node *cwd) {
    struct tree_node *originalDir = cwd;
    if (cwd -> parent != NULL) {
        show_prompt(cwd -> parent);
        printf("/%s", cwd -> string_buffer);
    }
    cwd = originalDir;
}

// *removes a node child from its parent node dir
// *take care to correctly support corner cases like the child being the only one
// *all memory occupied by the child should be freed
void remove_child(struct tree_node *cwd, struct tree_node *child) {
    child = cwd -> first_child -> tree;
    cwd = child -> parent;
    if (cwd -> first_child -> tree == NULL) {
        printf("Subdirectory is not empty!\n");
    }
    else if (cwd -> first_child != NULL) {
        free(child);
    }
}

void rmv(struct tree_node *cwd) {
    struct list_node *child = cwd -> first_child;
    printf("%s\n", child -> tree -> string_buffer);
    strcpy(child -> tree -> string_buffer, "");
    printf("String memory free successful\n");
    free(child -> tree -> string_buffer);
    //free(cwd -> first_child -> tree);
    //free(cwd -> first_child);
}

void rmv2(struct tree_node *cwd) {
    struct tree_node *child = cwd -> first_child -> tree;
    free(child);
}

void rmv3(struct tree_node *cwd) {
    struct tree_node *child = cwd -> first_child -> tree;
    cwd = child -> parent;
    if (strcmp(cwd -> first_child -> tree -> string_buffer, "\0") == 0) {
        printf("Subdirectory is not empty!\n");
    }
    else if (cwd -> first_child != NULL) {
        free(cwd -> first_child -> tree -> string_buffer);
        free(cwd -> first_child -> tree);
        free(cwd -> first_child);
    }
}

// implement rmdir (follow same pattern as previous exercise)
// *if the specified directory is not empty, rmdir should fail with an error message
void do_rmdir(struct tree_node *cwd, char *arg) {

    struct list_node *subDir = cwd->first_child;

    // checks if user input argument is NULL or ""
    if (NULL == arg || !strcmp(arg, "")) {
        printf("Please specify a directory that is not NULL: rmdir directoryName.\n");
    }

    while(subDir != NULL) {
        if (strcmp(subDir -> tree -> string_buffer, arg) != 0) {
            printf("Directory does not exist!\n");
        }
        subDir = subDir -> next;
    }

    if (strcmp(subDir -> tree -> string_buffer, arg) == 0) {

        if (subDir -> tree == NULL) {
            free(subDir);
        }
        while (subDir != NULL) {
            if (strcmp(subDir -> tree -> string_buffer, arg) == 0) {
                printf("Directory with that name exists. Please provide another name.\n");
                return;
            }
            subDir = subDir -> next;
        }
    } else {
        printf("Directory does not exist!\n");
    }
}

int main(void) {

    char directoryName[129] = "";

    printf("\nProgram Start... \n\n");

    // getting user input string
    // and capturing argument from user input
    char inputString[129];
    char delimiter[] = " ";
    char *line;
    char *arg;
    struct tree_node *root = make_tree_node("root\0");
    struct tree_node *cwd = root;

    printf("/ >");

    while (fgets(inputString, 128, stdin)) {
        inputString[strlen(inputString) - 1] = '\0';

        // gets argument and stores as arg
        line = malloc(strlen(inputString) + 1);
        strcpy(line, inputString);
        arg = strsep(&line, delimiter);
        arg = strsep(&line, delimiter);
        //printf("your argument: %s\n", arg);

        if(strncmp(inputString, "exit", 4) == 0) {
            printf("Breaking...\n");
            break;
        }

        //////////////////////////////// HANDLING LS ////////////////////////////

        else if(strncmp(inputString, "ls ", 3) == 0) {
            printf("The ls command should be used without arguments.\n");
        }

        else if(strncmp(inputString, "ls", 2) == 0) {
            do_ls(cwd);
            show_prompt(cwd);
            printf("/ >");
        }

        /////////////////////////// HANDING CD (EXTRA SAFE) //////////////////////////////
        else if(strncmp(inputString, "cd ..", 5) == 0) {
            cwd = do_cd(cwd, root, arg);
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "cd .", 4) == 0) {
            cwd = do_cd(cwd, root, arg);
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "cd ", 3) == 0) {
            cwd = do_cd(cwd, root, arg);
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "cd", 2) == 0) {
            cwd = root;
            printf("Returning to root directory.\n");
            show_prompt(cwd);
            printf("/ >");
        }

        ////////////////////////////// HANDLING MKDIR /////////////////////////////////////
        else if(strncmp(inputString, "mkdir  ", 7) == 0) {
            printf("Please specify directory name that is not NULL: mkdir directoryName\n");
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "mkdir ", 6) == 0) {
            do_mkdir(cwd, arg);
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "mkdir", 5) == 0) {
            printf("Please specify directory name: mkdir directoryName\n");
            show_prompt(cwd);
            printf("/ >");
        }

        ////////////////////////////// HANDLING RMDIR /////////////////////////////////////
        else if(strncmp(inputString, "rmdir  ", 7) == 0) {
            printf("Please specify directory name that is not NULL: rmdir directoryName\n");
            show_prompt(cwd);
            printf("/ >");
        }
        else if(strncmp(inputString, "rmdir ", 6) == 0) {
            printf("Removing Directory with name...\n");
            do_rmdir(cwd, arg);
            show_prompt(cwd);
            printf("/ >");
        }


        else if(strncmp(inputString, "rmv", 3) == 0) {
            printf("Removing first child test\n");
            struct tree_node *child = cwd -> first_child -> tree;
            rmv(cwd);
            show_prompt(cwd);
            printf("/ >");
        }


        else if(strncmp(inputString, "rmdir", 5) == 0) {
            printf("Please specify directory name: rmdir directoryName\n");
            show_prompt(cwd);
            printf("/ >");
        }
        else {
            printf("Unrecognised input: Please try again.\n");
            show_prompt(cwd);
            printf("/ >");
        }
    }

    printf("\nProgram Quit... \n\n");   

    return 0;
}

1 个答案:

答案 0 :(得分:0)

For the compiler to issue such a diagnostic, you must be trying to define a global variable with a non-constant initializer:

        public ObservableCollection<Attachment> AttachmentLst
        {
            get { return _attachmentLst; }
            set { SetProperty(ref _attachmentLst, value); }
        }
        #endregion

        #region Commands
        public ICommand AttachmentChecked
        {
            get
            {
                return _attachmentChecked ?? (_attachmentChecked = new CommandHandlerWithParam(obj => ExecuteAttachmentChecked(obj), CanExecuteAttachmentChecked()));
            }
        }

        private void ExecuteAttachmentChecked(object obj)
        {

        }

        private bool CanExecuteAttachmentChecked()
        {
            return true;
        }

This cannot be done at the global level.

You must define char *string_buffer = malloc(128 * sizeof(char)); with a constant initializer such as string_buffer, or no initializer at all, which will have the same effect, and allocate the memory at startup, in the NULL function:

main()

Note that if you do not need to reallocate char *string_buffer; int main(void) { string_buffer = malloc(128); ... } during the course of the program, you do not need to make it a pointer to dynamic memory, just defining a global array should suffice:

string_buffer