char to string c#

536
05 августа 2021, 12:30

Очень нужна помощь, пожалуйста. Есть текст в richtextbox, который превращаю в массив символов. Дальше нужно пройтись по всему массиву символов и проверить нет ли знаков (можно только буквы, если знак удалить, я пока добавляю в textbox), затем нужно добавить в datagrid слово, которое состоит из букв без иных знаков (в нижнем регистре). Проблема в том, что добавляется в datagrid в одну строку все слова и склеенные. Понимаю, что нужно разделить по пробелу, но так тоже не получается вывести нормально по одному слову в одну строку datagrid. Вот код:

...
string word;
    string str;
    private DataGridViewRow row;
    public Form1()
    {
        InitializeComponent();
        var col1 = new DataGridViewTextBoxColumn();
        dataGridView1.Columns.AddRange(col1);
    }
    private void button1_Click(object sender, EventArgs e)
    {
        Word();
    }
    public bool Oper(char v)
    {
        if (("№:;'+-/*@^<>~`()%$ ={}&?!.,--#0123456789".IndexOf(v) != -1))
            return true;
        return false;
    }
    public void Word()
    {
        char[] lines = richTextBox1.Text.ToCharArray();
        foreach (var s in lines)
        {
            if (!Oper(s) && s != ' ')
            {
                word += s;
            }
            else
            {
                textBox1.Text = textBox1.Text + s;
            }
        }
        dataGridView1.Rows.Add(word.ToString().ToLower());
    }
}

}

Answer 1

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

Я посидел 2 минуты и сделал такую функцию (расширение):

public static class Extensions
{
    public static string[] SplitOnWords(this string text)
    {            
        text = string.Join("", text.Select(symbol => Char.IsLetter(symbol) ? symbol : ' ')); // заменяет "небуквы" на пробел
        text = text.Trim().Replace("  ", " ").ToLower(); // удаляет лишние пробелы и переводит строку в нижний регистр          
        return text.Split(new char[] { ' ' }); // разделяет строку на слова
    }
}

Она возвращает массив слов, которые можно будет присвоить dataGridView1 в цикле foreach по нажатию кнопки:

var words = richTextBox1.Text.SplitOnWords();
foreach (var word in words)
{
    dataGridView1.Rows.Add(word);
}

Про метод .Select.

Answer 2

Я бы предложил работать через формирование списка токенов на основе изучаемого текста.

Создадим такой интерфейс

public interface IToken
{
    //значение токена
    string Value { get; }
    //позиция первого символа токена в тексте
    int Position { get; }
    //название токена
    string TokenName { get; }
    //инфо для отображения
    string TokenValue { get; }
}

Вот пример класса для токена Пробела

public class SpaceToken : IToken
{
    public string Value { get; }
    public int Position { get; }
    public string TokenName { get; }
    public string TokenValue => $@"[{TokenName}:{Position}]";
    public SpaceToken(int position)
    {
        Position = position;
        Value = " ";
        TokenName = "space";
    }
    public override string ToString()
    {
        return TokenName;
    }
}

А это для токена слова

public class WordToken : IToken
{
    public string Value { get; }
    public int Position { get; }
    public string TokenName { get; }
    public string TokenValue => $"<{Value}:{Position}:{OrderNumber}>";
    public int OrderNumber { get; }
    public WordToken(int position, string value, int orderNumber)
    {
        Position = position;
        Value = value.ToLower();
        TokenName = "word";
        OrderNumber = orderNumber;
    }
    public override string ToString()
    {
        return Value;
    }
}

Тогда текст можно превратить в токены так

public List<IToken> GetTokens(string text)
{
    if (string.IsNullOrEmpty(text))
        throw new ArgumentException(nameof(text));
    //готовим результат
    List<IToken> tokens = new List<IToken>();
    //нумерация слов в тексте
    int wordsOrder = 0;
    //позиция первой буквы слова
    int wordPosition = 0;
    //для посимвольного набора слова
    List<char> wordChars = new List<char>();
    var chars = text.ToCharArray();
    for (int i = 0; i < chars.Length; i++)
    {
        //извлекаем текущий символ
        var current = chars[i];
        if (Char.IsLetter(current))
        {
            //если это первая буква слова
            if (wordChars.Count == 0)
            {
                wordPosition = i;
            }
            //вносим букву в массив слова
            wordChars.Add(current);
            //если это последний символ в тексте, т.е. текст заканчивается на слове
            //нужно добавить словный токен
            if (i + 1 == chars.Length)
            {
                AddWordToken(wordChars, wordPosition, tokens, ++wordsOrder);
            }
        }
        else
        {
            //т.е. текущий символ не относится к слову
            //и до этого у нас возможно собиралось слово
            //и его нужно закрывать и создавать словный токен
            if (wordChars.Count > 0)
            {
                AddWordToken(wordChars, wordPosition, tokens, ++wordsOrder);
                //очищаем для следующего слова
                wordChars.Clear();
            }
            //добавляем небуквенный токен
            AddNotLetterToken(tokens, i, current);
        }
    }
    return tokens;
}
private void AddWordToken(List<char> wordChars, int position, List<IToken> tokens, int wordsOrder)
{
    var array = wordChars.ToArray();
    var word = new String(array);
    tokens.Add(new WordToken(position, word, wordsOrder));
}
private void AddNotLetterToken(List<IToken> tokens, int i, char current)
{
    if (Char.IsWhiteSpace(current))
    {
        tokens.Add(new SpaceToken(i));
        return;
    }
    if (Char.IsDigit(current))
    {
        tokens.Add(new NumberToken(i, current.ToString()));
        return;
    }
    //если это не пробел и не цифра, значит это какой-то знак
    tokens.Add(new SignToken(i, current.ToString()));
}

Ну, а далее уже будет достаточно просто работать с коллекцией токенов.

Пример целиком здесь.

Answer 3

Делим по пробелам, убираем лишнее

var words = richTextBox1.Text.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
foreach (var word in words)
{
    var onlyLetters = new String(word.Where(c => char.IsLetter(c)).ToArray()).ToLower();
    if (!string.IsNullOrEmpty(onlyLetters))
        dataGridView1.Rows.Add(onlyLetters);
}
READ ALSO
Как корректно переместить блок через Matrix3d.Displacement?

Как корректно переместить блок через Matrix3d.Displacement?

Имеется 2 отрезкаОдин - типа Line, второй - динамический блок, внутри которого Polyline

141
Вывод прочтённого из сокета при достижении символа новой строки

Вывод прочтённого из сокета при достижении символа новой строки

Не могу получить ответ от сервера сокета для клиента на С#После вызова Receive происходит блокировка и не снимается, даже если я превышу количество...

395
как передать List как параметр?

как передать List как параметр?

как в extetion написать метод который принемает List?

279
Запрос SQL в LINQ

Запрос SQL в LINQ

Есть такой запрос SQL

130