简体   繁体   English

数组中的Char指针未释放

[英]Char pointer in array is not freeing

I have an array of char pointers. 我有一个char指针数组。 This array have strings. 该数组有字符串。 When I want to free the allocated memory for one of the strings it works, but the string after the removed one turns into rubbish. 当我想释放分配给其中一个字符串的内存时,它可以工作,但是删除后的字符串变成了垃圾。 This is my code: 这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 3
void AddName(char *Names[],int *size)
{
    char str[100];
    int len;
    if (*size < MAX)
    {
        printf("Enter a string: ");
        scanf(" %s", str);
        len = strlen(str);
        Names[*size] = (char *)malloc((len+1)*sizeof(char));
        strcpy(Names[*size],str);
        *size = *size+1;
    }
    else printf("Full Memory!!\n");
}
void RemoveName(char *Names[],int *size)
{
    int loc;
    if (*size > 0)
    {
    printf("Starting from 0. Enter the name's location: ");
    scanf(" %d", &loc);
    free(Names[loc]);
    *size = *size-1;
    }else printf("ERROR\n");
}
void PrintNames(char *Names[],int size)
{
    int i;
    for (i = 0; i<size; i++)
    {
        printf(" %s\t", Names[i]);
    }
    printf("\n");
}
main()
{
    char *Names[MAX];
    int size = 0;
    int c;
    do
    {
        printf("=========================\n");
        printf("1- Add a new name.\n");
        printf("2- Delete an old name.\n");
        printf("3- Print names.\n");
        printf("4- Exit.\n");
        printf("=========================\n");
        printf("Enter your choice: ");
        scanf("%i", &c);
        printf("=========================\n");
        switch(c)
        {
            case 1: AddName(Names,&size);
            break;
            case 2: RemoveName(Names,&size);
            break;
            case 3: PrintNames(Names,size);
            break;
            case 4: printf("Good bye.\n");
            break;
            default: printf("ERROR: Bad input.\n");
        }
    }while(c != 4);
}

If I print the names in the array, it gives Carl Hello . 如果我在数组中打印名称,它将显示Carl Hello If I try to print again after freeing Carl it gives ↨Y (it should print Hello). 如果在释放Carl后尝试再次打印,它会显示↨Y (它应打印Hello)。

Your input is Carl and Hello 您输入的是Carl和Hello

Names[0] = Carl 名称[0] =卡尔

Names[1] = Hello 名称[1] =你好

Now you freed up the memory for Names[0] 现在,您释放了Names [0]的内存。

When you print names, you are trying to print Names[0] which is already freed up, so you are getting garbage. 当您打印名称时,您尝试打印已经释放的Names [0],因此您将得到垃圾。

You need to move all the pointers to fill up the empty space 您需要移动所有指针以填充空白空间

In this case on deletion of Names[0], you have only one entry so Have Names[0] point to memory at Names[1] 在这种情况下,删除Names [0]时,您只有一个条目,因此让Names [0]指向Names [1]上的内存

When you delete entry at i you need to adjust the pointers like below till the end of the list. 当您删除i处的条目时,您需要调整以下指针,直到列表末尾。

Names[i] -> Names[i+1]

