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

时间:2011-06-20 22:56:45

标签: c# .net string text-parsing

我有一个输入字符串,如下所示:

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”和“readString”等服务。我最终会喜欢这样的东西:

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

在这种情况下看起来并没有那么多改进,但我的实际对象模型有点复杂。我知道其他语言有这样的设施,但我不记得任何.net库只是从字符串的前面读取。

4 个答案:

答案 0 :(得分:1)

这可能会好一点:

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

答案 1 :(得分:1)

我建议你为此目的使用正则表达式。这是一个例子:

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]);
}

将打印:

Number: 4        Person: Bob
Number: 32       Person: Joe
Number: 64       Person: Sue
Number: 123      Person: Bill

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

[Number][Space][Letters]一次或多次,对吗?这正是它的含义:
(\d+) ([a-zA-Z]+)

编辑1:
在这一刻,我真的不知道你是否想要将每个人之前或之后的数字联系到每个人,但你所要做的就是交换上面的模式,所以它将成为:

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

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

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

所以你要匹配一个数字(\d+),然后是一个空格(),然后匹配你之前匹配的那个(Name Number Name Number ...

答案 2 :(得分:1)

您可以自己轻松编写这样的“图书馆”:

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());
    }
}

答案 3 :(得分:1)

尝试从队列中读取,它可能更清洁一点:

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());

您应该在其中添加各种防护,以避免尝试将空队列出列并使转换无效。