• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

C# parsowanie wielu liczb z łańcucha

Object Storage Arubacloud
0 głosów
359 wizyt
pytanie zadane 13 stycznia 2020 w C# przez Mariusz M Obywatel (1,670 p.)
edycja 13 stycznia 2020 przez Mariusz M

Jakiś czas temu wygrzebałem w systemie Windows kompilator języka C# ale do tej pory

nie znalazłem dobrego samouczka do tego języka

Oto kod programu do rozwiązywania układów równań liniowych

 

using System;
using System.IO;
using System.Globalization;
namespace LUdecomposition
{
	class LUdecomposition
	{
		public const double ZERO = 1.0e-15;
		public static void Main()
		{
			char esc;
			string str,path;
			int i,j,n;
			double[,] A;
			double[] b;
			int[] p;
			double d;
			NumberFormatInfo nfi = new NumberFormatInfo();
			nfi.NumberDecimalSeparator = ".";
			Console.WriteLine("Podaj ścieżkę do pliku w którym chcesz zapisać wynik");
			path = Console.ReadLine();
			using(StreamWriter sw = new StreamWriter(path,true))
			{
				do
				{
					try
					{
						Console.Clear();
						Console.WriteLine("Rozwiązywanie układów równań liniowych metodą rozkładu macierzy LU = PA");
						Console.WriteLine();
						Console.WriteLine("Podaj liczbę równań n=");
						str = Console.ReadLine();
						int.TryParse(str,out n);
						A = new double[n,n];
						b = new double[n];
						p = new int[n];
						for(i = 0;i < n;i++)
						{
							Console.WriteLine("Wprowadz " + (i+1).ToString(nfi) + ". wiersz macierzy");
							for(j = 0;j < n;j++)
							{
								str = Console.ReadLine();
								double.TryParse(str,out A[i,j]);
							}
							Console.WriteLine("Wprowadz " + (i+1).ToString(nfi) + ". wyraz wolny");
							str = Console.ReadLine();
							double.TryParse(str,out b[i]);
						}
						FactorLU(n,A,p,out d);
						sw.WriteLine(d.ToString(nfi));
						for(i = 0;i < n && Math.Abs(d) > ZERO  ;i++)
						{
							for(j = 0;j < n; j++)
							{
								Console.Write(A[i,j].ToString(nfi)+" , ");
								sw.Write(A[i,j].ToString(nfi) + " , ");
							}
							Console.WriteLine();
							sw.WriteLine();
						}
						if(Math.Abs(d) <= ZERO)
						{
							SolveLU(n,A,p,b);
							for(i = 0;i < n && Math.Abs(d) > ZERO ;i++)
							{
								Console.WriteLine(b[i].ToString(nfi));
								sw.WriteLine(b[i].ToString(nfi));
							}
							Console.WriteLine();
							sw.WriteLine();
						}
					}
					catch(System.IndexOutOfRangeException e)
					{
						
					}
					esc = (char)Console.ReadKey().Key;
				}
				while(esc != (char)ConsoleKey.Escape);
			}
		}
		public static void FactorLU(int n,double[,] A,int[] p,out double d)
		{
			int k,i,j,l;
			double pmax,tmp;
			d = 1.0;
			for(k = 0;k < n ;k++)
			{
				pmax = Math.Abs(A[k,k]);
				l = k;
				for(j = k + 1;j < n; j++)
				{
					if(Math.Abs(A[j,k]) > pmax)
					{
						pmax = Math.Abs(A[j,k]);
						l = j;
					}
				}
				if(l != k)
				{
					for(j = 0;j < n; j++)
					{
						tmp = A[k,j];
						A[k,j] = A[l,j];
						A[l,j] = tmp;
					}
					d = -d;
				}
				d *= A[k,k];
				if(pmax <= ZERO)
					return ;	
				p[k] = l;
				for(i = k + 1; i < n; i++)
				{
					A[i,k]/=A[k,k];
					for(j = k + 1;j < n; j++)
						A[i,j] -= A[i,k]*A[k,j];
				}
			}
		}
		public static void SolveLU(int n,double[,] LU,int[] p,double[] b)
		{
			int i,k;
			double tmp;
			for(k = 0;k < n - 1; k++)
			{
				tmp = b[k];
				b[k] = b[p[k]];
				b[p[k]] = tmp;
			}
			for(k = 1;k < n; k++)
				for(i = 0; i < k; i++)
					b[k] -= b[i]*LU[k,i];
			for(k = n - 1; k >= 0; k--)
			{
				for(i = k + 1;i < n; i++)
					b[k] -= LU[k,i]*b[i];
				b[k] /= LU[k,k];
			}
		}
	}
}

 

Dotychczas dowiedziałem się jak wczytywać dane z pliku linia po linii do łańcucha

Przeglądając anglojęzyczne fora zobaczyłem że można użyć funkcji Split

do tego aby pociąć łańcuch a następnie iterując po utworzonej tablicy parsować elementy tej tablicy

funkcją TryParse

jednak wymaga ona utworzenia dodatkowej tablicy co sprawia że rozwiązanie nie jest optymalne pamięciowo

i szukam czegoś innego

 

 

 

komentarz 13 stycznia 2020 przez piotrsz109 Stary wyjadacz (13,730 p.)
Możesz iterować po każdym znaku i wtedy możesz sprawdzać, jeśli dany znak jest cyfrą to dajesz pętlę, która dodaje znaki do string'a, a potem parsujesz to, albo definiujesz dwa int'y i zaznaczasz indeksy pierwszej i ostatniej cyfry.
komentarz 13 stycznia 2020 przez Mariusz M Obywatel (1,670 p.)
W Pascalu (free pascal compiler) istnieją takie procedury jak