In addition to the main problem identified by RADAR in their answer, there are several other issues: 除了RADAR在回答中发现的主要问题外,还有其他一些问题:

  1. Here: 这里:

     Names[*size] = (char *)malloc((len+1)*sizeof(char)); 

    don't cast the return from malloc() , and sizeof(char) is always one, so this should be: 不要转换malloc()的返回值,并且sizeof(char)始终为1,因此应为:

     Names[*size] = malloc(len + 1); 
  2. You should check the return from malloc() , because it can fail and return NULL . 您应该检查malloc()返回NULL ,因为它可能失败并返回NULL

  3. Here, as well as other places: 在这里,以及其他地方:

     printf("Enter a string: "); scanf(" %s", str); 

    You can get a problem because the thing you're sending to printf() does not end with a newline. 您可能会遇到问题,因为您要发送给printf()的东西没有以换行符结尾。 Interactive input and output is line-buffered by default in C, and on some systems you won't see that prompt until after you've entered your input. 交互式输入和输出默认情况下在C中是行缓冲的,在某些系统上,直到输入 ,您才会看到该提示。 To avoid this, call fflush(stdout) if you want to make sure some output that does not end with a newline displays immediately. 为避免这种情况,如果要确保立即显示不以换行符结尾的某些输出,请调用fflush(stdout)

  4. main() returns an int , and if you don't want to use command line arguments, the proper declaration is int main(void) . main()返回一个int ,如果您不想使用命令行参数,则正确的声明为int main(void) While main() is the one function returning a value where you don't have to explicitly return one, it's better form if you do. 虽然main()是一个函数返回一个值,你不必明确地返回一个,它是更好的形式,如果你做的。

  5. This: 这个:

     scanf(" %s", str); 

    will lead to Bad Times if the user enters more than 100 characters. 如果用户输入的字符数超过100个,则将导致Bad Times。 You can cope with this with scanf() but using fgets() is better. 您可以使用scanf()解决此问题,但使用fgets()更好。

  6. In general, this type of input strategy using scanf() is fragile, particularly if the user enters the wrong thing. 通常,使用scanf()这种输入策略很脆弱,特别是如果用户输入错误的内容时。 Particularly if you're getting a lot of input, you'll do yourself a big favor by defining some convenience functions to get lines and integers using fgets() , and re-using those functions. 特别是如果您获得大量输入,则可以通过定义一些便捷函数来使用fgets()获取行和整数,然后重新使用这些函数,从而对自己有所帮助。

  7. Your formatting is pretty bad in some spots. 您的格式在某些地方非常糟糕。

Here's a modified version taking all of the above into account: 这是考虑到以上所有因素的修改版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 3
#define BUFFER_LEN 100

/*  Convenience function to get a line from
 *  standard input - caller must free         */

char * get_line(void)
{
    char str[BUFFER_LEN];
    char * newstr;
    int len;

    /*  Get line of input  */

    if ( !fgets(str, sizeof str, stdin) ) {
        fprintf(stderr, "ERROR: Couldn't get string!\n");
        exit(EXIT_FAILURE);
    }

    /*  Remove trailing newline, if present  */

    len = strlen(str);
    if ( len > 0 && str[len - 1] == '\n' ) {
        str[--len] = 0;
    }

    /*  Allocate memory and copy string  */

    if ( !(newstr = malloc(len + 1)) ) {
        perror("couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    strcpy(newstr, str);

    return newstr;
}

/*  Convenience function to get an integer from standard input  */

long get_long(void)
{
    char * str, *endptr;
    long n;

    str = get_line();
    n = strtol(str, &endptr, 0);
    if ( *endptr ) {
        fprintf(stderr, "ERROR: You didn't enter an integer!\n");
        exit(EXIT_FAILURE);
    }

    free(str);

    return n;
}

/*  Adds a name to a list  */

void AddName(char * Names[], int * size)
{
    if ( *size < MAX ) {
        printf("Enter a string: ");
        fflush(stdout);

        Names[*size] = get_line();
        *size += 1;
    }
    else {
        printf("ERROR: List full!\n");
    }
}

/*  Removes a name from the list  */

void RemoveName(char * Names[], int * size)
{
    if ( *size > 0 ) {
        int i;
        long loc;

        printf("Starting from 0, enter the name's location: ");
        fflush(stdout);

        /*  Free the desired name...  */

        loc = get_long();
        free(Names[loc]);

        /*  ...and move any names ahead of it back.  */

        for ( i = loc + 1; i < *size; ++i ) {
            Names[i - 1] = Names[i];
        }

        *size -= 1;
    }
    else {
        printf("ERROR: list empty!.\n");
    }
}

/*  Prints the names in the list  */

void PrintNames(char * Names[], int size)
{
    int i;
    for ( i = 0; i < size; ++i ) {
        printf(" %s\t", Names[i]);
    }
    putchar('\n');
}

/*  Main function  */

int main(void)
{
    char * Names[MAX];
    int size = 0;
    long c;

    do {
        printf("=========================\n");
        printf("1- Add a new name.\n");
        printf("2- Delete an old name.\n");
        printf("3- Print names.\n");
        printf("4- Exit.\n");
        printf("=========================\n");

        printf("Enter your choice: ");
        fflush(stdout);
        c = get_long();

        printf("=========================\n");

        switch( c ) {
            case 1:
                AddName(Names, &size);
                break;

            case 2:
                RemoveName(Names, &size);
                break;

            case 3: 
                PrintNames(Names, size);
                break;

            case 4:
                printf("Good bye.\n");
                break;

            default:
                printf("ERROR: Bad input.\n");
                break;
        }
    } while ( c != 4 );

    return 0;
}

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

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