Skocz do zawartości

[c#] Tablica wielowymiarowa


Rekomendowane odpowiedzi

witam!!! Dopiero zaczyna uczyć się c# i potrzebuje waszej pomocy.

Mój problem polega na tym iż mam plik tekstowy postaci:

 

4 2 3

5 18 7 22

10 6

4 9 15

 

Musze danymi z tego pliku wypełnic nieregularną tablice wielowymiarową. Jednak nie mogę zrobić tego z klawiatury, tylko muszą one zostać wczytane z pliku. Pierwsze trzy liczby określają ilość elementów w poszczególnych jednowymiarowych tablicach znajdyjących się w tej tablicy. Pozostałe liczby powinny znaleźć się w tej tablicy. Bardzo proszę o waszą pomoc.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Moim zdaniem ta pierwsza linijka jest zupełnie zbędna, można się ograniczyć tylko do tego:

 

5 18 7 22

10 6

4 9 15

 

Zaraz coś napiszę.

 

EDIT 1:

Kurde, odczytywać plik do tablicy postrzępionej jest ciężko jak nie znamy liczby linii itd. Tutaj masz przykład, który korzysta z pomocy listy:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Tablica
{
class Program
{
	static void Main( string[] args )
	{
		int[][] tablica;

		FileStream plik = new FileStream( "dane.txt", FileMode.Open );
		StreamReader odczyt = new StreamReader( plik );

		string linia;

		// Tymczasowa lista
		List<int[]> lista = new List<int[]>();

		while ( ( linia = odczyt.ReadLine() ) != null )
		{
			int[] tablicaLiczb = Array.ConvertAll<string, int>( linia.Split( ' ' ), new Converter<string, int>( int.Parse ) );
			lista.Add( tablicaLiczb );
		}
		tablica = lista.ToArray();

		Console.WriteLine( "Zakończono odczyt, naciśnij jakiś klawisz..." );
		Console.ReadKey();
	}
}
}

 

Zaraz dam wersję przy z użyciem zwykłych list.

 

EDIT 2:

 

Poniższy przykład wykorzystuje listę, którą jest znacznie lepsza od tablic w tym przypadku (polecam zapoznać się z kolekcjami w C#):

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Tablica
{
class Program
{
	static void Main( string[] args )
	{
		List<List<int>> liczby = new List<List<int>>();
		string linia;

		FileStream plik = new FileStream( "dane.txt", FileMode.Open );
		StreamReader odczyt = new StreamReader( plik );

		while ( ( linia = odczyt.ReadLine() ) != null )
		{
			liczby.Add( new List<int>( Array.ConvertAll<string, int>( linia.Split( ' ' ), new Converter<string, int>( int.Parse ) )  ) );
		}

		Console.WriteLine( "Zakończono odczyt, naciśnij jakiś klawisz..." );
		Console.ReadKey();
	}
}
}

 

EDIT 3:

A tutaj wersja łatwiejsza do zrozumienia, bez stosowania statycznej metody Array.ConvertAll i Converter'a:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Tablica
{
   class Program
   {
       static void Main( string[] args )
       {
           List<List<int>> liczby = new List<List<int>>();
           string linia;

           FileStream plik = new FileStream( "dane.txt", FileMode.Open );
           StreamReader odczyt = new StreamReader( plik );

           while ( ( linia = odczyt.ReadLine() ) != null )
           {
               List<int> lista = new List<int>();
               string[] liczbyTekst = linia.Split( ' ' );

               foreach ( string tekst in liczbyTekst )
               {
                   lista.Add ( int.Parse( tekst ) );
               }
               liczby.Add( lista );
           }

           Console.WriteLine( "Zakończono odczyt, naciśnij jakiś klawisz..." );
           Console.ReadKey();
       }
   }
}

Odnośnik do komentarza
Udostępnij na innych stronach

  • 7 miesięcy temu...

Natrafiłem na Twojego posta kiedy poszukiwałem informacji na temat tablic. Miałem bardzo podobny problem ale dzięki temu co tu przedstawiłeś udało mi się go rozwiązać :)

Ale dręczy mnie jedna rzecz, bo zastanawiam się czy jest jakaś możliwość zrobienia tego na tablicy dwuwymiarowej?

W moim przypadku mam zawsze 6 liczb w wierszu, ale nie znam ilości wierszy.

 

Udało mi sie to zrobić po mojemu :) i da sie to bez problemu zrobić na dwuwymiarowej tablicy

