【问题标题】:Allocate memory for a dynamic string of char为 char 的动态字符串分配内存
【发布时间】:2020-11-28 05:55:45
【问题描述】:

我正在尝试创建一个函数,当用户按下 ENTER 以外的任何键时动态分配内存。代码编译时没有错误或警告(在 gcc 上),但无法正常工作......有人能告诉我到底出了什么问题吗?

如果我修改函数以返回指向 char i 的指针,例如

char * getString(char * string);

但是我仍然对原始代码以及为什么不起作用感到好奇,非常感谢任何解释。提前感谢所有花时间阅读本文的人。

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

void getString(char * string);

int main(void){

    char * str = NULL;

    printf("Write something:\n");
    getString(str);
    printf("You wrote:\n");
    printf("%s\n", str);
    free(str);

    return 0;
}


void getString(char * string){
    char ch;
    int length = 0;

    do{
        scanf("%c", &ch);
        if(length == 0){
            string = (char *) malloc(sizeof(char));
        } else {
            string = (char *) realloc(string, (length + 1) * sizeof(char));
        }
        if(string == NULL){
            printf("ERROR: memory could not be allocated!!\n");
        }

        string[length] = ch;
        length++;
    } while(ch != '\n');

    string[length - 1] = '\0';
}

【问题讨论】:

  • getString(char * string) 内更改string 不会影响调用代码的str

标签: c


【解决方案1】:

string 参数被传递到getString() 按值,因此它是str 变量的副本,因此任何更改getString()string 本身的影响,就像为其分配内存地址一样,不会反映在原始的 str 变量中。

要解决这个问题,您需要通过指针 传递string 参数。

如果realloc() 失败,您还需要修复代码存在的内存泄漏和访问冲突。

试试这个:

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

void getString(char ** string);

int main(void){

    char * str = NULL;

    printf("Write something:\n");
    getString(&str);
    printf("You wrote:\n");
    printf("%s\n", str);
    free(str);
    return 0;
}

void getString(char ** string){
    char ch, *newstr;
    int length = 0;

    if (string == NULL) {
        printf("ERROR: invalid parameter!!\n");
        return;
    }
    *string = NULL;

    do{
        if (scanf("%c", &ch) < 1) {
            ch = '\n';
        }

        newstr = (char *) realloc(*string, length + 1);
        if (newstr == NULL){
            printf("ERROR: memory could not be allocated!!\n");
            free(*string);
            *string = NULL;
            return;
        }
        *string = newstr;

        newstr[length] = ch;
        length++;
    }
    while (ch != '\n');

    (*string)[length - 1] = '\0';
}

【讨论】:

  • sizeof(char) 定义为 1. 不要强制转换 malloc 的结果
  • (*string)[length] = '\0'; 越界访问分配的空间。强制转换realloc 的返回值是没有意义的。
  • @M.NejatAydin 我修复了边界错误。至于类型转换,在 C 中不是必需的并且是无害的,但如果这段代码曾经在 C++ 中按原样编译,则需要进行类型转换(当然,C++ 有更好的方法来解决这个问题)
  • 该问题不包含c++ 标签。我无法理解为什么要使用 C++ 编译器编译 C 代码。此外,如果在读取换行符之前出现 EOF 条件,此代码可能会导致无限循环。
  • @M.NejatAydin "问题不包含 c++ 标记" - 我知道,但谁知道将来如何使用此代码,由 OP 或其他人。但是无所谓。我现在删除了演员表和sizeof。 “我无法理解为什么要使用 C++ 编译器编译 C 代码”——这种情况一直在发生,尤其是基于 C 的库。很多开源代码都是C。“另外,如果在读取换行符之前出现EOF条件,此代码可能会导致无限循环” - 已修复。
【解决方案2】:

实施解决方案的更好方法。
您应该使用双指针作为getString 的参数,它将存储来自用户的输入字符串。

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

void getString(char**); // function prototype

/* Main function */
int main()
{
    /* Pointer to point to the memory location
     * where input string will be stored */
    char *s=NULL;
    /* Call by reference,the function will place 
     * string in memory location where the pointer
     *  is pointing */
    getString(&s); 
    printf("s=%s\n",s);
    
    free(s);
    return 0;
}

/* getString function will
 * store each input character in
 * the allocated memory area. */
void getString(char** p)
{
    if(*p==NULL){
        if((*p=malloc(1*sizeof(char)))==NULL)
            exit(0);
    }

    int c; //Variable to store each input character
    size_t i=0; //Counter to keep track of the size of the input string

    while((c=getchar())!='\n' && c!=EOF){
        char* newp = realloc(*p,i+1);
        if(newp==NULL){
            fprintf(stderr,"realloc failed\n");
            free(p);
            exit(0);
        }
        *p = newp;
        *(*p+i)=c;
        i++;
    }
    *(*p+i)='\0'; //Null character to end the string.
}

【讨论】:

  • 错误使用 realloc(如果 malloc 内存泄漏失败)和 malloc(无结果检查)
  • 我觉得DV的问题已经够多了
  • 仍然不正确重新分配。仍然是 malloc 和 realloc 的演员。不需要 sizeof,因为 sizeof(char) 定义为 1
  • 因为它可以消除潜在的警告。 void * 可以在没有强制转换的情况下转换为任何指针。
  • 此代码仍有潜在的 UB 是 realloc 失败
猜你喜欢
  • 1970-01-01
  • 2018-06-16
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-25
相关资源
最近更新 更多