繁体   English   中英

数组中的Char指针未释放

[英]Char pointer in array is not freeing

我有一个char指针数组。 该数组有字符串。 当我想释放分配给其中一个字符串的内存时,它可以工作,但是删除后的字符串变成了垃圾。 这是我的代码:

#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);
}

如果我在数组中打印名称,它将显示Carl Hello 如果在释放Carl后尝试再次打印,它会显示↨Y (它应打印Hello)。

您输入的是Carl和Hello

名称[0] =卡尔

名称[1] =你好

现在,您释放了Names [0]的内存。

当您打印名称时,您尝试打印已经释放的Names [0],因此您将得到垃圾。

您需要移动所有指针以填充空白空间

在这种情况下,删除Names [0]时,您只有一个条目,因此让Names [0]指向Names [1]上的内存

当您删除i处的条目时,您需要调整以下指针,直到列表末尾。

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

除了RADAR在回答中发现的主要问题外,还有其他一些问题:

  1. 这里:

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

    不要转换malloc()的返回值,并且sizeof(char)始终为1,因此应为:

     Names[*size] = malloc(len + 1); 
  2. 您应该检查malloc()返回NULL ,因为它可能失败并返回NULL

  3. 在这里,以及其他地方:

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

    您可能会遇到问题,因为您要发送给printf()的东西没有以换行符结尾。 交互式输入和输出默认情况下在C中是行缓冲的,在某些系统上,直到输入 ,您才会看到该提示。 为避免这种情况,如果要确保立即显示不以换行符结尾的某些输出,请调用fflush(stdout)

  4. main()返回一个int ,如果您不想使用命令行参数,则正确的声明为int main(void) 虽然main()是一个函数返回一个值,你不必明确地返回一个,它是更好的形式,如果你做的。

  5. 这个:

     scanf(" %s", str); 

    如果用户输入的字符数超过100个,则将导致Bad Times。 您可以使用scanf()解决此问题,但使用fgets()更好。

  6. 通常,使用scanf()这种输入策略很脆弱,特别是如果用户输入错误的内容时。 特别是如果您获得大量输入,则可以通过定义一些便捷函数来使用fgets()获取行和整数,然后重新使用这些函数,从而对自己有所帮助。

  7. 您的格式在某些地方非常糟糕。

这是考虑到以上所有因素的修改版本:

#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