Skip to content

Commit 705c8dd

Browse files
committed
fixup! feat: add exercise for pointer concept
1 parent 88c486c commit 705c8dd

21 files changed

+262
-18745
lines changed

config.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,11 @@
201201
"slug": "speedywagon",
202202
"name": "Speedywagon Foundation",
203203
"uuid": "ed2148a5-674c-4660-a050-b11ab240b876",
204-
"concepts": [],
204+
"concepts": [
205+
"pointers"
206+
],
205207
"prerequisites": [
206208
"classes",
207-
"pointers",
208209
"references"
209210
]
210211
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Hints
2+
3+
## General
4+
5+
- Pay close attention to pointer syntax.
6+
You will be using `*` (dereference operator) and `->` (member access through pointer).
7+
- Make sure to check for null pointers (`nullptr`) where necessary to avoid accessing invalid memory.
8+
- You can run the tests even if your code isn't complete; a rough structure is enough to see test results.
9+
- All functions used by the tests must be declared in the header file.
10+
- If your program crashes or behaves unexpectedly, it's often due to null pointer dereferencing.
11+
Double-check that you handle `nullptr` properly.
12+
- When using pointer arithmetic, ensure that you stay within the bounds of the sensor array.
13+
Going beyond the array's capacity can lead to memory issues.
14+
15+
## 1. Check Sensor Connection (`connection_check`)
16+
17+
- The task is mainly about verifying whether a pointer is null or not.
18+
- Use the comparison operator `!=` to check if a pointer is valid.
19+
- If you're unsure whether you're checking the pointer correctly, think about what `nullptr` represents (the absence of a valid memory address).
20+
21+
22+
## 2. Count Activity of Sensors (`activity_counter`)
23+
24+
- You need to iterate over the array of sensors.
25+
An array in C++ can be treated as a pointer to its first element.
26+
- Use pointer arithmetic (`sensor_array + i`) to access the sensor at index `i`.
27+
- The `->` operator is used to access a member of the struct through a pointer.
28+
29+
### Example
30+
31+
```cpp
32+
int sum = (sensor_array + i)->activity; // Access activity using pointer arithmetic
33+
```
34+
35+
## 3. Alarm Control (`alarm_control`)
36+
37+
- First, check if the pointer is null before accessing the sensor.
38+
- Use the `->` operator to access the `activity` member of the `pillar_men_sensor` struct.
39+
- Think carefully about what should happen if the sensor's activity level is `0`.
40+
Should the alarm trigger?
Lines changed: 56 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,91 @@
11
# Instructions
22

3-
In this exercise, you will be simulating a windowing based computer system.
4-
You will create some windows that can be moved and resized.
5-
The following image is representative of the values you will be working with below.
3+
Welcome, Engineer!
4+
You are one of the last veterans of the Speedywagon Foundation, a secret organization that, for decades, has been battling ancient threats like the Pillar Men.
5+
In the course of this effort, you've spent years maintaining the Foundation's technological systems, built using a mix of cutting-edge tech and aging libraries.
66

7-
```
8-
<--------------------- screenSize.width --------------------->
9-
10-
^ ╔════════════════════════════════════════════════════════════╗
11-
| ║ ║
12-
| ║ position.x,_ ║
13-
| ║ position.y \ ║
14-
| ║ \<----- size.width -----> ║
15-
| ║ ^ *──────────────────────┐ ║
16-
| ║ | │ title │ ║
17-
| ║ | ├──────────────────────┤ ║
18-
screenSize.height ║ | │ │ ║
19-
| ║ size.height │ │ ║
20-
| ║ | │ contents │ ║
21-
| ║ | │ │ ║
22-
| ║ | │ │ ║
23-
| ║ v └──────────────────────┘ ║
24-
| ║ ║
25-
| ║ ║
26-
v ╚════════════════════════════════════════════════════════════╝
27-
```
7+
However, in recent times, the sensors that track Pillar Men activities are malfunctioning.
8+
The Foundation's systems are old, and the code interacts with a legacy C++ library that cannot be updated.
9+
Your task is to implement three core functions that monitor Pillar Men sensor activity using an old-fashioned pointer-based library.
2810

29-
## 1. Define a `size` struct for storing the dimensions of the window
11+
The Foundation's operations rely on you.
3012

31-
Define a `struct` named `size`.
32-
It should have two member variables `width` and `height` that store the window's current dimensions.
33-
The constructor function should accept initial values for these fields.
34-
The width is provided as the first parameter, the height as the second one.
35-
The default width and height should be `80` and `60`, respectively.
13+
## 0. The Sensor Environment (`pillar_men_sensor`)
3614

37-
Additionally, define a member function `void resize(int newWidth, int newHeight)` that takes a new width and height as parameters and changes the fields to reflect the new size.
15+
As sensor readings can be huge, we supply a mockup _struct_ that is used in the actual library.
16+
The code has already been implemented in the header file for you.
3817

3918
```cpp
40-
size aSize{1080, 764};
41-
aSize.width;
42-
// => 1080
43-
aSize.height;
44-
// => 764
45-
46-
aSize.resize(1920, 1080);
47-
aSize.width;
48-
// => 1920
49-
aSize.height;
50-
// => 1080
19+
struct pillar_men_sensor {
20+
int activity{};
21+
std::string location{};
22+
std::vector<int> data{};
23+
};
5124
```
5225
53-
## 2. Define a `position` struct to store a window position
54-
55-
Define a struct (or class) named `position` with two member variables, `x` and `y` that store the current horizontal and vertical position, respectively, of the window's upper left corner.
56-
The constructor function should accept initial values for these fields.
57-
The value for `x` is provided as the first parameter, the value for `y` as the second one.
58-
The default value should be `0` for both variables.
59-
60-
The position (0, 0) is the upper left corner of the screen with `x` values getting larger as you move right and `y` values getting larger as you move down.
26+
## 1. Check Sensor Connection (`connection_check`)
6127
62-
Also define a method `void move(int newX, int newY)` that takes new x and y parameters and changes the properties to reflect the new position.
63-
64-
```cpp
65-
position point{};
66-
point.x;
67-
// => 0
68-
point.y;
69-
// => 0
70-
71-
point.move(100, 200);
72-
point.x;
73-
// => 100
74-
point.y;
75-
// => 200
76-
```
28+
Your first task is to ensure that the Pillar Men sensor is connected properly.
29+
We can't have false alarms triggered by disconnected sensors.
30+
You will write a function `connection_check`, which tests if the sensor's pointer is valid by checking for `nullptr`.
7731
78-
## 3. Define a `programWindow` class
32+
### Task
7933
80-
Define a `programWindow` class or struct with __pointers__ to the following member variables:
34+
- Define a function that accepts a pointer a a `pillar_men_sensor` _struct_.
35+
- The function should return `true` if the sensor pointer is not null, and `false` otherwise.
8136
82-
- `screenSize`: holds a pointer of type `size` with `width` 800 and `height` 600
83-
- `windowSize` : holds a pointer of type `size`, the initial value is the default value of the `size` instance
84-
- `windowPosition` : holds a pointer of type `position`, the initial value is the default value of the `position` instance
85-
86-
When the window is opened (initialized), it always has the default `windowSize` and `windowPosition` in the beginning.
87-
Its constructor should not take any input parameters.
37+
### Example
8838
8939
```cpp
90-
programWindow aProgramWindow{};
91-
programWindow.screenSize->width;
92-
// => 800
93-
94-
// Similar for the other fields.
40+
pillar_men_sensor* sensor{nullptr};
41+
bool isConnected = connection_check(sensor);
42+
// isConnected => false
9543
```
9644

97-
## 4. Add a method to resize the window
45+
## 2. Count Activity of Sensors (`activity_counter`)
46+
47+
Pillar Men are lurking in the shadows, and we need to know if sensors have detected any activity.
48+
You will write the `activity_counter` function, which takes in an array of sensors and a capacity indicating the number of sensors in the array.
9849

99-
The `programWindow` class should include a function `resize`.
100-
It should accept a __pointer__ of type `size` as input and attempts to resize the window to the specified size.
50+
### Task
10151

102-
However, the new size cannot exceed certain bounds.
52+
- Define a function that accepts a pointer to the first element of an array and the arrays capacity.
53+
- Use pointer arithmetic to loop through the sensor array and accumulate the activity readings.
54+
- Return the accumulated activity.
10355

104-
- The minimum allowed height or width is 1.
105-
Requested heights or widths less than 1 will be clipped to 1.
106-
- The maximum height and width depend on the current position of the window, the edges of the window cannot move past the edges of the screen.
107-
Values larger than these bounds will be clipped to the largest size they can take.
108-
E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request.
56+
### Example
10957

11058
```cpp
111-
programWindow aProgramWindow{};
112-
113-
size newSize{600, 400};
114-
aProgramWindow.resize(&newSize);
115-
aProgramWindow.size->width;
116-
// => 600
117-
aProgramWindow.size->height;
118-
// => 400
59+
pillar_men_sensor sensor_array[3] = {{0}, {101}, {22}};
60+
int totalActivity = activity_counter(sensor_array, 3);
61+
// totalActivity => 123
11962
```
12063
121-
## 5. Add a method to move the window
64+
## 3. Alarm Control (`alarm_control`)
12265
123-
Besides the resize functionality, the `programWindow` class should also include a function `move`.
124-
It should accept a parameter as a __pointer__ of type `position` as input.
125-
The `move` function is similar to `resize` however, this function adjusts the _position_ of the window to the requested value, rather than the size.
66+
Not every sensor should trigger an alarm unless there’s real danger.
67+
The `alarm_control` function ensures that a sensor only triggers an alarm if its activity level is greater than 0.
68+
This function should also check for null sensors to prevent system crashes.
12669
127-
As with `resize` the new position cannot exceed certain limits.
70+
### Task
12871
129-
- The smallest position is 0 for both `x` and `y`.
130-
- The maximum position in either direction depends on the current size of the window.
131-
The edges cannot move past the edges of the screen.
132-
Values larger than these bounds will be clipped to the largest size they can take.
133-
E.g. if the window's size is at `x` = 250, `y` = 100 and a move to `x` = 600, `y` = 200 is requested, then the window would be moved to `x` = 550, `y` = 200 as the screen is not large enough in the `x` direction to fully accommodate the request.
72+
- Define a function that accepts the pointer to a `pillar_men_sensor`.
73+
- The function should first check for a `nullptr` sensor. If the sensor is `nullptr`, return `false`.
74+
- If the sensor is valid and its activity is greater than 0, return `true`; otherwise, return `false`.
75+
76+
### Example
13477
13578
```cpp
136-
programWindow aProgramWindow{};
137-
138-
position newPosition{50, 100};
139-
aProgramWindow.move(&newPosition);
140-
aProgramWindow.position->x;
141-
// => 50
142-
aProgramWindow.position->y;
143-
// => 100
79+
pillar_men_sensor db{9008, "songokunoie", {7, 7, 7}};
80+
bool alarm = alarm_control(&db);
81+
// alarm => true
14482
```
14583

146-
## 6. Change a program window
147-
148-
Implement a `changeWindow` function that accepts a __pointer__ to a `programWindow` object as input and changes the window to the specified size and position.
84+
## Wrapping Up
14985

150-
The window should get a width of 400, a height of 300 and be positioned at x = 100, y = 150.
86+
You’ve been entrusted with an essential task for the Speedywagon Foundation.
87+
By testing for valid sensor connections, counting activity, and implementing alarm controls, you’ve ensured that the Foundation's battle against the Pillar Men can continue uninterrupted.
15188

