如何将字符串转换为整数再转换为字符串?

6

我曾试图搜索我的问题的重复内容,但没有找到。同时,抱歉标题可能不太易懂。我对我要搜索的事物以及术语感到非常困惑。我是一名电子工程师,对 .Net 框架知识非常匮乏,请多多关照。

我的当前项目是心率监测器,可以将测量到的心率存储到 EEPROM 中,以便发送到电脑后进行后续日志查看。

我正在使用 RS-232 (串行) 协议与 8 位微控制器进行接口。每当我向微控制器发送字符 "l",它都会以以下格式向我返回一些信息:

0x1E 0x21 0x01 0x13 0x14 0x35 0x46 0x1E 0x21 0x01 0x13 0x14 0x43 0x48 0x0A 0x0D

空格仅用于信息目的,这些字节彼此不分。

从微控制器发送的这些8位HEX值包括记录信息的起始值0x1E,以DD MM YY HH MM格式表示的日期和时间,以及记录的心率。当所有记录回显时,会发送0x0A和0x0D字符。

例如,上面的代码表示:

Record start.
21.01.13 14:35
Heart Rate: 70
Record start.
21.01.13 14:43
Heart Rate: 72
End of records.

我该如何获取类似于"S210113143570S210113144372"这样的字符串值,其中S可以是任意字符。随后,我将对其应用正则表达式语法,并将其分组以便将这些值添加到listview控件中。

在评论和答案之后进行编辑:

我的示例没有写错。不幸的是,编码与上述完全相同。


你能展示相关的代码片段吗? - Nasmi Sabeer
看起来日期和时间部分没有以 HEX 的形式发送,是吗? - Abdusalam Ben Haj
我想知道为什么您将节拍率视为十六进制,而将其他信息视为字符串。这似乎不太合适(请将其作为一位电气工程师的旁注)。 - daryal
@MichaelViktorStarberg 谢谢 :) 但是 RegExp 不在这个问题的范围内。我可以自己处理它。 - abdullah kahraman
@daryal 你是对的。我现在明白你的意思了。 - abdullah kahraman
显示剩余3条评论
4个回答

5

实际上,每个字节都代表一个数字。我假设你已经有了一个包含这些值的byte[]数组:

var data = new byte[] { 0x1E, 0x21, 0x01, 0x13, 0x14, 0x35, 0x46,
                        0x1E, 0x21, 0x01, 0x13, 0x14, 0x43, 0x48, 0x0A, 0x0D };

现在你可以像这样创建真实的对象:

class LogEntry
{
    public DateTime Timestamp { get; set; }
    public int HeartRate { get; set; }
}

var logEntries = new List<LogEntry>();

for(int i = 0; i < data.Length; i+= 7)
{
    if(data[i] == 0x0a && data[i + 1] == 0x0d)
        break;
    if(data[i] != 0x1e)
        throw new InvalidDataException();

    var logEntry = new LogEntry();
    var year = BcdToDecimal(data[i + 3]) + 2000;
    var month = BcdToDecimal(data[i + 2]);
    var day = BcdToDecimal(data[i + 1]);
    var hour = BcdToDecimal(data[i + 4]);
    var minute = BcdToDecimal(data[i + 5]);
    var heartRate = data[i + 6];
    logEntry.Timestamp = new DateTime(year, month, day, hour, minute, 0);
    logEntry.HeartRate = heartRate;
    logEntries.Add(logEntry);
}

byte BcdToDecimal(byte bcdValue)
{
    return (byte)((bcdValue / 16 * 10) + (bcdValue % 16));
}

该方法 BcdToDecimal 将BCD转换为它们的实际值。

