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

发布于 2024-11-16 20:37:53 字数 690 浏览 5 评论 0原文

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

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 库可以简单地从字符串的前面读取。

I have an input string that looks something like this:

4 Bob 32 Joe 64 Sue 123 Bill 42

Where the 4 indicates the number of string integer pairs to follow. My current way of processing this looks something like this:

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

This feels quite cumbersome. Is there some library in C# that can wrap a string and give me services like "readInt" and "readString". I would ultimately like to have something like:

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

It doesn't look like that much of an improvement in this case, but my actual object model is a bit more complicated. I know other languages have facilities to o things like this, but I can't recall any .net libraries to simply read from the front of a string.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眉目亦如画i 2024-11-23 20:37:53

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

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

You could easily write such a “library” yourself:

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

If the string could be large, or you are reading it from a stream, you have to do the splitting yourself:

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());
    }
}
随风而去 2024-11-23 20:37:53

这可能会好一点:

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

This is probably a little better:

var strings = input.Split(' ');
for ( int i = 2; i < strings.length; i + 2 )
{
  ProcessPerson(strings[i - 1], Int32.Parse(strings[i]));
}
栩栩如生 2024-11-23 20:37:53

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

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

will print:

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 ...

I suggest you using Regular Expressions for that purpose. Here is an example:

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

will print:

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

When using Regular Expressions, all you need to know is how to express the pattern you want to match. In this case, you want to match:

[Number][Space][Letters] one or more times, right? That's exactly what it means:
(\d+) ([a-zA-Z]+)

Edit 1:
In this moment, I don't really know if you want to associate to each person the number that is before or after each one, but all you have to do is swap the above pattern, so it will become:

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

Edit 2:
If you want to skip the first number, you can use this pattern:

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

so you're matching a number (\d+), then a space (), and then the same you were matching before (Name Number Name Number ...)

萌辣 2024-11-23 20:37:53

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

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

如果您向队列添加扩展方法,您可以进一步简化(未经测试):

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

ProcessPerson(queue.DequeueInt(), queue.Dequeue());

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

Try reading from a queue, it could be a bit cleaner:

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

If you add extension methods to Queue you can simplify this further (untested):

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

ProcessPerson(queue.DequeueInt(), queue.Dequeue());

You should add all kinds of guards in there as well to avoid trying to dequeue an empty queue and invalid conversions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文