Odnośnik do komentarza
Udostępnij na innych stronach

  • 1 rok później...

Witam

 

Potrzebuje odczytac plik tekstowy w ktorym zapisane sa wartosci od 0-255 odzielone spacjami. Dokladnie jest to 262144 znakow.

Wczytuje je za pomoca FileStream ReadTo End gdyz ciag jest nieprzerywany znakami podzialu.

 

Potrzebuje stworzyc z tego tablice jednowymiarowa .

 

 string PixelData = sr.ReadToEnd();
int[] tablica = Array.ConvertAll<string, int>(PixelData.Split(' '), new Converter<string, int>(int.Parse));

 

Probowalem to zrobic z listami jak w przykladzie wyzej ale nie wychodzi. Gdyby ktos mogl poprawic bylbym bardzo wdzieczny.

Odnośnik do komentarza
Udostępnij na innych stronach

Oto moj kod. Programik dostaje plik, wyswietla na ekranie co sie dzieje i zapisuje do pliku o zmienionym rozszerzeniu.

 

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;


public class Program
{

    public static void Main(String[] args)
    {
        if (args.Length < 1)
        {
            Console.WriteLine("Wywołanie programu: Program plik");
            return;
        }
   
        String plik = args[0];
        FileInfo file = new FileInfo(plik);
        string newFile, newFileWOext;
        newFile = Path.GetDirectoryName(plik) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(plik) + ".new";
        newFileWOext = Path.GetFileNameWithoutExtension(plik) + ".new";

      StreamReader sr;
        StreamWriter fs;
       
        try
        {
           sr = new StreamReader(plik);
            fs = new StreamWriter(newFile);
           
          
        }
        catch (Exception)
        {
            Console.WriteLine("Otwarcie pliku {0} nie powiodło się.", plik);
            return;
            
        }

        try
        {
          
                int m = 0;
               string linia = sr.ReadToEnd();
            
                //int[][] tablica;
              
          int[]tablicaLiczb = Array.ConvertAll<string, int>(linia.Split(' '),new Converter<string, int>(int.Parse));

          /*
          List<int[]> lista = new List<int[]>();

          while ( ( linia = sr.ReadLine() ) != null )
          {
              int[] tablicaLiczb = Array.ConvertAll<string, int>( linia.Split( ' ' ), new Converter<string, int>( int.Parse ) );
              lista.Add( tablicaLiczb );
          }
           tablica = lista.ToArray();
          */


          for (int i = 0; i < 4;i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                     
                            m=m+1;
                                                
                            Console.Write(m);
                            Console.Write(" :");
                            Console.WriteLine(tablicaLiczb[m]);
                            fs.Write(tablicaLiczb[m]);
                            fs.Write(" ");

                            Console.ReadKey();
                    }
                 
                }
   
            sr.Close();
            fs.Close();

        }
        catch (Exception)
        {
            Console.WriteLine("Wystąpił błąd podczas odczytu z pliku {0}.", plik);
            return;
        }
    }
}

 

Dziala dla pliku np

new.txt

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

 

To jest moja proba aby sprawdzic dzialanie tego parsera. i dziala jednak nie wiedzac czemu czyta plik od drugiej linii. Jednak zmieniajac to w petle [512][512] program zwraca blad. Analizujac gdzie jest blad doszedlem do tego ze chyba ta funkjca convert nie obsluguje takich dlugich ciagow.

 

 

Generalnie musze to wykorszytac aby z ciagu znakow 512*512 odczytywac z pliku tekstowego wartosci skali szarosci (0-255). i tworzenia z tego bitmapy w skali szarosci.

 

