Очень нужна помощь, пожалуйста. Есть текст в 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());
}
}
}
Мне кажется, что разбивать строку на символы "вручную" и "вручную" их проверять не совсем корректно, лучше использовать методы 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.
Я бы предложил работать через формирование списка токенов на основе изучаемого текста.
Создадим такой интерфейс
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()));
}
Ну, а далее уже будет достаточно просто работать с коллекцией токенов.
Пример целиком здесь.
Делим по пробелам, убираем лишнее
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);
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Имеется 2 отрезкаОдин - типа Line, второй - динамический блок, внутри которого Polyline
Не могу получить ответ от сервера сокета для клиента на С#После вызова Receive происходит блокировка и не снимается, даже если я превышу количество...