Diziler (arrays), listelere benzer veri yapılarıdır. Numaralar, yazılar, boolean değerler gibi farklı değer tiplerinde verileri barındırabilirler. Dizileri örnekleyecek olursak:
string[] programlamaDilleri = {"C#","Solidity", "Python", "Javascript"};
programlamaDilleri = ["C#","Solidity", "Python", "Javascript"]
const programlamaDilleri = ["C#","Solidity", "Python", "Javascript"];
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract Diziler { // programlamaDilleri isminde bir değişken tanımladık. string[] programlamaDilleri; //İç içe dizi tanımladık. string[][2] benzerDiller; // Listeyi doldurmak için bir fonksiyon tanımladık. function liste() public returns (string[4] memory, string[] memory){ string[4] memory diller = ["C#","Solidity", "Python", "Javascript"]; programlamaDilleri = ["C#","Solidity", "Python", "Javascript"]; benzerDiller = [["C#","Solidity"], ["Python", "Javascript"]]; string memory ilkDil = programlamaDilleri[0]; return (diller, programlamaDilleri); }
Dizilerin ne olduğu hakkında kısaca bilgi sahibi olduk. Peki Solidity dilindeki dizilerin özellikleri neler?
- Diziler, sabit ya da dinamik büyüklüklerde olabilir.
string[3]
ifadesi 3 elemanlı sabit bir string dizisini ifade ederkenstring[]
ifadesi değişken sayıdaki elemanın bulunduğu bir string dizisini ifade eder. - Dizilerde elemanlar 0'dan başlar. İlk eleman sıfır endeksine göre çağrılır.
string memory ilkDil = programlamaDilleri[0];
- Dinamik ve sabit diziler beraber kullanılabilirler. Örneğin,
uint [][2] memory x
dizisinde 2 elemanlı bir dizinin içerisinde dinamik elemanlı alt diziler vardır. Yukarıdaki kod bloğunda örneğini görebilirsiniz. - Dizinin son sayısını aşan bir çağrı yapmak hata fırlatır. Örneğin, 5 elemanlı bir diziden 8. elemanı çağırmak hata döndürecektir. (Diziler2 sözleşme kodunu inceleyin.)
- push() ve pop() fonksiyonlarıyla eleman ekleme ve çıkarma yapılabilir. (Diziler2 sözleşme kodunu inceleyin.)
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract Diziler2 { // programlamaDilleri isminde bir değişken tanımladık. string[] programlamaDilleri; // Listeyi doldurmak için bir fonksiyon tanımladık. function liste() public returns (string memory){ // push() fonksiyonu kullanarak dizimize eleman ekledik. programlamaDilleri.push("C++"); // Dizimizden son elemanı sildik. programlamaDilleri.pop(); string memory ilkDil = programlamaDilleri[0]; // Eleman sayısı 4 olduğundan son elemanı almak için toplam sayıdan bir eksiği çağırıyoruz. (Dizilerin 0 endeksli olduğunu unutmayın!) string memory sonDil = programlamaDilleri[3]; // Eleman sayısı 4 olduğundan son elemanı çağırırken hata alacağız. (Dizilerin 0 endeksli olduğunu unutmayın!) //string memory sonDilHatali = programlamaDilleri[4]; return (sonDil); }
bytes
ve string
diziler birbiriyle aynı işleve sahiptir. Aralarındaki fark string
'de metnin içindeki elemanlara ulaşmak mümkün değilken bytes
dizilerinde her bir elemana ulaşılabilmekte ve müdahale edilebilmektedir.
contract bytesDiziler { bytes1[] public bytesDizi1; /*a*/ // bytes1[] public bytesDizi2 = ["a", "a"]; // HATALI. Dizi tanımlamasında harfler için tür tanımlaması yapmadığımız için hata aldık. /*b*/ bytes1[] public bytesDizi2 = [bytes1("a"),bytes1("a")]; // DOĞRU // Storage dizi işlemleri function elemanEkle() public { // bytesDizi1.push("as"); // 1 byte değerinden fazla "as" bir değer eklemeye çalıştığımız için hata aldık. bytesDizi1.push("a"); // Bir byte değerinde eleman ekledik. /* 1. ve 2. numaralı işlemler birbiriyle aynı görevi yapmaktadır. a ve b numaları işlemlerin aksine burada bytes1 vb. tanımlamaya gerek YOKTUR! */ /*1.*/ bytesDizi2.push("a"); /*2*/ bytesDizi2.push(bytes1("a")); bytesDizi1.pop(); bytesDizi2.pop(); } // Memory dizi işlemleri function memoryBytesDiziler() public { // bytes1[] memory x = new bytes1[](1); // x.push(bytes1("a")); // HATALI KULLANIM. push ve pop mümkün burada değil. x[0] = bytes1("a"); // 0. indeksi yani ilk elemanı bytes1 "a" olarak tanımladık. x[1] = bytes1("b"); // 1. indeksi yani ikinci elemanı bytes1 "b" olarak tanımladık. x[2] = "c"; // 2. indeksi yani üçüncü elemanı bytes1 "c" olarak tanımladık. // x[2] = "sc"; // "sc" bytes2, bytes3 gibi değerlerde tanımlanabilir. Bu yüzden bytes1 tanımlamasında hata aldık.
contract stringDiziler { // string dizi tanımladık. string[] public stringDizi1; string[] public stringDizi2 = ["a", "b", "c"]; string[] public stringDizi3 = [string("a"),string("b")]; // DOĞRU string[3] public stringDizi4 = ["a", "b", "c"]; // Sabit büyüklükteki string dizi string[3] public stringDizi5 = ["a", "b"]; // Sabit büyüklükteki string dizinin ilk iki elemanını tanımladık. // string[1] public stringDizi5 = ["a", "b", "c"]; // 1 elemanlı olması gereken ama fazla eleman girilen sabit dizi. HATALI! // Storage dizi işlemleri function elemanEkleCikar() public { // stringDizi1'e eleman ekleyelim. stringDizi1.push("a"); stringDizi1.push(string("asdasdas")); // Farklı bir tanımlama. stringDizi1.push("sdadsa"); // stringDizi1.push(string("ş")); // ParserError: Invalid character in string. stringDizi1.pop(); stringDizi1.pop(); } // Memory dizi işlemleri function memoryStringDiziler() public { string[] memory x = new string[](1); // x.push(bytes1("a")); // HATALI KULLANIM. push ve pop mümkün burada değil. x[0] = string("a"); // 0. indeksi yani ilk elemanı string "a" olarak tanımladık. x[1] = string("b"); // 1. indeksi yani ikinci elemanı string "b" olarak tanımladık. x[2] = "c"; // 2. indeksi yani üçüncü elemanı string "c" olarak tanımladık. // x[3] = "ğ"; // ParserError: Invalid character in string. (KARAKTER HATASI) x[4] = "BUYUKHARF"; x[5] = "FAZLA KARAKTER";
bytes.concat
ve string.concat
fonksiyonları metinleri birbirine iliştirmemizi sağlar. Örneğin, "minimal" ve "block" değerlerini concat fonksiyonlarıyla birbirine birleştirebiliriz ve "minimalblock" metnini bytes ya da string değerinde elde ederiz. Aşağıdaki örnek kodları inceleyebilirsiniz.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract concatFonksiyonlari{ bytes public isim1 = "minimal"; // bytes: 0x6d696e696d616c bytes public isim2 = "block"; // bytes: 0x626c6f636b function isimBirlestir() view public returns(bytes memory){ bytes memory birlestirilen_isim = bytes.concat(isim1, isim2); return birlestirilen_isim; // bytes: 0x6d696e696d616c626c6f636b }
concatFonksiyonlari sözleşmesindeki işlemlerin dönütleri aşağıdaki ekran görüntüsünde de gösterilmektedir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; contract concatStringFonksiyonlari{ string public isim1 = "minimal"; // string: minimal string public isim2 = "block"; // string: block function isimBirlestir() view public returns(string memory){ string memory birlestirilen_isim = string.concat(string(isim1), string(isim2)); return birlestirilen_isim; // string: minimalblock döner }
concatStringFonksiyonlari sözleşmesindeki işlemlerin dönütleri aşağıdaki ekran görüntüsünde de gösterilmektedir.
Şubat 2022'den itibaren Solidity v0.8.12 sürümü ve sonrasında gelen derleyicilerde artık dizeleri daha basit bir şekilde birleştirebilirsiniz! Çünkü v0.8.12 öncesindeki derleyicilerde string dizelerinde concat işlemi yapılamamaktaydı ve sadece bytes.concat() destekleniyordu.
Aşağıda karşılaşılabilecek hataları, olası durumları örneklerle açıkladım. concatStringBytesFonksiyonlari sözleşmesini inceleyebilirsiniz.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; contract concatStringBytesFonksiyonlari{ function a(bytes1 dize1, bytes calldata dize2) view public returns(bytes memory){ bytes memory concat_bytes = bytes.concat(dize1, dize2[:1]); return concat_bytes; } function b(bytes calldata dize1, bytes12 dize2, string memory dize3) view public returns(bytes memory){ // arrays and array slices olmayan veri türlerindeki verilerde indeks erişimi mümkün değildir. // TypeError: Index range access is only possible for arrays and array slices. // bytes memory concat_bytes1 = bytes.concat(dize1, dize2[:1]); // dize3[:1] dizi parçalaması bytes türünde ve calldata konumundaki, dize1 gibi, veriler için kullanılabilir. // TypeError: Index range access is only supported for dynamic calldata arrays. // bytes memory concat_bytes2 = bytes.concat(dize1, dize3[:1]); // string türü direk olarak bytes değerine eklenemez. bytes(dize3) şeklinde dönüştürülmelidir. // TypeError: Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but string memory provided. // bytes memory concat_bytes3 = bytes.concat(dize1, dize3); // YANLIŞ! bytes memory concat_bytes4 = bytes.concat(dize1[:1], bytes(dize3)); // DOĞRU! // bytes türüde direk olarak string değerine eklenemez. string(dize1[:1]) şeklinde dönüştürülmelidir. // TypeError: Invalid type for argument in the string.concat function call. string type is required, but t_bytes_calldata_ptr_slice provided. string memory concat_string1 = string.concat(string(dize1[:1]), dize3); // DOĞRU! // string memory concat_string2 = string.concat(dize1[:1], dize3); // HATALI! return concat_bytes4;
new
koduyla dizi oluşturmak sadece bellekte (memory) depolanan dizilerde ve sabit büyüklükteki storage
dizilerde mümkündür. Değişken büyüklükteki storage
dizisinde new
kullanıldığında hata meydana gelecektir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract DizilerMadde1 { uint[] public dizi1; // Dizi değişken boyutlarda olabilir. uint[2] public sabitElemanliDizi1; // 2 elemanlı sabit dizi. Boyut değiştirilmesi mümkün değil. //uint[] public dizi2 = new uint[]; //Bu tanımlama HATALIDIR. storage'da new ile değişken dizi tanımlanamaz. uint[] public sabitElemanliDizi2 = new uint[](6); // Sabit büyüklükteki diziyi storage'da new ile tanımladık. function a(uint[] memory x) public{ uint[] memory b = new uint[](5); uint[] memory d = x;
length: Dizilerin eleman sayısına .length
ile erişmemizi sağlar. x.length
şeklinde kullanılır ve integer türünde sayı döner.
push(x): Dizilerin sonuna .push(x)
ile x türünde eleman eklememizi sağlar. Fonksiyon hiçbir şey döndürmez. Dinamik storage
dizilerinde ve bytes
'da kullanılır.
push(): Dizinin sonuna veri eklemek için dizi.push() = x
şeklinde kullanılabilir.
pop(): Dizilerin sonundan .pop()
ile eleman kaldırmamızı sağlar. Fonksiyon hiçbir şey döndürmez. Dinamik storage
dizilerinde ve bytes
'da kullanılır.
memory
'de tanımlanan dizilerde pop
ve push
ile diziye müdahale edilmesi mümkün değildir. storage
'da tanımlanan dizilerde bu işlemler gerçekleştirilebilmektedir.
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract DizilerMadde2 { uint[] public dizi; // Değişken boyutlarda tanımlanan dizi. function a(uint[] memory x) public{ uint[] memory sabitMemoryDizi = new uint[](5); uint8[] memory sabitMemoryDizi2 = new uint8[](1); uint[] memory degiskenMemoryDizi = x; // sayıları dizinin sonuna ekleyelim. dizi.push(5); // => dizi = [5] dizi.push(3); // => dizi = [5,3] dizi.push(6); // => dizi = [5,3,6] // Diziden elemanları pop ile sondan silelim. dizi.pop(); // => dizi = [5,3] dizi.pop(); // => dizi = [5] // b.pop(); // TypeError: Member "pop" is not available in uint256[] memory outside of storage. // b.push(5); // TypeError: Member "push" is not available in uint256[] memory outside of storage. sabitMemoryDizi[0] = 1; degiskenMemoryDizi[0] = 2; sabitMemoryDizi2 = new uint8[](5); // Tekrardan boyut tanımlaması yaptık. // sabitMemoryDizi2 = new uint[](5); // Türü farklı olduğu için hata aldık. uint => uint8 // sabitMemoryDizi = [1,3,4,5,6]; // TypeError: Type uint8[5] memory is not implicitly convertible to expected type uint256[] memory. // x = [1,2,3]; // Bellekteki değişken büyüklükteki bir diziye sabit tanımlama yapmak mümkün olmuyor. // dizi = [1,2,3]
string.concat
veyabytes.concat
'ı bağımsız değişkenler olmadan çağırırsanız, boş bir dizi döndürürler. [1]
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; contract concatBosDonus{ function a(string memory dize1) view public returns(string memory){ string memory concat_string = string.concat(); return concat_string; }
Diziler konusunu örnekler vererek inceledik. Karşılaştığım hataları ve önemli noktaları da paylaşmaya gayret ettim. Umarım faydalı olmuştur. Bundan sonraki yazımızda Array Slices konusunu inceleyeceğiz. Kolay gelsin.
Yorumunu Bırak
Yorumlar
0 Yorum yokHenüz yorum yapılmamış. İlk yorum yapan sen ol.