【问题标题】:Strange Behaviour of an Array in a run-length code decoding运行长度代码解码中数组的奇怪行为
【发布时间】:2018-12-03 15:39:54
【问题描述】:

((如果您懂德语,则链接到原始问题:https://stepik.org/lesson/193516/step/9?unit=167933)

Task : printf("falsche eingabe") 每当输入中有错误时,如果一切正确,则只需打印解码后的版本。还有2种模式(单(abc)/多(aaa)),每当模式发生变化时,您还需要打印“'”(启动模式为单模式。)

示例输入 1:

abcdefghijklmnopqrstuvwxyzabcdefghijkl

样本输出 1:

虚幻

示例输入 2:

abcdefg

示例输出 2:

abcdefg

示例输入 3:

'a2b3c2d2'efg

示例输出 3:

aabbbccddefg

嗨。这是我的功课,我已经成功地做到了,只需解码输入并考虑原始输入错误的每个条件。然后我想好了..这不应该是最好的方法。因此我决定将代码解码并重新编码,如果保存的输入与我的编码版本匹配,则只需打印解码数据,否则出错。 问题是每当我尝试输入 1-'a2 2-斧头

解码不正确。我得到类似的结果 1- aa* ||啊||啊? || .....(aa + 一个随机标记) 2- ax + 一个随机符号

当我尝试使用相同逻辑但长度更长的输入时,程序运行良好。

如果有人知道并展示了修复解码的方法,我会很高兴。如果可能的话,我也不想通过在最后添加一个for循环来解决这个问题..

谢谢你

#include <stdio.h>

int main()
{
    char el[50];
    scanf("%s", &el); // 'a2b2c3'dfh
    char saved[50]; // 'a2b2c3'dfh
    char decoded[50]; //aabbcccdfh

    int k, h, y = -1, b = -1; //

    int multi = 0; //(while decoding) 1 -> multi , 0 -> not
    char encoded[50]; // 'a2b2c3'dfh
    int multi2 = 0; //(while encoding)

    for (k = 0; el[k] != '\0'; k++) { //saving

        saved[k] = el[k]; // 'a2b2c3'dfh
    }

    for (k = 0; el[k] != '\0'; k++) { //decoding

        if (el[k] == 39) {
            continue;
        }

        if (50 <= el[k + 1] && el[k + 1] <= 57) { // 2->9
            if (multi == 0)
                multi = 1;
        }

        if (multi == 0) {
            y++;
            decoded[y] = el[k];
        }

        else { //multi ==1 //a2
            for (h = 0; h < (int)el[k + 1] - 48; h++) {

                y++;
                decoded[y] = el[k];
                multi = 0;
            }

            k++;
        }

    } // decoded = aabbcccdfh ( hier ist k = laenge )

    if (k > 30) {
        printf("falsche eingabe");
        return 0;
    }

    for (k = 0; k < y + 1; k++) {
        if (decoded[k] == decoded[k + 1]) {

            if (multi2 == 0) {
                multi2 = 1;
                b++;
                encoded[b] = 39;
            }
        }

        if (multi2 == 0) {
            b++;
            encoded[b] = decoded[k];
        }
        else {
            b++;
            encoded[b] = decoded[k];
            // 0 -> decoded[k], 1 -> for, 2-> '

            for (h = k; decoded[h] == decoded[h + 1]; h++)
                ;

            b++;
            encoded[b] = ((h - k + 48) + 1);

            k = h;

            if (decoded[k + 1] != decoded[k + 2]) {
                multi2 = 0;
                b++;
                encoded[b] = 39;
            }
        }
    }

    //wurde die erste eingabe richtig codiert ? ( also gibt es fehler oder nicht ? )

    for (k = 0; saved[k] != '\0'; k++) {
        if (saved[k] != encoded[k]) {
            printf("falsche eingabe\n");
            return 0;
        }
    }
    printf("%s", decoded);
}

我尽量说清楚,如果可以更清楚,我很抱歉。

【问题讨论】:

    标签: c arrays run-length-encoding


    【解决方案1】:

    规范说:

    • 以单一方式开始

    • 当看到' 时,它会在模式之间切换

    • 在多模式中,一个字母 (Zeichen) 后跟一个数字(Ziffer,因此是一个 单个 数字),表示字母 (Zeichen) 必须重复的频率。 (所以最大重复次数为 9。)

    只需按照指定的方式实现即可。

    例子:

    abc'd2e4'ma'r2 --> abcddeeeemarr
    

    【讨论】:

    • 您的示例应导致“falsche eingabe”,因为在4 和ma 之间缺少字符';压缩后的字符串必须是:abc'd2e4'ma'r2 在德语中它描述了' 总是在两种模式之间切换。
    • @TomKuschel,规范说“so wird nur einmal in den Multimodus umgeschalten und erst beim nächsten "Einzelgänger" zurückgeschalten”,所以从多到单的过渡是隐含的,因为m 后面没有数字。
    • @PaulOgilvie TomKuschel 是对的。您给定的条目应导致 "falsche eingabe" 。每当模式发生变化时,都会有一个'...“Der Übergang zwischen Single- und Multimodus wird durch das Trennzeichen ' (einfaches Hochkomma) markiert。”
    • @Paul Ogilvie,你对 "Einzelgänger zurückschalten" 的说法是对的,但是没有关于 "Einzelgänger" 的详细定义,你没有t 阅读以下 " Der Übergang zwischen Single- und Multimodus wird durch das Trennzeichen ' (einfaches Hochkomma) markiert。" - 这意味着转换的两个方向以及示例:'a2b3c2d2 'efg 明确定义了行为。
    • 顺便说一下,带有 wird ... zurückgeschalten 的德语文本在语法上是错误的,应该是 wird ... zurückgeschaltet。 ;-)
    【解决方案2】:

    我可以看到 2 个问题

    1) 你打错了scanf

    scanf("%s",&el);
    

    应该是

    scanf("%s",el);
    

    因为你给它传递了一个字符串

    2) 你不会 NUL 终止你的字符串。这可能会导致未定义的行为,因为代码不知道字符串在哪里结束,并且会很高兴地超出您的数组。

    在你的循环之后添加终止字符,如下所示。循环结束后,k 将指向最后一个值。

    for (k = 0; el[k] != '\0'; k++) { //saving
    
        saved[k] = el[k]; // 'a2b2c3'dfh
    }
    saved[k] = '\0';
    

    我刚刚发现的另一个问题是,您正在以一种奇怪的方式填充像 decoded 这样的字符串,这使得 NUL 终止它们变得困难。

    y++ 应该在您将值存储到下面的数组之后(显然您应该使用0 而不是-1 对其进行初始化)。

            decoded[y] = el[k];
            y++;
    

    这意味着当您完成填充decoded 后,您可以使用decoded[y]='\0' 来终止它,因为y 将指向末尾,就像k 对上面的saved 循环所做的那样。

    encode 和 b 也是如此

    【讨论】:

    • 对于这段代码,缺少 & 操作数并没有改变任何东西。我曾经用你提到的方式扫描字符串,但遇到了一些问题,然后决定再次使用这种方式..
    • 去掉 & 应该会阻止你收到关于将错误类型的东西传递给scanf的警告
    • 据我所知,c 在扫描输入时会在数组末尾放入一个“\0”。代码的问题部分是用于解码的 for 循环,并且在那里扫描了使用的字符串。所以这也不应该是问题。
    • 是的 - scanf 将 NUL 终止 el,但它不会终止 saved、decoded 或 encoded - 你需要自己做这个
    • 那么最有效的方法是什么?对于 k 的最后一个值,我尝试像 decoded[k+1] = '\0' 那样做,但自然没有帮助。我认为要做到这一点,我应该首先确定解码版本的长度。这似乎是一项漫长的工作......
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    相关资源
    最近更新 更多