function Pos(

const substr:shortstring;
const s:shortstring;

):SizeInt;

function Copy(

     S:AStringType;

     index:SizeInt;

     count:SizeInt;

):string;

i myślałem nad tym aby wykorzystać jakieś analogiczne funkcje C#

 

Trzeba tylko sprawdzać czy dane w pliku są w odpowiedni sposób sformatowane

np z pierwszej linii wczytujemy liczbę równań

a w następnych liniach wczytywać wiersze macierzy oraz odpowiadającą im składową

wektora wyrazów wolnych

Tyle że trzeba sprawdzać czy z linii wczytanej do łańcucha da się wczytać odpowiednią

liczbę liczb oraz czy w pliku jest zapisana odpowiednia liczba wierszy macierzy

Funkcja TryParse jest ok tyle że parsuje tylko jedną liczbę

To funkcji Split chciałbym uniknąć bo to właśnie funkcja Split wymaga utworzenia dodatkowej tablicy
komentarz 23 stycznia 2020 przez Mariusz M Obywatel (1,670 p.)

@piotrsz109,
 a jakiś przykład takiego parsowania

komentarz 24 stycznia 2020 przez piotrsz109 Stary wyjadacz (13,730 p.)
IEnumerable<object> Parse(string t)
{
    int s1=0;
    for(int i=0;i<t.Length;i++)
    {
        if(Char.IsNumber(t[i])) s1=i;
        else s1=-1;
        while(Char.IsNumber(t[i])) i++;
        if(s1 >=0) yield return int.Parse(t.Substring(s1, i-s1);            //Zwraca liczby
        else if(!Char.IsWhitespace(t[i])) yield return t[i];                    //Zwraca znaki arytmetyczne
    }
}

Coś, mniej więcej tak

komentarz 25 stycznia 2020 przez Mariusz M Obywatel (1,670 p.)
Ja myślałem nad zastąpieniem funkcji Split funkcjami

Trim , IndexOf, Substring  i TryParse

Nie myślałem nad tym aby samodzielnie pisać funkcję Parse
komentarz 25 stycznia 2020 przez piotrsz109 Stary wyjadacz (13,730 p.)
To tylko taka nazwa. I twój pomysł, o ile dobrze myślę, jest dość podobny do mojego programu.

Jednak jak tak patrzę, to myślę, że moje rozwiązanie, jako że niższego poziomu, jest nieco bardziej optymalne od używania np.: IndexOf, bo iterowała by ona często od początku string'a, co w tym wypadku zbędne.

Pozdrawiam
komentarz 29 stycznia 2020 przez Mariusz M Obywatel (1,670 p.)
Przymiotnika optymalny już się nie stopniuje Coś albo jest optymalne albo nie
(To ma swoje źródła w łacinie bo skoro już przymiotnik jest w stopniu najwyższym to już nie potrzeba go stopniować)
Zdaje się że pomysł z IndexOf, oraz Substring  wykorzystywałem parę razy w Pascalu tylko tam procedury się inaczej nazywały

 

Czy twój pomysł zadziała także dla innych typów np double ?
komentarz 29 stycznia 2020 przez piotrsz109 Stary wyjadacz (13,730 p.)
Musiałbyś wziąć pod uwagę użycia kropki w warunku char.IsNumber. Wtedy dodajesz możliwość, że znak to kropka i wtedy zawsze parsujesz na double, a nie int'y, bo w razie czego dodasz możliwość zaokrąglania

1 odpowiedź

0 głosów
odpowiedź 23 stycznia 2020 przez Mariusz M Obywatel (1,670 p.)

Tak naprawdę chodziło mi o czytanie danych z pliku

Udało mi się jednak sprowadzić ten problem do parsowania wielu liczb z łańcucha

Oto przykład pliku który miałby być wczytany

6
1 0 0 0 0 0 0
0 1 -1 0 0 0 0 
2 0 0 -2 0 0 0
0 2 3 0 -3 0 0
1 0 0 2 0 -4 0
0 1 0 0 1 0 1

 

Jakiś czas temu znalazłem jak wczytywać taki plik linia po linii do łańcucha

using System;
using System.IO;
namespace FileApplication {
   class Program {
       static void Main(string[] args) {
           try{
              // Create an instance of StreamReader to read from a file.
              // The using statement also closes the StreamReader.
           string path;
           Console.ReadLine(path);
           using(StreamReader sr =newStreamReader(path)) {
              string line;

              // Read and display lines from the file until 
              // the end of the file is reached. 
             while((line = sr.ReadLine())!=null) {
               Console.WriteLine(line);
          }
        }
      }catch(Exception e) {
       // Let the user know what went wrong.
      Console.WriteLine("The file could not be read:");
      Console.WriteLine(e.Message);
    }
   Console.ReadKey();
 }
}
}


 

I teraz nie wiem jak parsować te dane z łańcucha

W Pascalu są takie funkcje jak

function Pos(
const substr:shortstring;
const s:shortstring;
):SizeInt;

function Copy(
     S:AStringType;
     index:SizeInt;
     count:SizeInt;
):string;

i myślę że w C# też istnieją analogiczne funkcje

 

 

 

Podobne pytania

0 głosów
2 odpowiedzi 311 wizyt
pytanie zadane 20 grudnia 2022 w C# przez JoannS Początkujący (250 p.)
0 głosów
2 odpowiedzi 985 wizyt
pytanie zadane 9 stycznia 2018 w C i C++ przez mn130496 Gaduła (3,530 p.)
0 głosów
1 odpowiedź 413 wizyt

92,624 zapytań

141,482 odpowiedzi

319,822 komentarzy

62,005 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...