【问题标题】:How to write switch statement for a string type?如何为字符串类型编写 switch 语句?
【发布时间】:2016-09-06 06:01:06
【问题描述】:

我用串口连接了一个设备,它返回给我“:GS#”字符串。经过长时间的检查,我几乎可以确定问题出在 切换条件,即我的程序从不输入 case 并且总是默认。我在文本框中打印了收到的字符串,它是 ":GS#" !我很困惑。我的错误在哪里?

这是我的代码:

char[] lxCMD = new char[8];
.
.
.

private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
  serialPort.Read(lxCMD, 0, lxCMD.Length);
  this.Invoke(new EventHandler(UpdateVar));
        }

private void UpdateVar(object sender, EventArgs e)
{
  string strRecieved = "Ack";
  if (lxCMD[0] != 0x6)
  {
    strRecieved = new string(lxCMD);
  }
  textBox1.AppendText(strRecieved);  // This line prints :GS# correctly!
  textBox1.AppendText(Environment.NewLine);
  switch(strRecieved)
    {
      case ":GS#":
          serialPort.Write("20:08:18#");
          textBox1.AppendText("1:");  
          textBox1.AppendText(Environment.NewLine);
              break;
       case "Ack":
          serialPort.Write("1");
          textBox1.AppendText("2:");
          textBox1.AppendText(Environment.NewLine);
              break;
       default:
          textBox1.AppendText("Nothing");
              break;

            }

        }

【问题讨论】:

  • 您的字符串中是否添加了任何控制字符?也许你应该在切换之前对其进行消毒。
  • 字符串末尾是否有空格或不可打印字符?鉴于您的 char[] 长度为 8 个字符,字符串也可能是该长度。
  • 没有理由不应该工作,除非你没有收到确切的:GS#。检查未打印字符的字符串长度等内容。
  • 我通过终端 v1.93b 进行了检查。十六进制字符串是 3A 47 53 23 与 ":GS#" 完全匹配。
  • @Pana - 检查字符串的长度。 .NET 不使用以空值结尾的字符串。

标签: c# winforms switch-statement


【解决方案1】:

正如 cmets 中所指出的,您保存读取字节的 char 数组长度为 8 个字符。因此,当您将该数组转换为字符串时,它会创建一个长度为 8 的字符串,您可以通过调用 strRecieved.Length 来检查它,例如:

textBox1.AppendText(strRecieved);  // This line prints :GS# correctly!         
textBox1.AppendText(Environment.NewLine);
Console.Out.WriteLine(strRecieved.Length); //or any other means of output - will output 8

这意味着字符串中有一些不可打印的字符(ASCII 表为空)。因此案件不匹配!

由于串行端口的Read 方法返回读取的字节数,请尝试使用它来获取正确的子字符串。例如(我认为这应该可行):

char[] lxCMD = new char[8];
var bytesRead = 0; 
.
.
.

private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
  bytesRead = serialPort.Read(lxCMD, 0, lxCMD.Length);
  this.Invoke(new EventHandler(UpdateVar));
        }

private void UpdateVar(object sender, EventArgs e)
{
  string strRecieved = "Ack";
  if (lxCMD[0] != 0x6)
  {
    strRecieved = new string(lxCMD);
    strRecieved = strRecieved.SubString(0, bytesRead)
  }
  textBox1.AppendText(strRecieved);  // This line prints :GS# correctly!
  textBox1.AppendText(Environment.NewLine);
  switch(strRecieved)
    {
      case ":GS#":
          serialPort.Write("20:08:18#");
          textBox1.AppendText("1:");  
          textBox1.AppendText(Environment.NewLine);
              break;
       case "Ack":
          serialPort.Write("1");
          textBox1.AppendText("2:");
          textBox1.AppendText(Environment.NewLine);
              break;
       default:
          textBox1.AppendText("Nothing");
              break;

            }

        }

【讨论】:

  • 现在可以使用了!但有时bytesRead 的值是1,strRecieved 是“:”,然后是bytesRead = 3 和strRecieved = GS#。为什么有时会出现中断?串口是否有一些参数需要设置以避免中断?
【解决方案2】:

将 if 语句中的字符串 strRecieved 初始化更改为:

strRecieved = new string(chars.TakeWhile(c => c != '\0').ToArray());

问题是,如果输入的长度不是 8,则 char 数组最后会包含多个 \0 字符。

下面的测试证明了这一点:

[Test]
    public void stringConstructor_CharArrayWithSomeEmptyValues_StringWithoutEmptyValues()
    {
        var expected = "test";
        var chars = new char[expected.Length+42];
        chars[0] = expected[0];
        chars[1] = expected[1];
        chars[2] = expected[2];
        chars[3] = expected[3];
        var str = new string(chars.TakeWhile(c => c != '\0').ToArray());

        Assert.AreEqual(expected, str);
        str = new string(chars,0,chars.Length);
        Assert.AreNotEqual(expected, str);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-26
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2021-12-19
    • 1970-01-01
    • 2013-04-06
    相关资源
    最近更新 更多