从字符串前面读取单个int的最简单方法

本文关键字:最简单 方法 int 单个 字符串 前面 读取 | 更新日期: 2023-09-27 18:00:03

我有一个输入字符串,看起来像这样:

4 Bob 32 Joe 64 Sue 123 Bill 42

其中,4表示要跟随的字符串整数对的数量。我目前的处理方式是这样的:

var strings = input.Split(' ');
int count = Int32.Parse(strings[0]);
for ( int i = 0; i < count; i++ )
{
  string name = strings[count*2 + 1];
  int number = Int32.Parse(strings[count*2 + 1]);
  ProcessPerson(name, number);
}

这感觉很麻烦。C#中是否有一些库可以包装字符串并为我提供诸如"readInt"answers"readString"之类的服务。我最终想拥有这样的东西:

int count = input.ReadInt();
for(int i = 0; i<count; i++)
{
  ProcessPerson(input.ReadString(), input.ReadInt());
}

在这种情况下,它看起来没有太大的改进,但我的实际对象模型有点复杂。我知道其他语言也有类似的功能,但我不记得有任何.net库可以简单地从字符串的前面读取。

从字符串前面读取单个int的最简单方法

您可以轻松地自己编写这样一个"库":

class Parser
{
    private readonly Queue<string> m_parts;
    public Parser(string s)
    {
        m_parts = new Queue<string>(s.Split(' '));
    }
    public string ReadString()
    {
        return m_parts.Dequeue();
    }
    public int ReadInt32()
    {
        return int.Parse(ReadString());
    }
}

如果字符串可能很大,或者你正在从流中读取它,你必须自己进行拆分:

class StreamParser
{
    private readonly TextReader m_reader;
    public StreamParser(string s)
        : this(new StringReader(s))
    {}
    public StreamParser(TextReader reader)
    {
        m_reader = reader;
    }
    public string ReadString()
    {
        var result = new StringBuilder();
        int c = m_reader.Read();
        while (c != -1 && (char)c != ' ')
        {
            result.Append((char)c);
            c = m_reader.Read();
        }
        if (result.Length > 0)
            return result.ToString();
        return null;
    }
    public int ReadInt32()
    {
        return int.Parse(ReadString());
    }
}

这可能要好一点:

var strings = input.Split(' ');
for ( int i = 2; i < strings.length; i + 2 )
{
  ProcessPerson(strings[i - 1], Int32.Parse(strings[i]));
}

我建议您为此使用正则表达式。这里有一个例子:

string input = "4 Bob 32 Joe 64 Sue 123 Bill";
var matches = Regex.Matches(input, @"(?:('d+) ([a-zA-Z]+))+");
for (int i = 0; i < matches.Count; i++)
{
    Console.WriteLine("Number: {0} 't Person: {1}", matches[i].Groups[1], matches[i].Groups[2]);
}

将打印:

人数:4人:Bob人数:32人:Joe电话:64人:苏号码:123人:Bill

使用正则表达式时,您只需要知道如何表达要匹配的模式。在这种情况下,您需要匹配:

[Number][Space][Letters]一次或多次,对吧?这正是它的意思:
('d+) ([a-zA-Z]+)

编辑1:
在这一刻,我真的不知道你是想把每个人之前还是之后的号码联系起来,但你所要做的就是交换上面的模式,所以它会变成:

(?:([a-zA-Z]+) ('d+))+

编辑2:
如果你想跳过第一个数字,你可以使用这个模式:

'd+ (?:([a-zA-Z]+) ('d+))+

所以你匹配的是一个数字('d+),然后是一个空格(),然后和你之前匹配的一样(CCD_5)

尝试从队列中读取,它可能会更干净:

var s = "4 Bob 32 Joe 64 Sue 123 Bill 42";
var queue = new Queue(s.Split(' '));
var count = Convert.ToInt32(queue.Dequeue());
while (queue.Count != 0)
{
    var name = queue.Dequeue();
    var number = Convert.ToInt32(queue.Dequeue());
    ProcessPerson(name, number);
}

如果将扩展方法添加到Queue,则可以进一步简化(未经测试):

public static class QueueExtensions {
    public static int DequeueInt(this Queue<string> queue) {
        return Convert.ToInt32(queue.Dequeue());
    }
}
ProcessPerson(queue.DequeueInt(), queue.Dequeue());

您还应该在其中添加各种保护,以避免试图将空队列和无效转换出列。