C# 字节数组中的增量字符

C# 字节数组中的增量字符,c#,.net,byte,buffer,unsafe,C#,.net,Byte,Buffer,Unsafe,我正在用以下内容对字节数组进行预填充: private static byte[] idBuffer = ASCIIEncoding.Default.GetBytes("A" + DateTime.Now.ToString("yy") + DateTime.Now.DayOfYear + "0000001"); 字节数组中的0000001部分是我的ID部分,每次调用increment方法时,我都希望用ASCII字符0-1A-S递增它 例如,增量序列样本将为: 000000S ... 0000

我正在用以下内容对字节数组进行预填充:

 private static byte[] idBuffer = ASCIIEncoding.Default.GetBytes("A" + DateTime.Now.ToString("yy") + DateTime.Now.DayOfYear + "0000001");
字节数组中的0000001部分是我的ID部分,每次调用increment方法时,我都希望用ASCII字符0-1A-S递增它

例如,增量序列样本将为:

000000S ... 00000S0 00000S1 ... 00000不锈钢 ... 0000S00 ... 0000S99 0000S9A 等等

我很难找到正确的算法/状态机来正确增加字符

现在,我预先填充一个char表:

private static byte[] charCodes = new byte[] { 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 80, 81, 82, 83};
我在状态机上做了一些粗野的尝试,但这只能让我排到第二位:

if (idBuffer[bufPosition] < 83)
{
    idBuffer[bufPosition] = charCodes[charCodePosition];
    charCodePosition++;
}
else
{
    if (idBuffer[bufPosition - 1] == 48)
    {
        for (int i = bufPosition; i < idBuffer.Length; i++)
            idBuffer[i] = 48;

        idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
        charCodePosition2++;
    }
    else
    {
        charCodePosition2++;
        idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
    }

    charCodePosition = 0;
}

我确信有一种更优雅的方法可以做到这一点,但我想不出——理想情况下,如果有人知道如何使用不安全的代码/指针来实现这一点,那就更好了

其实很简单:

从最后一个元素开始。 加一个。 如果您现在有“0”+10 58,请将其调整为“A”65。 如果您除了“T”之外还有其他任何东西懒得查找ASCII代码,那么您就完成了。 调整到“0”48。 通过向左移动一个元素并从第2步开始重复进行进位。 基于这样一个事实,您希望酷假设您的目标是偏好不安全代码和固定大小的数字,您可以将整个代码展开到简单的状态机中:

{number-to-add, char} -> {incremented char, carry}
“A”-“C”的近似代码为0,1,3。如果将表合并为一个表,即将字符和索引合并为具有位移位的单个uint值,则可能会稍微简化

char[2,256] incrementedChar = new char[2,256]{
      {...64 0..., 'A', 'B', 'C', more 0 }, // A+0 = A, 
      {...64 0..., 'B', 'C', 'A', more 0 }};// A+1 = B, .., C+1 = A+carry

int[2,256] carryTable = new int[2,256]{
      {...64 0..., 0, 0, 0, more 0 }, // adding 0 never carry 
      {...64 0..., 0, 0, 1, more 0 }};// carry when adding 1 to `C`

var chars = new[] {'A','A', 'A', 'C'};
int carry = 1; // adding 1 to the last digit
char current;
// unrolled loop from end to start. Adjust indexes if it is not in the beginning.

current = incrementedChar[carry, chars[3]];
carry = carryTable[carry, chars[3]];
chars[3] = current;

current = incrementedChar[carry, chars[2]];
carry = carryTable[carry, chars[2]];
chars[2] = current;

current = incrementedChar[carry, chars[1]];
carry = carryTable[carry, chars[1]];
chars[1] = current;

current = incrementedChar[carry, chars[0]];
carry = carryTable[carry, chars[0]];
chars[0] = current;

关于如何将数字转换为任意基或从任意基转换为任意基,可能有数百个问题,即…我不想转换,我想增加数组中的字节数以产生所需的结果-我查看了您链接中的搜索结果,但找不到任何适用的内容抱歉,错过了最后一部分-您正在寻找更复杂的解决方案。我想你们仍然可以在讨论数学运算的问题中找到灵感,而不是在10。。。若我需要做BaseX数学,我会先用反向查找映射将数字值转换为0-X范围,然后执行操作,然后再转换回。。。但这还不够复杂。试试这个:var results=Encoding.UTF8.GetCharsnew byte[35]。选择x,i=>bytei+49.ToArray@jdweng:这创建了一个到所选字母表的映射,但它没有实现增量,这是问题的关键。对于外观更酷的代码,我的理解是,出于选择不安全步骤2-5的原因,应该使用查找表char->{incremented char,carry}。Ben,如果我正确理解您的解决方案,它只会增加下一个位置,但不会重置先前的位置,例如,我希望输出为000S。。。0010 ... 0011 ... 001S。。。0020 .. 等等@AlexeiLevenkov:使用查找表不需要不安全,而且查找表不会执行步骤4。也许你是说2,3,5?无论如何,查找表的速度不太可能更快,当然也不容易看出它的效果。@TJF:第5步解决了这个问题。@BenVoigt抱歉,但我不明白-我知道5将当前位置设置为0,然后向左移动一个位置。但这并不考虑在你向上移动一个位置后返回右侧开始递增,例如00SSS之后应该在01000,01001之后。。。01SSS这个想法不错,不需要不安全的代码,但实现完全失败了。您正在向数字中添加1111111,而不是添加0000001。完全忽略了问题中的字母表,它同时使用十进制数字和字母,尽管这对于查找表来说很容易处理with@BenVoigt很好的一点-我们同时在整理桌子。完整的表格不适合回答/可读性较差,但唯一棘手的部分是9->A-应该是可行的…看起来是一个正确的解决方案,只有一个问题。您正在使用current的新值而不是传入值查找carryTable。请注意,当添加一个创建“0”或在您的表中创建“A”@BenVoigt手动展开循环时,进位规则也可以写为进位,结果比我想象的更难: