Skip to content

Commit 215fdd9

Browse files
committed
feat(compound_data_types): enhance main.rs with detailed examples of tuples, arrays, slices, strings, and nested structures
1 parent 310a912 commit 215fdd9

1 file changed

Lines changed: 176 additions & 36 deletions

File tree

  • projects/04_data_types/compoundDataTypes/src

projects/04_data_types/compoundDataTypes/src/main.rs

Lines changed: 176 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,194 @@
77
// Strings are collections of characters, and they can be mutable or immutable.
88

99
fn main() {
10-
// Example of a tuple
10+
println!("=== Compound Data Types in Rust ===\n");
11+
12+
// ===== TUPLES =====
13+
println!("--- TUPLES ---");
14+
15+
// Basic tuple
1116
let person: (&str, String, i32, f64, bool) = ("Alice", String::from("Bob"), 30, 5.5, false);
1217
println!("Tuple: {:?}", person);
1318
println!("Name1: {}, Name2: {}, Age: {}, Height: {}, Is Student: {}", person.0, person.1, person.2, person.3, person.4);
14-
15-
// Example of an array
16-
// {} represents a display format for arrays
17-
// {?} is used to print the array in a debug format
18-
// Arrays in Rust are fixed-size and must have a type specified
19+
20+
// Tuple destructuring - unpacking values into separate variables
21+
let (name1, name2, age, height, is_student) = person;
22+
println!("\nDestructured tuple:");
23+
println!(" name1: {}", name1);
24+
println!(" name2: {}", name2);
25+
println!(" age: {}", age);
26+
println!(" height: {}", height);
27+
println!(" is_student: {}", is_student);
28+
29+
// Unit type - empty tuple (used when no value is returned)
30+
let unit: () = ();
31+
println!("\nUnit type: {:?} (size: {} bytes)", unit, std::mem::size_of_val(&unit));
32+
33+
// Nested tuples
34+
let nested: ((i32, i32), (i32, i32)) = ((1, 2), (3, 4));
35+
println!("Nested tuple: {:?}", nested);
36+
println!("Access nested: ({}, {})", nested.0.0, nested.1.1);
37+
38+
// Tuples as function return values
39+
let coords = get_coordinates();
40+
println!("Function returned tuple: {:?}", coords);
41+
42+
// ===== ARRAYS =====
43+
println!("\n--- ARRAYS ---");
44+
45+
// Basic array
1946
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
2047
println!("Array: {:?}", numbers);
21-
22-
// Example of an array of strings
48+
49+
// Array initialization shortcut - [value; count]
50+
let zeros: [i32; 5] = [0; 5]; // Creates [0, 0, 0, 0, 0]
51+
let threes: [i32; 10] = [3; 10]; // Creates 10 threes
52+
println!("Array of zeros: {:?}", zeros);
53+
println!("Array of threes: {:?}", threes);
54+
55+
// Array length and iteration
56+
println!("\nArray length: {}", numbers.len());
57+
println!("Iterating over array:");
58+
for (index, value) in numbers.iter().enumerate() {
59+
println!(" Index {}: {}", index, value);
60+
}
61+
62+
// Mutable arrays
63+
let mut mutable_array = [1, 2, 3, 4, 5];
64+
println!("\nOriginal array: {:?}", mutable_array);
65+
mutable_array[0] = 10;
66+
mutable_array[4] = 50;
67+
println!("Modified array: {:?}", mutable_array);
68+
69+
// Multidimensional arrays
70+
let matrix: [[i32; 3]; 2] = [
71+
[1, 2, 3],
72+
[4, 5, 6]
73+
];
74+
println!("\n2D array (matrix): {:?}", matrix);
75+
println!("Element at [1][2]: {}", matrix[1][2]);
76+
77+
// Array of strings
2378
let words: [&str; 3] = ["Rust", "is", "awesome"];
24-
println!("Words: {:?}", words);
25-
// Accessing elements in an array
79+
println!("\nWords: {:?}", words);
2680
println!("First word: {}", words[0]);
2781
println!("Second word: {}", words[1]);
2882
println!("Third word: {}", words[2]);
83+
84+
// Note: Array bounds checking
85+
// Uncommenting the line below will cause a panic at runtime:
86+
// println!("Out of bounds: {}", words[10]); // PANIC!
87+
println!("\nNote: Accessing out-of-bounds index causes panic at runtime");
88+
println!("Rust checks array bounds to prevent memory safety issues");
2989

30-
31-
// Example of a slice
32-
let slice1: &[i32] = &numbers[1..4];
33-
let slice2: &[i32] = &numbers[0..2];
34-
let slice3: &[i32] = &numbers[2..];
35-
let slice4: &[i32] = &numbers[..]; // Full slice of the array
36-
let slice5: &[char] = &person.0.chars().collect::<Vec<char>>()[..]; // Slicing the characters of the name in the tuple
37-
let slice6: &[char] = &person.1.chars().collect::<Vec<char>>()[..]; // Slicing the characters of the name in the tuple
38-
println!("Slice1 of numbers: {:?}", slice1);
39-
println!("Slice2 of numbers: {:?}", slice2);
40-
println!("Slice3 of numbers: {:?}", slice3);
41-
println!("Slice4 of numbers: {:?}", slice4);
42-
println!("Slice5 of person name1: {:?}", slice5);
43-
println!("Slice6 of person name2: {:?}", slice6);
44-
45-
// Example of a string
90+
// ===== SLICES =====
91+
println!("\n--- SLICES ---");
92+
93+
let slice1: &[i32] = &numbers[1..4]; // Elements 1, 2, 3
94+
let slice2: &[i32] = &numbers[0..2]; // Elements 0, 1
95+
let slice3: &[i32] = &numbers[2..]; // From element 2 to end
96+
let slice4: &[i32] = &numbers[..3]; // From start to element 2
97+
let slice5: &[i32] = &numbers[..]; // Full slice of the array
98+
99+
println!("Original array: {:?}", numbers);
100+
println!("Slice [1..4]: {:?}", slice1);
101+
println!("Slice [0..2]: {:?}", slice2);
102+
println!("Slice [2..]: {:?}", slice3);
103+
println!("Slice [..3]: {:?}", slice4);
104+
println!("Slice [..]: {:?}", slice5);
105+
106+
// Slice length
107+
println!("Slice1 length: {}", slice1.len());
108+
109+
// ===== STRINGS =====
110+
println!("\n--- STRINGS ---");
111+
112+
// String vs &str
113+
// String: growable, heap-allocated, mutable, owned
114+
// &str: string slice, fixed size, immutable, borrowed (view into string)
115+
46116
let mut greeting: String = String::from("Hello, ");
47117
greeting.push_str("World!");
48-
println!("Greeting: {}", greeting);
49-
50-
// Strings vs String slices (&str)
51-
// String is a growable, heap-allocated data structure [growable, mutable, owned]
52-
// &str is a string slice, which is a view into a string [fixed size, immutable, borrowed]
53-
let greeting_slice: &str = &greeting[..];
54-
println!("Greeting slice: {}", greeting_slice);
55-
56-
// mut is used to make a variable mutable
118+
println!("String: {}", greeting);
119+
120+
// String methods
121+
println!("\nString methods:");
122+
println!(" Length: {}", greeting.len());
123+
println!(" Is empty: {}", greeting.is_empty());
124+
println!(" Bytes: {}", greeting.bytes().count());
125+
println!(" Contains 'World': {}", greeting.contains("World"));
126+
127+
// String indexing - IMPORTANT: Cannot directly index strings!
128+
// This would NOT work: greeting[0]
129+
// Strings are UTF-8 encoded, so indexing by byte position isn't safe
130+
println!("\nString characters (using .chars()):");
131+
for (i, ch) in greeting.chars().enumerate() {
132+
println!(" Position {}: {}", i, ch);
133+
}
134+
135+
// String slicing (careful with UTF-8!)
136+
let greeting_slice: &str = &greeting[0..5]; // "Hello"
137+
println!("\nString slice [0..5]: {}", greeting_slice);
138+
139+
// String concatenation methods
140+
let s1 = String::from("Hello");
141+
let s2 = String::from("World");
142+
143+
// Method 1: + operator (takes ownership of s1)
144+
let s3 = s1 + " " + &s2; // s1 is moved here
145+
println!("\nConcatenation with +: {}", s3);
146+
147+
// Method 2: format! macro (doesn't take ownership)
148+
let s4 = String::from("Rust");
149+
let s5 = String::from("Programming");
150+
let s6 = format!("{} {}", s4, s5);
151+
println!("Concatenation with format!: {}", s6);
152+
println!("s4 still valid: {}", s4); // s4 not moved
153+
154+
// Mutable string operations
57155
let mut mutable_string: String = String::from("Mutable String");
156+
println!("\nOriginal: {}", mutable_string);
157+
58158
mutable_string.push_str(" - Now I can change it!");
59-
println!("Mutable String: {}", mutable_string);
159+
println!("After push_str: {}", mutable_string);
160+
161+
mutable_string.push('!');
162+
println!("After push (char): {}", mutable_string);
163+
164+
// String to bytes
165+
println!("\nString as bytes: {:?}", greeting.as_bytes());
166+
167+
// ===== TUPLE STRUCTS =====
168+
println!("\n--- TUPLE STRUCTS ---");
169+
170+
// Tuple structs are named tuples
171+
struct Color(i32, i32, i32);
172+
struct Point(i32, i32);
173+
174+
let black = Color(0, 0, 0);
175+
let origin = Point(0, 0);
176+
177+
println!("Color RGB: ({}, {}, {})", black.0, black.1, black.2);
178+
println!("Point: ({}, {})", origin.0, origin.1);
179+
180+
// ===== NESTED STRUCTURES =====
181+
println!("\n--- NESTED STRUCTURES ---");
182+
183+
// Nested arrays and tuples
184+
let nested_array: [[i32; 2]; 3] = [[1, 2], [3, 4], [5, 6]];
185+
println!("Nested array: {:?}", nested_array);
186+
187+
let complex: (String, [i32; 3], (bool, f64)) = (
188+
String::from("Complex"),
189+
[1, 2, 3],
190+
(true, 3.14)
191+
);
192+
println!("Complex tuple: ({}, {:?}, {:?})", complex.0, complex.1, complex.2);
193+
194+
println!("\n=== End of Compound Data Types Demo ===");
195+
}
196+
197+
// Helper function demonstrating tuple as return type
198+
fn get_coordinates() -> (f64, f64) {
199+
(10.5, 20.3)
60200
}

0 commit comments

Comments
 (0)