przykladowy plik

 

www.files.aristocracy.pl/krs/test.txt

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Dobra, więc tak:

 

plik tekstowy:

10 15 32 52 53 255 0 124 23 438 328 123 72 11 16

 

Rozwiązanie:

TextReader file = new StreamReader( "TextFile1.txt" );
int[] tablica = file.ReadToEnd().Split( ' ' ).Select( i => int.Parse( i ) ).ToArray();

 

Oczywiście mógłbym to porozbijać na linijki, ale mi się nie chciało. Jako, że od czasu powstania tematu minęły 2 lata, to do C# i .NET doszły nowe bajery, m.in. LINQ czy Extension Methods i właśnie użyłem tego ostatniego bajeru. Musisz mieć najnowszego Visuala (2008) oraz .NET 3.0. Opis jak to działa:

 

1) Jako, że masz plik tekstowy, to lepiej użyć dedykowaną klasę TextReader.

2) Odczytujesz całą zawartość i w tym momencie masz String.

3) String oferuje metodę Split, która rozbija String na tablicę stringów. W argumencie podajesz spację jako separator. W tym momencie masz tablicę Stringó.

4) Każda Tablica dowolnego rodzaju, jest typem wyliczeniowym / enumerycznym (składa się z elementów, które można przetwarzać), dlatego też posiada zestaw dodatkowych funkcji, które weszły od oczasów .NET 3.0 (lub 3.5, nie pamiętam). Jest nią między innymi Select. Działa to na takiej zasadzie, że do każdego elementu zostanie wykonane coś co jest w nawiasie. Składnia:

argument (będący aktualnym elementem tablicy) => wyjście.

Możesz zapisać np. takie coś:

zzz => zzz

I to oznacza, że nic się nie stanie. :)

Ja w przykładzie powyżej, dla każdego wybranego elementu z tablicy stringów kazałem przekonwertować się na int.

5) Select zwrócił mi bliżej nieokreślony zbiór elementów, który wiem że składa się ze intów. Dlatego użyłem od razu ToArray żebym miał gotową, jawną tablicę intów.

 

Może być? :)

 

UPDATE:

Ważne, musisz do referencji dodać LINQ:

using System.Linq;

 

UPDATE 2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main( string[] args )
        {
            TextReader file = new StreamReader( "TextFile1.txt" );
            int[] tablica = file.ReadToEnd().Split( ' ' ).Select( i => int.Parse( i ) ).ToArray();

            foreach ( int i in tablica )
            {
                Console.WriteLine( i );
            }

            Console.ReadKey();
        }
    }
}

Odnośnik do komentarza
Udostępnij na innych stronach

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    public class Program
    {

        public static void Main(String[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Wywołanie programu: Program plik");
                return;
            }

            String plik = args[0];
            FileInfo file = new FileInfo(plik);
            string newFile, newFileWOext;
            newFile = Path.GetDirectoryName(plik) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(plik) + ".new";
            newFileWOext = Path.GetFileNameWithoutExtension(plik) + ".new";
            try
            {
                Console.WriteLine("lol, plik");
               Console.ReadKey();
               TextReader ciag = new StreamReader(plik);
               Console.WriteLine("lol2, plik");
               Console.ReadKey();
                int[] tablica = ciag.ReadToEnd().Split(' ').Select(i => int.Parse(i)).ToArray();
                foreach (int i in tablica)
                {
                    Console.WriteLine(i);
                    
                }

                Console.ReadKey();

            }
            catch (Exception)
            {
                Console.WriteLine("Wystąpił błąd podczas odczytu z pliku {0}.", plik);
                return;
            }
        }
    }
}

 

Dziala dla malego pliku, gdy probuje wyswietlic ten 512*512 nie przehodzi.

Dziekuje za podpowiedz z Net3.0.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Może zacznijmy od tego czy piszesz jakąś pracę zaliczeniową czy też coś dla siebie. Jeśli to drugie, to radzę zmienić format z bliku tekstowego na binarny, bo jeżeli będziesz to konwertował na bitmapę, to nie ma sensu tracić mocy na konwersję każdego znaku.