你在哪里将这些HEX值转换为整数? - Abdusalam Ben Haj
1
@abdullahkahraman:在这里你不能使用常规的数学计算,因为我们正在使用整型变量。所有的计算都是用整数进行的,即使中间结果也是整数。这意味着19/16等于1。乘以10的结果是10,加上模数的3的结果是13,正如预期的那样。我在发布代码之前实际测试了它,所以请放心,这个转换是正确的。 - Daniel Hilgarth
1
@abdullahkahraman:然而,如果您更喜欢使用自己的代码,也可以这样做。结果是相同的,并且可以在C#中无需更改地使用。 - Daniel Hilgarth
1
@abdullahkahraman:为什么这让人沮丧?你典型的.NET应用程序不需要这种类型的转换,因为开发此类转换非常简单,所以它没有包含在.NET框架中。 另外,请阅读此文 ,了解为什么某个功能未被实现。 最后但并非最不重要的是,有一个庞大的.NET社区为各种东西提供库。 我相信肯定存在一个具有BCD转换的库。 但是,由于它非常简单易懂,所以实现它的速度比搜索库还要快。 - Daniel Hilgarth
1
@abdullahkahraman:没问题。我只是想提供一些背景和上下文,解释为什么不能期望框架中有每一个功能。 - Daniel Hilgarth
显示剩余9条评论

0

兄弟,我认为你应该考虑使用字符串,即

string heartRate=70;
string recordStart=21.01.13 14:35;
string fullValue = heartRate + '|' + recordStart;

现在,您可以使用split方法轻松地拆分字符串,而不是应用正则表达式,例如:

string splittedValues[]=fullValue.Split('|');

当需要时,您将获得这些值,例如:

splittedValues[0] \\it will be heard rate string (at index zero)
similarly
splittedValues[1] \\it will be record start string (at index one)

我仍然不理解您的问题,如果我的回答无关,请告诉我,我会进行澄清。


很遗憾,由于我正在使用一款8位微控制器,所以这些东西非常底层。使用字符串将会花费我大量宝贵的时钟周期。不过还是感谢你的努力。 - abdullah kahraman

0
public static String ParseData(String data)
{
    MatchCollection matches = Regex.Matches(data, "0[xX]([a-fA-F0-9]{2})");

    Int32 count = 0;
    String result = String.Empty;

    foreach (Match match in matches)
    {
        switch (count)
        {
            case 0:
            {
                if (match.Value.Equals("0x1E", StringComparison.OrdinalIgnoreCase))
                {
                    result += "S";
                    break;
                }

                goto End;
            }

            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                result += match.Groups[1].Value;
                break;

            case 6:
                result += Int32.Parse(match.Groups[1].Value, NumberStyles.HexNumber).ToString();
                count = -1;
                break;
        }

        ++count;
    }

    End:;

    return result;
}

抱歉如果我表达不清楚,但是符号0x0F是用来表示8位十六进制值的。 - abdullah kahraman
这会返回你期望的结果。"0x1E0x210x010x130x140x350x460x1E0x210x010x130x140x430x480x0A0x0D" 返回 "S210113143570S210113144372"。 - Tommaso Belluzzo
那么我应该使用哪种方法从串口读取这些数据呢?因为我的输入不是像0x1E0x210x010x130x140x350x460x1E0x210x010x130x140x430x480x0A0x0D这样的字符串。 - abdullah kahraman
...这些从微控制器发送的8位HEX值。 - abdullah kahraman
别担心,放轻松。我只是想知道它是哪种格式。 - Tommaso Belluzzo

0

非常抱歉我犯了一个非常愚蠢的错误。我发现在微控制器端执行这个操作非常容易且不会占用太多时钟周期。现在我已经完成了这个操作,解析数值变得非常容易。

我在微控制器端使用了以下例程:

unsigned char BCDtoDecimal(unsigned char bcd_number)
{
  return ((bcd_number>>4)*10 + (bcd_number&0x0F));
}

所以,在 C# 方面,代码非常简单:

    private void buttonGetLogs_Click(object sender, EventArgs e)
    {
        string inputBuffer;
        char[] charArray;
        try
        {
            serialPort.Write("l");
            inputBuffer = serialPort.ReadLine();
            charArray = inputBuffer.ToCharArray();
            inputBuffer = string.Empty;
            foreach (char item in charArray)
            {
                inputBuffer += Convert.ToInt32(item).ToString();
            }
        }
        catch (Exception) { }
    }

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