计算UPC-A条形码的校验位

时间:2013-10-24 19:53:16

标签: c# visual-studio-2010 check-digit

我目前正在开发VS2010中的Windows窗体,它应该为新的部件号创建UPC-A并将它们存储在数据库中。到目前为止,我仍然试图把各个部分拼凑起来,我在计算校验位方面遇到了问题。我提出了以下两种情况:

场景1:按照我们目前在Excel中的方式进行计算:

string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]["UPCNumber"].ToString();
string manCode = value.Substring(1, 5);
string prodCode = value.Substring(7, 5);
int first = Math.Abs(Convert.ToInt32(value));

while (first >= 10)
first /= 10;

int chkDigitSubtotal;

string UPCNumber = first + manCode + prodCode;

chkDigitSubtotal = Convert.ToInt32((UPCNumber.Substring(1, 1)) + (UPCNumber.Substring(3, 1)) + 
(UPCNumber.Substring(5, 1)) + (UPCNumber.Substring(7, 1)) + (UPCNumber.Substring(9, 1)) + 
(UPCNumber.Substring(11, 1)));

chkDigitSubtotal = (3 * chkDigitSubtotal) + Convert.ToInt32((UPCNumber.Substring(2, 1)) + 
(UPCNumber.Substring(4, 1)) + (UPCNumber.Substring(6, 1)) + (UPCNumber.Substring(8, 1)) + 
(UPCNumber.Substring(10, 1)));

 string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);

当我运行此代码时,我收到错误“对于Int32,值太大或太小”。我不明白为什么“值”是一个有{12}个字符的varchar(它们都是数字)。

场景2:我发现了一个在线剪切的代码。这段代码有效,但给了我错误的校验位。我正在使用我们使用Excel工作表计算的UPC:

string value = "606891001678"; //valid UPC with check digit
string UPCBody = value.Substring(0, 11);
int sum = 0;
bool odd = true;

for (int i = value.Length - 1; i >= 0; i--)
{
    if (odd == true)
    {
        int tSum = Convert.ToInt32(value[i].ToString()) * 2;

        if (tSum >= 10)
        {
            string tData = tSum.ToString();
            tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
        }
        sum += tSum;
    }
    else
        sum += Convert.ToInt32(value[i].ToString());

    odd = !odd;
}

int result = (((sum / 10)+1) *10) - sum;
result = result % 10;
MessageBox.Show(UPCBody + " & " + result);

在这个例子中,校验位显然应该是8,但它返回2。 我花了很多时间在这上面并且可以使用一些建议。为什么我在第一个场景中出现错误,为什么我在第二个场景中得到的不同校验位应该是什么?

提前感谢您的帮助!

克里斯

编辑:

我删除了之前的两个编辑,因为代码存在缺陷,因为我没有得到正确的结果。我发现我们使用杜鹃花条形码,他们有自己的计算校验位的方法(参见ChkDigitSubtotal)。 所以下面的代码工作,并为我的方案提供了正确的校验位。我认为这个代码将适用于所有UPC-A计算的chkDigitSubtotal。感谢哈里森的出色指导和足智多谋的回答!

string value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]
["UPCNumber"].ToString();
long chkDigitOdd;
long chkDigitEven;
long chkDigitSubtotal;
string UPCNumber = value.Substring(0, 11);
chkDigitOdd = Convert.ToInt64(UPCNumber.Substring(0, 1)) +
Convert.ToInt64(UPCNumber.Substring(2, 1)) + Convert.ToInt64(UPCNumber.Substring(4, 1)) 
+ Convert.ToInt64(UPCNumber.Substring(6, 1)) + Convert.ToInt64(UPCNumber.Substring(8, 
1)) + Convert.ToInt64(UPCNumber.Substring(10, 1));
chkDigitOdd = (3 * chkDigitOdd);
chkDigitEven = Convert.ToInt64(UPCNumber.Substring(1, 1)) + 
Convert.ToInt64(UPCNumber.Substring(3, 1)) + Convert.ToInt64(UPCNumber.Substring(5, 1)) 
+ Convert.ToInt64(UPCNumber.Substring(7, 1)) + Convert.ToInt64(UPCNumber.Substring(9, 
1));
chkDigitSubtotal = (300-(chkDigitEven + chkDigitOdd));
string chkDigit = chkDigitSubtotal.ToString();
chkDigit = chkDigit.Substring(chkDigit.Length - 1, 1);

2 个答案:

答案 0 :(得分:1)

基于我在wikipedia上阅读的内容,您在第一个示例中错误地进行了计算。

  • String.Substring + String.Subtring或" 1" +" 1" =" 11"。你是 寻找1 + 1 = 2。您需要先将每个子字符串转换为int 添加。

+ Operator (C# Reference)

  

二进制+运算符是为数字和字符串类型预定义的。对于   数字类型,+计算其两个操作数的总和。 当一个或   两个操作数都是string类型,+连接字符串   操作数的表示。

  • String.Substring基于0,所以你错过了 {偶数位数String.Substring(0,1)

String.Substring Method

  

startIndex:子字符串从零开始的字符位置   在这种情况下。

  • 您的checkdigit字符串尝试获取小于12位的字符串的第12位数字。此外,这不是链接中所见的计算。它正在寻找该数字的10 - mod 10。这也发生在行
  • 中的更新编辑

string chkDigit = ((300 - chkDigitSubtotal).ToString()).Substring(12, 1);

您试图从基于第12个0的字符中取Substring,或者从第13个字符中取1个长度。但是,chkDigitSubtotal的值不会那么大/长。

就你的错误而言,正如金龙在他的回答中所述,你将12个字符串转换为数字,这不符合Int32并且你应该使用一个长的。

int first = Math.Abs(Convert.ToInt32(value));

转到

long first = Math.Abs(Convert.ToInt64(value));

我会检查你的计算实际上是先在前面的步骤中按逻辑运行。

<强>更新

编辑2 中,您的最后一行看起来% operator周围的变量发生了逆转。你想取109的余数除以10(即9),你的代码取10的剩余部分除以109(即0)所以改变。

chkDigitSubtotal = 10 - (10 % (chkDigitEven + chkDigitOdd));

chkDigitSubtotal = 10 - ((chkDigitEven + chkDigitOdd) % 10);

现在10 - 9 = 1这是你的checkDigit。

答案 1 :(得分:0)

如果value是一个12位长的字符串,则它太大而无法放入int。请改用long