Odnośnik do komentarza
Udostępnij na innych stronach

Może zacznijmy od tego czy piszesz jakąś pracę zaliczeniową czy też coś dla siebie. Jeśli to drugie, to radzę zmienić format z bliku tekstowego na binarny, bo jeżeli będziesz to konwertował na bitmapę, to nie ma sensu tracić mocy na konwersję każdego znaku.

 

Na prace zaliczeniowa. Najprostszym rozwiazaniem bylo by chyba zczytywanie znak po znaku i przypisywanie od razu wartosci ale nie wychodzilo mi to i probowałem wczytywac caly pllik zamieniac na tablice i przypisywac wartosci.

 

Oto kod do ktorego to potrzebuje:

 

 

 

 

for (i = 0; i < openFileDialog1.FileNames.Length; i++)
                        {
                          
                            progressBar1.Value++;
                            this.Refresh();
                            string newFile;
                           
                            //newFile = openFileDialog1.FileNames[i].ToString();
                            System.Drawing.Bitmap image = new System.Drawing.Bitmap(512, 512);
                             newFile = Path.GetDirectoryName(openFileDialog1.FileNames[i]) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(openFileDialog1.FileNames[i]) + ".bmp";
                            int m = 0;
                       
                            //BinaryReader br;
                            //br = new BinaryReader(new FileStream(openFileDialog1.FileNames[i],FileMode.Open));

                      
                                   for (int x = 0; x < image.Width; ++x)
                                        {
                                          
                                            for (int y = 0; y < image.Height; ++y)
                                            {
                                 
                                            // Tutuaj wczytywanie pixela z txt i przypisywanie wartosci
                                              
                                                image.SetPixel(x, y, Color.FromArgb(255,k,k,k));
                                            }
                                    
                            }
                                   image.Save(newFile);
                                   br.Close();
                        }

 

A oto funkjca zapisujaca

 

for (i = 0; i < openFileDialog1.FileNames.Length; i++)
                        {
                            double k;
                            progressBar1.Value++;
                            this.Refresh();
                            string newFile;
                            newFile = openFileDialog1.FileNames[i].ToString();
                            newFile = Path.GetDirectoryName(openFileDialog1.FileNames[i]) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(openFileDialog1.FileNames[i]) + ".txt";
                            Bitmap image = new Bitmap(openFileDialog1.FileNames[i].ToString());
                            int m = 0;
                            StreamWriter fs;
                            fs = new StreamWriter(newFile);
                            for (int y = 0; y < image.Height; y++)
                            {
                                for (int x = 0; x < image.Width; x++)
                                {
                                    Color col = image.GetPixel(x, y);
                                    byte red_pixel = col.R;
                                    byte green_pixel = col.G;
                                    byte blue_pixel = col.B;
                                    k = (red_pixel*0.299 + green_pixel*0.587 + blue_pixel*0.114);
                             
                                    fs.Write(k);
                                    fs.Write(" ");
                                }
                                fs.WriteLine();
                            }
                            fs.Close();

                        }

 

Dodam, ze bitmapy maja zawsze rozmiar 512*512 wiec o bledy wynikajace z niewlasciwego rozmiaru bitmapy lub tablicy nie nalezy sie martwic.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

Pisałeś wcześniej, że działało Ci to (niezależnie czy używałeś convert, czy funkcjonalności linq?) przy małych plikach, bo przy dużych już się sypało... Ale w którym momencie np. przy tym moim rozwiązaniu? Sprawdź może czy samo wczytywanie i konwertowanie na tablicę stringów działa:

 

string bufor = file.ReadToEnd();
string[] dane = bufor.Split( ' ' );

Jeśli to przejdzie, to wtedy po prostu pobierasz np. pierwsze 512 elementów z tablicy i parsujesz, potem kolejne itd.

 

Jeśli natomiast już w tym momencie się sypie, to będziesz musiał zrobić sekwencyjny odczyt danych wprost z pliku.

Odnośnik do komentarza
Udostępnij na innych stronach

