Я писал уже про то как получал данные от компрессора в своем блоге и потом чуть больше на хабре. Речь сейчас идет больше за первый описываемый компрессор, где данные передаются в виде строки. Недавно мне пришлось немного менять его код и я увидел что он "несколько странный" - преобразование строки в массив строк происходит через поиск первого символа разделителя ( в моем случае ";" ) а затем сокращение строки на количество символов до этого разделителя и затем повтор по циклу. Причем в первоначальном варианте был жестко привязан размер массива на 35 элементов, что потом вылезло в проблемы, которые пришлось решать - по какой-то причине количество элементов сократилось и цикл стал выходить за диапазон индекса массива:
воскресенье, 15 октября 2023 г.
Преобразование строки в массив чисел float
string answer = req.ResponseText;
answer = answer.Replace("&", ";");
float[] strarr = new float[35];
for (int i = 0; i< 35; i++)
{
int position = answer.IndexOf(";");
string str = answer.Substring(0,position);
strarr [i] = float.Parse(str, CultureInfo.InvariantCulture.NumberFormat);
answer = answer.Substring(position+1);
}
Для этого добавил счетчик элементов по количеству встречаемых символов ";" и чтобы не добавлять пустую строку в конце сделал еще и условие позиции этого символа:
string answer = req.ResponseText;
answer = answer.Replace("&", ";");
int count = 0;
foreach (char c in answer) if (c ==';') count++;
float[] strarr = new float[count+1];
int position = 0;
int i = 0;
do
{
position = answer.IndexOf(";");
if (position>0) {
string str = answer.Substring(0,position);
strarr [i] = float.Parse(str, CultureInfo.InvariantCulture.NumberFormat);
answer = answer.Substring(position+1);
i++;
}
}
while (position>0);
Это избавило от ошибки выхода за границы массива, но не сделало код красивее и проще, и тем более оптимальнее, почему в тот раз не обратился к конструкции Split я не помню, но в этот раз решил исправить, но правда без нюансов не обошлось - последний элемент массива строк пустой, и из-за этого преобразование во float выдавало ошибку
string answer = req.ResponseText;
answer = answer.Replace("&", ";");
string[] strarr = answer.Split(';');
float[] floarr = new float[strarr.Length];
if (strarr.Length > 1)
{
for (int i = 0; i < strarr.Length-1; i++)
{
floarr[i] = float.Parse(strarr[i], CultureInfo.InvariantCulture.NumberFormat);
}
}
Кстати этот код можно упростить удалив строку с Replace, а все потому что метод Split может разделять строку по нескольким разделителям, то есть нужно задать там ; и & чтобы разделить на массив. Также этот код можно упростить используя Array.ConvertAll, но я так долго разбирался с тем почему происходит ошибка даже на таком элементарном коде который выше, что решил что ну его нафиг, пусть остается так, лучше напишу просто заметку об этом и скину ссылку как еще можно преобразовать массив. Вообще было бы еще интересно сравнить какое преобразование оптимальнее, чтобы точно убедиться что лучше)), хотя оба кода работают нормально вцелом. Хотя опять же - нет никакой валидации на входе - если компрессор место числа выдаст какой-липо символ и пустоту, то в очередной раз будет ошибка и будет необходимость переписывать код...
PS не поленился и в онлайн режиме (на сайте майкрософт с описанием метода Split можно включить проверку кода) сделал компиляцию предыдущего случая и упрощенного до 3 строк кода, причем последний пустой элемент массива удаляется автоматически, используя перегрузку метода Split, о чем говорилось и в статье майкрософт:
string answer = req.ResponseText;
string[] strarr = answer.Split(new char[] { ';', '&' }, StringSplitOptions.RemoveEmptyEntries);
float[] floarr = Array.ConvertAll(strarr, s => float.Parse(s, CultureInfo.InvariantCulture.NumberFormat));
Вот и очередной лайфхак, как все это дело проверять - можно проверять онлайн, а редактором для блога использовать онлайн vscode))) отличная работа)
Чтобы проверить можно сделать так :
string answer = "95.460999;01;65.000000;99.811996&109.811996;01;75.000000";
string[] strarr = answer.Split(new char[] { ';', '&' }, StringSplitOptions.RemoveEmptyEntries);
float[] floarr = Array.ConvertAll(strarr, s => float.Parse(s, CultureInfo.InvariantCulture.NumberFormat));
foreach (var sub in floarr)
{
Console.WriteLine($"Substring: {sub}");
}
Подписаться на:
Комментарии к сообщению (Atom)
Комментариев нет:
Отправить комментарий