Считать числовые данные из текстового SPICE файла и записать их в свои переменные - C#

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток!...возникла такая проблемка: имеется текстовый файл формата SPICE (пример ниже): .model 2T3107E PNP (Is=991.3f Xti=3 Eg=1.11 Vaf=35 Bf=210 Ne=1.58 + Ise=8.12p Ikf=80m Xtb=1.5 Br=2.86 Nc=2 Isc=100p Ikr=80m Rc=7 + Cjc=7.37p Vjc=.7 Mjc=.333 Fc=.5 Cje=10.6p Vje=.75 Mje=.3333 + Tr=80p Tf=113p Itf=8m Vtf=50 Xtf=1.2) Нужно прочитать из такого файла ЧИСЛОВЫЕ значения параметров элемента (в данном случае описание модели транзистора) и записать каждый параметр в свою переменную, например: значение Is=991.3f в переменную, допустим, double IS, Xti=3 в переменную double Xti и т. д. Особенности задачи определяются особеннностями синтаксиса языка SPICE, а именно: а) параметры, которые необходимо записать в переменную заключены в круглые скобки; они (скобки) - ОБЯЗАТЕЛЬНЫЙ элемент синтаксиса модели; б) между наименованием параметра, знаком "равно" (знак "равно" является обязательным элементом синтаксиса) и числовым значением пробелов может не быть, может быть один или несколько, например: Is=991.3f или Is =991.3f или Is= 991.3f или Is = 991.3f и т. д.; в) распознать и определить множитель по буквенному индексу, например Ise=8.12p (пико-) это 8,12 умноженное на 10^-9 (т. е. занести в переменную double Ise = 8,12 / 10^9); Ikr=80m это 80 мили-, т .е. в переменную занести double Ikr=80 / 10^3 и т. д.; г) между собой параметры ВСЕГДА разделены НЕ менее чем одним пробелом (больше одного возможно); д) целая и дробная части числа могут разделяются как точкой, так и запятой, например: может быть так Br=2.86 или так Br=2,86 - при записи в переменную точки заменить на запятые; е) при отсутствии у числа целой части - нуль в начале записи может присутствовать, а может и нет, например: может быть так Mjc=.333 или вот так Mjc=0.333 - при записи в перемнную автоматически подставлять "недостающий" нуль; ж) последовательность перечисления параметров внутри круглых скобок - произвольная; Дополнительные пояснения: а) знак "плюс" - перенос строки (при чтении параметров игнорируется); б) описание модели ВСЕГДА начинается с выражения ".model", а заканчивается закрывающей скобкой; в) круглых скобок (с параметрами) всегда один "комплект". Хотелость бы посмотреть похожий пример, причем не обязательно для SPICE, это может просто поиск в текстовом файле каких-нибудь именованных величин с их последующем занесем в переменные или, возможно, кто-то сможет показать (на примере одного-двух параметров) как реализовать поставленные задачи. Заранее благодарен.

Решение задачи: «Считать числовые данные из текстового SPICE файла и записать их в свои переменные»

textual
Листинг программы
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
 
namespace ConsoleApplication2
{
    class Program
    {
        private static string Data = @".model 2T3107E PNP (Is=991.3f    Xti=   3 Eg   =1.11 Vaf  =  35                         
+Bf=210 Ne=1.58
+ Ise=8.12p Ikf=80m Xtb=1.5 Br=2.86 Nc=2 Isc=100p Ikr=80m Rc=7
+ Cjc=7.37p Vjc=.7 Mjc=.333 Fc=.5 Cje=10.6p Vje=.75 Mje=.3333
+ Tr=80p Tf=113p Itf=8m Vtf=50 Xtf=1.2)
.model Q2N2222A NPN (IS=14.34F XTI=3 EG=1.11 VAF= 74.03 BF=255.9 NE=1.307 ISE=14.34F IKF=.2847 XTB=1.5 BR=6.092 NC=2 ISC=0 IKR=0 RC=1 CJC=7.306P MJC=.3416 VJC=.75 FC=.5 CJE=22.01P MJE=.377 VJE=.75 TR=46.91N TF=411.1P ITF=.6 VTF=1.7 XTF=3 RB=10)";
 