Wczytywanie calego pliku przehodzi, bo gdy zapisyje ten odczytany ciag do innego pliku oba sa takiej samej wielkosci i z ta sama zawartoiscia.

 

Problemu wysypywania sie przy duzej dlugosci ciagu nie ma gdy zrobie tak:

 

  string str = ciag.ReadToEnd();
               string[] strarray = str.Split(' ');
               float[] intarray = new float[strarray.Length];
               for (int i = 0; i < strarray.Length; i++)
               {
                   intarray[i] = Convert.ToByte(strarray[i]);
                   Console.Write(i);
                   Console.Write("  :");
                   Console.Write(intarray[i]);
                   tw.Write(intarray[i]);
                   tw.Write(" ");
               }

Jednak plik do kotrego zapisuje tW.Write lekko sie rozni od pierwowzoru test.txt ma 534'335 a wyjsciowy 532'840.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main( string[] args )
        {
            if ( File.Exists( "dane_startowe.txt" ) == false )
            {
                TextWriter writer = new StreamWriter( "dane_startowe.txt" );
                Random rand = new Random();

                for ( int i = 0; i < 262144; i++ )
                    writer.Write( rand.Next( 255 ).ToString() + ' ' );

                writer.Close();
            }

            TextReader reader = new StreamReader( "dane_startowe.txt" );
            string buffer = reader.ReadToEnd();
            string[] data = buffer.Trim().Split( ' ' );

            int[] intarray = data.Select( s => int.Parse(s) ).ToArray();

            if ( File.Exists( "dane_koncowe.txt" ) == false )
            {
                TextWriter writer = new StreamWriter( "dane_koncowe.txt" );
                foreach ( int i in intarray )
                    writer.Write( i.ToString() + ' ' );
                writer.Close();
            }
        }
    }
}

 

Kod powyżej mi działa. Plik wejściowy i wyjściowy są takie same. Wczytuję stringa, potem rozbijam na tablicę stringów, potem konwertuję na tablicę intów za pomocą SELECT, żeby w końcu przeparsować całą tablicę intów i zapisać ją do pliku.

 

btw. Przed funkcją Split użyłem jeszcze Trim co by wyczyścić stringa ze spacji na końcu, inaczej w tablicy stringów ostatnim elementem była spacja i int.Parse się przy tym wywalało. :)

 

btw. Może dlatego u Ciebie są błędy, bo używasz BinaryReader / BinaryWriter do obsługi tekstu, zamiast TextReader / TextWriter.

Odnośnik do komentarza
Udostępnij na innych stronach

No tak, fakt teraz pliki wygladaja tak samo :-). Mozna spokojnie isc spac.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(String[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Wywołanie programu: Program plik");
                return;
            }
            String plik = args[0];
            FileInfo file = new FileInfo(plik);
            string newFile, newFileWOext;
            newFile = Path.GetDirectoryName(plik) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(plik) + ".new";
            newFileWOext = Path.GetFileNameWithoutExtension(plik) + ".new";
            try
            {

                TextReader reader = new StreamReader(plik);
               TextWriter writer = new TextWriter(newFile);
                string buffer = reader.ReadToEnd();
                string[] data = buffer.Trim().Split(' ');
                int[] intarray = data.Select(s => int.Parse(s)).ToArray();
                foreach (int i in intarray)
                writer.Write(i.ToString() + ' ');
                reader.Close();
                writer.Close();
                Console.Write(intarray.Length);
                Console.ReadKey();
            }
            catch (Exception)
            {
                Console.WriteLine("Wystąpił błąd podczas odczytu z pliku {0}.", plik);
                return;
            }
        }
    }
}

 

Powyzszy kod odczytuje plik podany w argumencie, czyta liczby i zapisuje je do pliku o tej samej nazwie ze zmienionym rozszerzeniem. Moze komus sie przyda. :-)

Jutro pobawie sie w przypisywanie danych z przeczytanej tablicy do tablicy pixeli. Oby sie udalo :-). Dziekuje za pomoc.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...