152-
```cpp
153-
programWindow aProgramWindow{};
154-
changeWindow(&programWindow);
155-
aProgramWindow.size->width;
156-
// => 400
89+
As a modern C++ engineer, you’d prefer using smart pointers, but alas, legacy code demands respect for the old ways.
90+
The fate of humanity may rest on these pointers, so proceed carefully, and may the Hamon energy guide you.
15791

158-
// Similar for the other fields.
159-
```
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Introduction
2+
3+
Like many other languages, C++ has _pointers_.
4+
You already know _references_ and _pointers_ are similar, but think of them as a level closer to the inner workings of your computer.
5+
_Pointers_ are variables that hold object addresses.
6+
They are used to directly interact with objects, enabling dynamic memory allocation and efficient data manipulation in C++.
7+
8+
If you're new to _pointers_, they can feel a little mysterious but once you get used to them, they're quite straight-forward.
9+
10+
They're a crucial part of C++, so take some time to really understand them.
11+
The bare-bone version in this concept is also called _dumb pointer_ or _raw pointer_.
12+
With modern C++ there are also _smart pointers_, the basic type is not smart at all and you have to handle all the work manually.
13+
14+
Before digging into the details, it's worth understanding the use of _pointers_.
15+
_Pointers_ are a way to share an object's address with other parts of our program, which is useful for two major reasons:
16+
1. Like _references_, pointers avoid copies and help to reduce the resource-footprint of your program.
17+
2. Unlike _references_, pointers can be reassigned to different objects.
18+
3. Pointers can also point to a null value, to indicate, that they currently do not point to any object.
19+
20+
## General Syntax
21+
22+
A pointer declaration in C++ involves specifying the data type to which the the pointer is pointing, followed by an asterisk (`*`) and the pointer's name.
23+
When pointers are declared, they are not automatically initialized.
24+
Without explicit assignment, a pointer typically holds an indeterminate value, often referred to as a "garbage address."
25+
While certain compilers might initialize pointers to `nullptr`, this behavior is not guaranteed across all compilers, so it's essential not to rely on it.
26+
It's best practice to explicitly initialize raw pointers and verify their non-null status before utilization to avoid potential issues.
27+
28+
```cpp
29+
int* ptr{nullptr}; // Declares a pointer and makes sure it is not invalid
30+
```
31+
32+
To assign the address of a variable to a pointer, you use the address-of operator (`&`).
33+
Dereferencing a pointer is done using the _indirection operator_ (`*`) operator.
34+
35+
```cpp
36+
std::string opponent{"Solomon Lane"};
37+
// 'ethan' points to the address of the string opponent
38+
std::string* ethan{&opponent};
39+
// Instead of ethan's, the opponent's name address is given to the passPort
40+
std::string passportName{*ethan};
41+
```
42+
43+
Attention: dereferencing has to be done explicitly, while _references_ just worked like an alias.
44+
45+
## Pointer Arithmetic
46+
47+
_Pointer arithmetic_ allows you to perform arithmetic operations on pointers, which is particularly useful when working with arrays.
48+
Adding an integer to a pointer makes it point to a different element.
49+
50+
```cpp
51+
// Stargate addresses
52+
int gateAddresses[] = {462, 753, 218, 611, 977};
53+
// 'ptr' points to the first element of 'gateAddresses'
54+
int* ptr{gateAddresses};
55+
// Accesses the third Stargate address through pointer arithmetic
56+
int dialedAddress{*(ptr + 2)};
57+
// Chevron encoded! Dialing Stargate address:
58+
openStarGate(dialedAddress);
59+
```
60+
61+
~~~~exercism/caution
62+
Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully.
63+
Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities.
64+
One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure.
65+
~~~~
66+
67+
## Accessing member variables
68+
69+
In C++, the `->` operator is used to access members of an object through a pointer to that object.
70+
It is a shorthand which simplifies accessing members of objects pointed to by pointers.
71+
For instance, if `ptr` is a pointer to an object with a member variable `x`, instead of using `(*ptr).x`, you can directly use `ptr->x`.
72+
This operator enhances code readability and reduces verbosity when working with pointers to objects.
73+
74+
Here's a brief example, with a _struct_ `Superhero` that has a member variable `superpower`.
75+
The main function creates a pointer `dianaPrince` to a `Superhero` object (representing Wonder Woman).
76+
The `->` operator is used to access the member variable `superpower`, showcasing Wonder Woman's iconic "Lasso of Truth."
77+
78+
```cpp
79+
struct Superhero {
80+
std::string superpower;
81+
};
82+
83+
Superhero* dianaPrince = new Superhero;
84+
dianaPrince->superpower = "Lasso of Truth";
85+
// Using the -> operator to access member variable superpower:
86+
std::cout << "Wonder Woman, possesses the mighty " << dianaPrince->superpower;
87+
// Memory cleanup:
88+
delete dianaPrince;
89+
```
90+
91+
## Pointers vs. references
92+
93+
Pointers and references both enable indirect access to objects, but they differ in their capabilities and safety considerations.
94+
Pointers offer the flexibility of changing their target object and can be assigned null.
95+
However, this flexibility introduces risks, such as dereferencing null pointers or creating dangling pointers.
96+
References, on the other hand, cannot be null and are bound to valid objects upon creation, avoiding these risks.
97+
Given their safer nature, references should be preferred over pointers unless the additional functionalities provided by pointers are necessary.
98+
99+
[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88

0 commit comments

Comments
 (0)