根据我对Code128条形码校验位计算的理解*(与大多数其他标准条形码类型完全不同),我的代码是正确的。但是,我会感谢那些可能更了解/从沟渠(或实验室)外套附着的沟渠中获得一些经验观察/泥浆的人进行的“理智检查”。
条形码中的每个字符,从左边开始,首先被转换为其ASCII码(IOW,条形码字符“1”将被视为其ASCII码49,等等),然后该值被乘以通过其在字符阵列中的序数位置。
e.g。对于伪造的条形码编号“123456789”,“1”等于49,“2”等于50,......“9”等于57。
然后,每个字符的序号位置乘以其ASCII值。例如,1 * 49 == 49,2 * 50 == 100,...... 9 * 57 == 513。 然后你将所有这些加起来,得到(在这种情况下)2,445。
下一步是将该数字除以Code128“幻数”103;你感兴趣的价值是模数。因此,在这种情况下,2445%103 == 76。
倒数第二个 - 最后,你转换该值(76),将其视为ASCII码,将另一个方向转换为其“表示”值,即“L”。
最后,将计算出的字符附加到原始条形码。确实如此(尽管还有ado或adieux),你得到的值是“123456789L”
如果这不是正确的值,那么我理解错误。
以下是一些条形码:
0) 123456789
1) 12345678
2) 1234567
3) 123456
...以及它们应如何与计算出的校验位一起显示(并使用下面的代码):
0) 123456789L
1) 12345678N
2) 1234567*
3) 123456E
最后但并非最不重要的是,这是我用来计算Code128校验位的代码:
private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
const int CODE_128_DIVISOR = 103;
string barCode = textBoxRawCode128.Text.Trim();
int runningTotal = 0;
for (int i = barCode.Length - 1; i > -1; i--)
{
char valToConvertToASCII = Convert.ToChar(barCode[i]);
int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
runningTotal += (valToMultiply*(i + 1));
}
int code128Modulus = runningTotal%CODE_128_DIVISOR;
textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
return valToConvertToASCII;
}
我不太喜欢Brian Anderson的回答;他可能是对的(可能是),但我认为只要校验位数计算,开始和停止位就会被忽略。是不是它们只是让条形码扫描器知道从哪个点开始注意,然后从哪个点恢复它的电子打盹?
然后数学(如果Brian对于需要从ASCII值中减去32来说是正确的)将是:
(17*1)+(18*2)+(19*3)+(20*4)+(21*5)+(22*6)+(23*7)+(24*8)+(25*9)
-or:
17 + 36 + 57 + 80 + 105 + 132 + 161 + 192 + 225 == 1005
为什么开始字符会包含在计算中,而不是停止字符?
由于1005%103 == 78,校验位将是......“N”......或者是(78-32 == 46)“ - ”?
如果包含停止和开始字符,那么当然也会改变解决方案......
我承认我并不完全是条形码,所以我可能已经看过这样但只是没有注意到或注意到了,但可以条形码的检查数字为“ - ”和“< EM>“?这看起来很奇怪;如果不仅仅是数字,我希望它们永远是字母数字。如果我的怀疑是正确的,那么当计算最终得到一个简单的检查数字时会怎么做,例如“ - ”或“”或“〜”,&amp; c?
所以,如果我理解Brian和其他来源我读得正确,我会从条形码扫描器中读取语义解码的内容:
[startChar]123456789[checkDigit][stopChar]
...但是哪个逻辑上会删除停止字符 - 因为它不是校验位计算的一部分 - 而且(逻辑上不太正确)也会删除校验位,所以我实际得到的将是:
[startChar]123456789
...并按摩它并计算校验位以显示条形码的人类可读表示:
123456789[checkDigit]
由于条形码扫描后显然(?)显示了启动字符,因此我可以将其预先添加到要计算的runningTotal值;因此,我的代码现在是:
private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
const int CODE_128_DIVISOR = 103;
string barCode = textBoxRawCode128.Text.Trim();
int runningTotal = ConvertToASCIIInt(barcode[0]); // Start with the value of the start char; this should always be either 103 (Code128A), 104 (Code128B), or 105 (Code128C); 106 is the stop char
for (int i = barCode.Length - 1; i > 0; i--) // now disregarding already calculated first element by ignoring element 0
{
char valToConvertToASCII = Convert.ToChar(barCode[i]);
int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
runningTotal += (valToMultiply*(i + 1));
}
int code128Modulus = runningTotal%CODE_128_DIVISOR;
textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
const int ASCII_ADJUSTMENT_VAL = 32;
return valToConvertToASCII-ASCII_ADJUSTMENT_VAL;
}
答案 0 :(得分:3)
看起来您可能缺少代码128A(103),128B(104)或128C(105)的起始字符。这个数字用'* 1'加权,就像barCode字符串中的第一个字符一样。我还认为你必须使用Code 128值(即ASCII_value_of_character - 32)进行数学运算。因此,对于字符串“123456789”,我得到“104,17,18,19,20,21,22,23,24,25,79,106”,包括开始128B(104),停止(106)和校验和79(1109%103)。