【问题标题】:How to allocate memory to string with variable length?如何为可变长度的字符串分配内存?
【发布时间】:2020-09-06 19:17:26
【问题描述】:

我有一个函数以特定方式混合2个字符串,并生成一个新字符串,我该如何分配新字符串的内存?

我已尝试添加此代码,但我不确定如何将其用于我不知道的字符串中。

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

char *CreateString(char *string1, char *string2) {
    int size;
    int size1 = 0;
    int size2 = 0;

    for (int i = 0; *(string1 + i); i++) {
        size1++;
    }

    for (int i = 0; *(string2 + i); i++) {
        size2++;
    }

    size = (size1 * size2) + size1;

    char string[size];
    char *stringptr = string;

    for(int i = 0; i < size; i = i + size2 + 1) {
        *(stringptr + i) = *(string1++);

        for (int j = 0; j < size2; j++) {
            *(stringptr + i + j + 1) = *(string2 + j);
        }
    }
    puts(string);
}

int main() {
    char string1[] = "chocolate";
    char string2[] = "123";

    CreateString(string1, string2);
    return 0;
}

【问题讨论】:

  • 计算新的大小并用 malloc 分配那么多(+1 为 \0)。
  • 调用 malloc 如下:(char*)malloc(strlen(the_string) + 1)。为空字符添加一个 ('\0)
  • 您想了解strlen。并写string1[i] 而不是*(string1+i)。后者没有错,但可读性较差。
  • @Adam 从不强制转换 malloc 的返回值。
  • 你期望什么输出?我很确定你的函数可以用 3-4 行代码重写。

标签: c string function pointers malloc


【解决方案1】:

使用string.hstrlen 例程:

size_t size=strlen(string);
size_t size2=strlen(string2);
size_t total_size=(size*size2)+size;
//now you make a malloc of a string result ugual to total_size+1 due to the fact the string end with "/0" character.
char* string_final;
 string_final=malloc(sizeof(char)*(total_size+1));
    if(string_final==NULL){
        perror("Error in malloc");
    }
    else{
     //...continue
   }

【讨论】:

  • 当我尝试在 main 中使用 printf("%s", string3) 打印时,它不会打印任何东西...
【解决方案2】:

你可以为字符串分配内存

char *stringptr = malloc(size + 1);

请注意,您的代码可以使用来自&lt;string.h&gt; 的字符串函数进行简化:

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

char *CreateString(const char *string1, const char *string2) {
    size_t size1 = strlen(string1);
    size_t size2 = strlen(string2);
    size_t size = size1 * (size2 + 1);
    char *stringptr = malloc(size + 1);

    if (stringptr) {
        for (size_t i = 0; i < size; i = i + size2 + 1) {
            stringptr[i] = *string1++;
            strcpy(stringptr + i + 1, string2);
        }
    }
    return stringptr;
}

int main() {
    char string1[] = "chocolate";
    char string2[] = "123";
    char *string3 = CreateString(string1, string2);
    if (string3) {
        printf("%s\n", string3);
        free(string3);
    } else {
        printf("cannot allocate memory\n");
    }
    return 0;
}

【讨论】:

  • 我无法将 const 添加到我的函数中,但它确实帮助我了解了一些事情,我做了和你一样的事情,我返回了 stringptr 但是当我打印它时它只打印一个空格你知道吗为什么”?
  • @adhamjabali:为什么不能在CreateString的原型中添加const?参数应声明为const char *,以表明此函数不会修改这些参数字符串。我在我的系统上编译了上面的代码并得到了预期的输出:c123h123o123c123o123l123a123t123e123。你是怎么复制代码的?你用什么系统?
  • 是的,这是我复制代码的问题,我已修复它,非常感谢。
【解决方案3】:

根据您的描述,[来自 cmets,给定:“巧克力”“123”作为用户输入]
“...字符串是这样制作的:c123o123c123o123l123a123t123e123 但带有我从用户那里获得的字符串。”
CreateString 可以这么简单:

char * CreateString(const char* string1,const char* string2)
{
    int len1 = strlen(string1);
    int len2 = strlen(string2);
    char *ptr = string1;

    char tempBuf[len1 + len1*len2 +1];// intermediate content buffer

    char *newString = calloc(len1 + len1*len2 +1, 1);
    if(newString)//test return of malloc
    {
        while(*ptr != NULL)//while each character is not NULL, stay in loop
        {//use combination of sprintf and strcat to interleave
         //components of new string
            sprintf(tempBuf, "%s%c", newString, *ptr);
            strcat(tempBuf, string2);
            sprintf(newString, "%s", tempBuf);
            ptr++;//increment pointer to next char in string1
        }                  
    }
    return newString;  //calling function should always check for null before using
}

int main(int argc, char *argv[])//Use this signature rather than 
{                               //int main(void) to allow user input
    if(argc != 3) //simple verification that command line contains 2 arguments
    {
        printf("%s\n", "Usage: prog.exe <string1> <string2>");
        return 0;
    }
    char *newString = CreateString(argv[1],argv[2]);
    if(newString)
    {   
        printf( "Resulting string is: %s\n", newString);
        free(newString); //free when finished
    }       
    return 0;
}  

使用"chocolate""123" 的用户输入,程序返回:

【讨论】:

    【解决方案4】:

    当我运行你的代码时,我得到了字符串:

    c123h123o123c123o123l123a123t123e123
    

    您似乎想在string2 的每个字符后添加string2

    所以,在你的情况下,你可以打电话给malloc

    size = (size1 * size2) + size1;
    char *string = malloc(size + 1); // +1 for null character
    if(!string) {
       printf("cannot malloc for string\n");
       return NULL;
    }
    

    你的函数应该在最后返回string。不想使用string的时候不要忘记释放这个函数的返回值,避免内存泄漏。

    这段代码如下:

        for(int i=0;*(string1+i);i++){
            size1++;
        }
    
        for(int i=0;*(string2+i);i++){
            size2++;
        }
    

    可以替换为strlen函数:

    size1 = strlen(string1);
    size2 = strlen(string2);
    

    【讨论】:

    • malloc(sizeof(char) * size + 1) 不一致:使用malloc(size + 1)malloc(sizeof(char) * (size + 1))。所有 3 个表达式的计算结果都相同,但你的混合了苹果和橙子。
    • @chqrlie 你是对的,因为(sizeof(char) 总是等于1。我将编辑代码。
    • 所以我添加了这个 if(!string)... 并将 else 用于我的其余功能?如果允许,它会返回 Null 或字符串?
    • @adhamjabali 当然,您可以使用if ... else。或者您可以使用 if(string) {/*your rest of code*/} 这只是您处理错误的一种方式。如果您的代码出现错误,您无需对其余代码执行任何操作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 2020-01-29
    • 2012-11-01
    • 2020-03-11
    • 2012-07-10
    • 1970-01-01
    相关资源
    最近更新 更多