作为输入时,如何处理不存在的字符?——计算方法

3

抱歉,如果问题标题有点不准确,那是因为这是一个非常奇特的问题。我的目标是解码使用我将在一段时间内解释的方法编码的输入字符串为纯英文文本。 编码是通过选择一个介于2和消息长度一半之间的整数nRows完成的,例如,长度为11的消息将允许nRows值在2到5的范围内。然后将消息写入网格的列中,每个网格单元格中一个字符,在每个列中nRows个字符,直到所有消息字符都被使用。这可能导致最后一列只填充了部分内容。然后逐行读取消息。 例如,如果输入消息是ALL HAIL CAESAR,nRows值为2,编码将如下所示:

A L H I   A S R
L   A L C E A @

在表格中,@代表一个不存在的空白字符,我只是加上它来解释下一部分 :)

我的实际问题是解码这些短语。迄今为止,我编写的代码可以解决一些问题,但是一旦空白字符(@)变得很多,代码就开始崩溃了,因为代码显然无法识别它们,算法会跳过它们。 我的代码是:

/*
 * DeConfabulons.c
 * A program to Decode for the Confabulons
 * 
 * August 9th 2015
 */

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

//A simple function confab which given input text encoded using
//the Confabulons encoding scheme, and a number of rows, returns 
//the originally encoded phrase.

void deconfab(const char inText[], int nRows, char outText[])
{
    int count = 0;
    int i = 0;
    int len = strlen(inText);
    float help = ((float)len/(float)nRows);
    int z = 0;
    while (z < round(help))
    {
        while (((int)inText[count] > 0) && (count <= len))
        {
            outText[i] = inText[count]; 
            i ++;
            if (count < (int)help)
            {
                count = count + round((int)help+0.5);
            }
            else
            {
                float helper = count + help;
                count = round(helper);
            }  


        }
        z ++;
        count = z;
    }
    outText[i] = '\0';
}

下面介绍的方法适用于之前提到的凯撒加密算法。它的编码形式是ALHI ASRL ALCEA。我拿到的那个问题的主要输入为:

char buffer[40] = {'\0'};
deconfab("ALHI ASRL ALCEA", 2, buffer);
printf("%s\n", buffer);

正确输出的是:

ALL HAIL CAESAR

然而,当处理带有额外“空格”字符的情况时,例如:

char buffer[60] = {0};
char* s = "Two hnvde eo frgqo .uxti hcjeku  mlbparszo y";
deconfab(s, 13, buffer);
printf("%s\n", buffer);

输出应该是:
The quick brown fox jumps over the lazy dog.

然而我的代码将返回:
Thdefq.the browneorouickmps ov  g x julazy

我经过多次手动测试,得出结论是最后一列的空格字符导致了这个问题,然而无论我尝试什么,代码都不能在每个测试用例中正常工作。我可以几乎任意编辑大部分函数,但是任何输入或者int main(void)中的内容都不允许编辑。我只是想找到一种方法将这些空格字符识别为实际不存在的字符。


然而,在处理带有额外空字符的情况时,我在这里没有看到那些额外的空字符。但是在这里""Two hnvde eo frgqo .uxti hcjeku mlbparszo y""。 - alk
我遇到的问题是它们实际上不存在 - 如果您查看表格(第一个代码样式输入),则字符从列的顶部到底部,从左到右读取。我正在使用的方法要求我们知道表格中所有这些空白空间,以便能够找到下一个字符。提供的输入不包含这些内容,我们需要用另一种方式来解决它们。输入从行的左侧到右侧自上而下读取(减去空白@单元格)。回想起来,我可能不应该称它们为空值,我现在会更改它们。 - user99point9
3个回答

2
首先,就我所看到的而言,你的输入中不包括那些“null”字符 - 如果你通过添加任何“虚拟”字符来实现这一点的话,算法就可以运行。第一种情况下它可以工作的原因是在输入的末尾缺少了“空白”字符,与句子中缺少的位置相同。
你可以尝试通过猜测带有这些虚拟字符的消息的长度(我不确定如何表述)来解决这个问题,例如: ALHI ASRL ALCEA 有 15 个字符(15 mod 2 = 1),但是 ALHI ASRL ALCEA@ 有 16 个字符。同样,Two hnvde eo frgqo .uxti hcjeku mlbparszo y 有 44 个字符(44 mod 13 = 5),因此需要相当数量的虚拟字符才能使其工作(13-5=8)。
此时有几种方法 - 例如,你可以尝试插入缺失的空格来对齐列,逐字符将所有内容复制到二维数组中,然后逐行读取,或者只确定从最后一列开始的(len mod rows)个字符,将其从输入中移除(需要使用一些经典的C字符串函数进行操作,因此我在此不会给出完整的答案),接着读取剩余部分然后附加最后一列的字符。
希望这可以帮到你。

2

索引计算存在一些混乱。 首先,它是纯离散变换。因此,它应该仅使用整数实现。 下面的函数可以完成所需操作。

void deconfab(const char inText[], int nRows, char outText[])
{
    int len = strlen(inText);
    int cols = len / nRows;
    int rows_with_large_cols = len % nRows;
    int count = 0;
    int col = 0;
    int row = 0;

    while (count < len)
    {
        int idx;
        if (row < rows_with_large_cols)
            idx = row * (cols + 1) + col;
        else
            idx = rows_with_large_cols * (cols + 1) +
                (row - rows_with_large_cols) * cols + col;

        if (idx > len - 1) {
            ++col;
            row = 0;
            idx = col;
        }

        outText[count] = inText[idx];
        ++row;
        ++count;
    }
    outText[count] = '\0';
}

它可能需要更好的重写。现在它就像一个伪代码来解释算法。


0

如果你要处理空值,就不能使用标准的str*函数。相反,你必须直接处理数据,并使用*read函数族来获取你的数据。


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