        private static void Main(string[] args)
        {
            var ms = new StreamWriter(new MemoryStream());
            ms.Write(Data);
            ms.Flush();
            ms.BaseStream.Position = 0L;
 
            var sp = new SpiceParser(ms.BaseStream);
        }
    }
 
    public class SpiceModelParam
    {
        public SpiceModelParam()
        {
        }
 
        public SpiceModelParam(string name, float value = 0f)
        {
            Name = name;
            Value = value;
        }
 
        public string Name { get; set; }
        public float Value { get; set; }
 
        public override string ToString()
        {
            return string.Format("{0} = {1}", Name, Value);
        }
    }
 
    public class SpiceModel
    {
        public SpiceModel()
        {
            Parameters = new List<SpiceModelParam>();
        }
 
        public SpiceModel(string name)
            : this()
        {
            Name = name;
        }
 
        public string Name { get; set; }
        public List<SpiceModelParam> Parameters { get; private set; }
 
        public override string ToString()
        {
            return string.Format("{0} [{1}]", Name, Parameters.Count);
        }
    }
 
    public class SpiceParser
    {
        private const string ModelID = ".model";
        private StreamReader mReader;
 
        public SpiceParser(Stream stream)
        {
            if (!stream.CanRead || !stream.CanSeek)
                throw new Exception();
 
            mReader = new StreamReader(stream);
            Models = new List<SpiceModel>();
            Parse();
        }
 
        public List<SpiceModel> Models { get; private set; }
 
        private void Parse()
        {
            while (!mReader.EndOfStream)
            {
                var line = ReadFullModel();
 
                Models.Add(ParseModel(line));
            }
        }
 
        private string ReadFullModel()
        {
            var sb = new StringBuilder();
 
            while (true)
            {
                var line = mReader.ReadLine();
                sb.Append(line);
 
                if (line.EndsWith(")"))
                    break;
            }
 
            return sb.ToString();
        }
 
        unsafe private void FixLine(char* ptr, int len)
        {
            var end = ptr + len;
 
            while (ptr != end)
            {
                if (*ptr == '+' || *ptr == '\n' || *ptr == '\r')
                    *ptr = ' ';
 
                ptr++;
            }
        }
 
        unsafe private SpiceModel ParseModel(string line)
        {
            int offset = 0;
 
            if (!line.StartsWith(ModelID))
                return null;
 
            offset += ModelID.Length + 1;
            var model = new SpiceModel();
 
            fixed (char* ptr = line)
            {
                FixLine(ptr, line.Length);
                char* pName = ptr + offset;
                pName = ParseModelName(pName, model);
 
                if (*pName == '(')
                    ParseParams(++pName, model);
            }
 
            return model;
        }
 
        unsafe private char* ParseModelName(char* pName, SpiceModel model)
        {
            int i = 0;
 
            for (; pName[i] != '('; ++i)
                ;
 
            model.Name = new string(pName, 0, i - 1);
 
            return pName + i;
        }
 
        unsafe private void ParseParams(char* ptr, SpiceModel model)
        {
            while (true)
            {
                var p = new SpiceModelParam();
 
                ptr = ParseParamName(ptr, p);
                ptr = ParseParamEqual(ptr);
                ptr = ParseParamValue(ptr, p);
                model.Parameters.Add(p);
 
                if (*ptr == ')')
                    return;
                else
                    ptr++;
            }
        }
 
        private const float P = -1 * 10f * 10f * 10f * 10f * 10f * 10f * 10f * 10f * 10f;
        private const float M = -1f * 10f * 10f * 10f;
        private readonly char DecimalSeparator = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator[0];
 
        unsafe private float ParseParamFactor(char* ptr)
        {
            switch (*ptr)
            {
                case 'p':
                case 'P':
                    return P;
                case 'm':
                case 'M':
                    return M;
                default:
                    return 1f;
            }
        }
 
        unsafe private char* ParseParamValue(char* ptr, SpiceModelParam p)
        {
            int i = 0;
 
            while (*ptr == ' ')
                ptr++;
 
            while (true)
            {
                // Если . или , то заменяем её на символ
                // который применяется в текущей локализации
                if (ptr[i] == '.' || ptr[i] == ',')
                {
                    ptr[i] = DecimalSeparator;
                }
                // Если текущий символ не цифра, то завершаемся
                else if (!(ptr[i] >= '0' && ptr[i] <= '9'))
                    break;
 
                i++;
            }
 
            var str = new string(ptr, 0, i);
            p.Value = float.Parse(str);
            ptr += i;
 
            if (*ptr != ' ')
                p.Value *= ParseParamFactor(ptr);
 
            return ptr;
        }
 
        unsafe private char* ParseParamEqual(char* ptr)
        {
            // Пропускаем пробелы
            while (*ptr == ' ')
                ptr++;
 
            if (*ptr != '=') // Проверка корректности позиции
                throw new Exception();
 
            return ++ptr;
        }
 
        unsafe private char* ParseParamName(char* ptr, SpiceModelParam p)
        {
            int i = 0;
 
            // Пропускаем пробелы
            while (*ptr == ' ')
                ptr++;
 
            // Имя параметра, до пробела или =
            while (ptr[i] != ' ' && ptr[i] != '=')
                i++;
 
            p.Name = new string(ptr, 0, i);
 
            // Перемещаемся за название параметра
            return ptr + i;
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 3.667 из 5
Похожие ответы