如何在C语言中解压字符数组

3
我需要创建一个函数:
char * decompress(const char * src) {
}

此函数的输入是某个字符串:

Hello world! -> Hello world!

Hel2o world!10" -> Hello world!!!!!!!!!!

正如您所看到的,如果有某个数字,它会重复前一个字符这个数字次。我是一名Java程序员,但现在我需要在C语言中解决这个问题。

我现在有这个代码。它只打印结果,但我不知道如何将其分配给返回指针。

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

char * decompress(const char * src) {
    int max = 0;
    int pom = 1;

    char *vysledek = "";
    int i;
    for (i = 0; i < strlen(src); i++) {
        max = 0;
        pom = 1;

        while (isdigit(src[i])) {
            int digit = (src[i] - '0');
            max = max * 10 + digit;
            i++;
            pom++;
        }

        if (max == 0) {
            max = 1;
        }

        int j;
        for (j = 0; j < max; j++) {
            printf("%c", src[i - pom]);
        }
    }

    return vysledek;
}

int main(int argc, char * argv []) {

    decompress("Hel2o world!10");

    return 0;
}

3
如果你的其余代码有效,你需要进行小的更改:为你的输出字符串分配内存,然后简单地将字符添加到其中。但是,问题仍然是要分配多少内存给你的字符串。你可以选择静态值(对所有长度都有效),近似值或者运行一个单独的循环以首先确定所需的空间量。另一个选项是动态分配一定量的内存,然后如果已填满,则分配两倍的大小并复制内容。 - Etheryte
2
你的代码中存在未定义行为(UB),因为在外层 for 循环的第一次迭代中,内层 for 循环打印了 src[-1] - Spikatrix
1个回答

1

既然你提到自己是Java程序员,那么你应该了解C语言中内存分配的方式(特别是字符串):

char *vysledek = "";

在Java中,这将创建一个字符串对象,您可以随意添加字符。然而,在C中,这基本上将创建一个char [1]数组,其中包含'\0'(字符串终止字符)。
由于 - 像Java的数组一样 - 您不能(不应该)在数组边界之外写入,因此您可以在此数组中存储一个字符,但该数组的内存不足以满足您的功能要求。
您可以通过首先迭代输入来找出需要分配多少内存(如Nit在他的评论中提到的那样)。然后,您可以为输出指针malloc必要的内存:
vysledek = malloc (<output string length>);


现在你已经分配了足够的内存,可以将输出写入该数组中,所以不需要使用


printf("%c", src[i - pom]);

you can now write:

vysledek[vysledek_counter++] = src[i - pom];

并返回指针。
请注意,即使在您的主方法结束时(看起来应该类似于此),您也应该释放返回的值。
int main(int argc, char * argv []) {
    char *output;

    output = decompress("Hel2o world!10");
    printf("%s\n", output);
    free(output);

    return 0;
}

需要补充的一点是:如果代码遇到非终止字符串(即没有 '\0' 字符来表示字符串的结尾),代码将会失败。为了解决这个问题,可以传递一个额外的字符串长度参数(你需要自己在返回的 char 数组中设置 '\0' 字符,并为该指针预留一个额外的字节)。在第一次迭代中,它也具有未定义的行为(正如 Cool Guy 指出的那样),因为 pom 至少为 1,导致 i - pom,从而尝试访问 src[-1]


我仍然对指针感到困惑。我尝试了你的例子,但它仍然不起作用。当我使用printf("%c\n", vysledek[0]);时,它没有返回任何内容。printf("%c\n", vysledek[1]);返回H(为什么),而printf("%s\n", vysledek);也没有返回任何内容,为什么呢? - hudi
我认为在这种情况下,混淆源于C语言中的字符串: 每当遇到“\0”字符时,大多数处理字符串的函数(包括printf)都会停止处理字符串,因为无法确定数组(因此也是字符串)的长度。我已编辑了我的答案,但你现在面临的问题是:当循环开始时,vysledek中的第一个字符设置为src[-1];这可能会将第一个字符设置为'\0',从而呈现为空字符串。(注:'\0'== 0,因此printf("%d",vysledek [0]); 将打印出 0) - SebiH
还有一些其他的错误:在读取数字后,您基本上跳过一个字符而不将其写入目标数组。(当您的 isdigit 循环结束时,它指向 - 例如 - 'o',将 'l' 读入目标数组两次(现在数组中存在 3 个 'l',因为在检测到任何数字之前,第一个已经读入数组),并再次增加计数器 i 而没有读入 'o'。 - SebiH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接