簡體   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