Самый простой способ прочитать один int с начала строки - PullRequest
3 голосов
/ 21 июня 2011

У меня есть строка ввода, которая выглядит примерно так:

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 ]

1 голос
/ 21 июня 2011

Попробуйте прочитать из очереди, это может быть немного чище:

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

Вам также следует добавить туда всевозможных охранников, чтобы не пытаться вывести из очереди пустую очередь и недопустимые преобразования.

1 голос
/ 21 июня 2011

Я предлагаю вам использовать регулярные выражения для этой цели. Вот пример:

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

1 голос
/ 21 июня 2011

Вы можете легко написать такую ​​«библиотеку» самостоятельно:

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());
    }
}
1 голос
/ 21 июня 2011

Это, наверное, немного лучше:

var strings = input.Split(' ');
for ( int i = 2; i < strings.length; i + 2 )
{
  ProcessPerson(strings[i - 1], Int32.Parse(strings[i]));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...