Thumbnail from Pixabay
Hello readers, below you can find my homework for SLC21 Week3 - Strings in C by @sergeyk.
Let's get started!
So from what I understand, the concept of two sizes of an array describes the scenario where the user must use a physical size and a logical size.
Physical Size
The Physical Size could best be described as the size of memory that is allocated for our array, it's the maximum size we can use for this structure, think of it like the storage size.
Logical Size
The Logical Size represents a number that shows how much of the data from the Physical Size is used. Logical Size can't exceed the Physical one, think of this as a portion of the storage used in Physical size.
Let's check an example with both and see how one and the other are working:
For the exercises I am using the following online compiler OneCompiler
In the example presented above, we are assuming our physical size is 1000, and declare myArray with that size, we could also define a variable outside the main and use inside myArray's declaration but we'll keep it like this to keep the explanation clear.
I declared the logicalSize as 10, meaning out of the 1000 "slots" our memory has, we can use 10 for the moment. I assigned some values using a simple for each and printed out to check if the values were correctly stored inside.
Everything looked good so I went to the next step, increasing the logicalSize. I know that logicalSize is far from reaching the physical one but still wanted to show that there needs to be a check to make sure we won't exceed the physical size, if we exceed it the compiler will throw an overflow error in most cases.
If the logical size is smaller than physical one, we can increase the logical size and add another value. To check if it worked we can print again myArray and we'll see in the console, that our new myArray has one extra value.
Let's see another example where we are adding multiple values.
Changed the if condition to a while to show that we are not limited to increasing the size by only one value. The main idea is that it can be increased as long as the size of logicalSize is below the physical size.
Now you might ask yourself why it needs to be smaller (Logical Size < Physical Size), it's not really a rule, but most of the people are getting used to populate arrays starting from the position 0, if you get to position 999 you already have 1000 slots occupied and you reached the limit of the physical size. 999 < 1000, if we were to compare (Logical Size <= Physical Size), from 0 to 1000 we would have 1001 slots occupied and get an overflow error because we are trying to fill an address outside our array with it's current size limit.
I got to this part of the homework and saw that I had to hardcode the limit in a variable N, so to repair this mistake, I will redo the code below using a defined N. The concept stays the same, it's just that now I am not comparing with 1000, I am comparing with N that has a defined value.
This method saves you from using dynamic memory allocation and allows you to manage arrays simpler, but at the same time you always need to be sure you aren't exceeding physical size and you lose the ability to increase the physical size beyond the initial value.
For the task above I've used C++ because that's what I used for the previous homework and that was still much related to arrays used in the previous homework, for the next one I saw that you used C and I will switch to it as well.
Let's start by declaring the string and printing it, taking it step by step and checking each time if code works accordingly.
We declared the string and printed it to make sure it works, also we use "%c"
in the printf because in C you need to specify the type of the variable you are going to print, in our case char
. Using the for
we are printing letter by letter, because in each slot of the array we are holding one character.
Now let's see how can we reverse this string, I have a few ideas in my mind on how to approach this, let's try two of them.
Let's assume we only need to show the reserved string and not store it somewhere, we can do that with a for loop but we start from the end of the array, this allows us to print the string from the end and reversing it.
A simple for starting from the last position until the first one and printing the value does the job, as you can see in the console the string is printed reversed. If you need to store it, you could create a new string that could hold the new value, something like this.
Created a newString that will hold the new value, and with a new index variable J initialized with 0 we copy the string as reversed to the new one, more details in the comments mentioned in the picture above.
Let's see how else we can do this, we could use an auxiliary char variable to hold our value and move letters from front to back, let's see an example.
Added some details in the comments mentioned in the picture above, I will also draw a representation in Adobe Illustrator and leave it below, you'll understand much more from the image.
An explanation for one exchange:
We use the aux
variable to hold the value from the first position, so in aux
we have H now.
In the first position [0]
we can now copy the value from the last position because the value currently on [0]
is already saved in the aux variable. How can we get the value from the last position? We use the 13-i-1
formula, where 13 = length
, i = current position in the loop
and -1
is used because the for starts from 0
.
So in the [0]
we have now the value from [13-0-1]
which is [12]
, and from the picture the value on [12]
is "t".
Now that the letter from [12]
is copied, we can copy on [12]
the value from our aux.
And with this we reversed first with last letter, and we are doing these steps in a for loop until we hit the middle of the string, once there, the string is reversed.
Without trying to find any fancy method, the first thing that comes to my mind is to use a while that swaps the neighboring letters as long as the current and next letters exist, mostly we'll check if these are different from \0
which if I remember correctly represents null.
The code would look like this:
The main idea is pretty simple, we start from the first position and move every 2 positions, because we are swapping the neighboring letters.
If in the current position and next one we have a value, we have values that can be swapped, once one of these values is null we are at the end of the string and there's a missing letter, meaning we don't have a letter to swap with.
For the left cycle it's pretty easy, so ABCDE
needs to become BCDEA
, we'll do it in a simple way, like this:
The main idea is to save the first letter in a variable so we can copy at the end of the string when we are done, and we move from the first position until we get a null value and copy to the current position the next one, each value gets shifted to the left. In the end we add the first letter and get the shifted string.
Now for the right side, let's use a for loop so it's a bit different than what we used for left cycling.
We save the last letter so we won't lose it while looping from the back to front, we loop like that using a for to copy each letter from left to right, once done all we have to do is add the last letter that we have saved to the first position, the result will be a string reversed to the right.
For this task, it will look pretty ugly without using functions, but I will do it all in the int main()
.
We'll use two indexes i
and j
, one used to go through the main string and the other is used to keep track of the position where the next non vowel should be copied.
Let's see an example, we'll stop using the strings as an array of chars, to keep the code shorter will print them as %s
because the code gets bigger now.
A short description, so we use the two indexes i
and j
to navigate through the string and keep a track of non vowels, we loop through the string until we reach it's end and do a vowel checking. If the current char is not a vowel we copy it to a new position, and j index is incremented to know our next non vowel position.
The fastest idea that came to my mind in tackling this task was to check the string for vowels, once a vowel has been found we shift the string to the right to make room for the doubled vowel. Each time a vowel is found, we increase the length of the string to not lose track of position.
It should look like this, also added some comments in the code:
It's not the best solution, with functions and str
ones everything could be faster.
Just for fun I also did the Additional Task, I won't dive into many details the concept stays the same as most of the exercises in this homework. I calculated using /
how many whitespaces can be distributed evenly and with %
what remaining whitespaces can't be distributed evenly. I did this by dividing with / and %
the expanding number of white spaces needed over the current number of white spaces. After that I started looking for white spaces I added the number of white spaces that can be evenly distributed and one white space that was extra, doing this allows me to expand each white space with the exact number of white spaces and add an extra one from the remaining number calculated with %
.
The code looks like this, pretty messy but it works :D
I kept this example with the new length set to 27 but it works with other values as well.
That was it for this homework, I did my best to keep it interesting, these are not the best approaches, are the approaches I thought first while reading into the homework.
In the end I'd like to invite @r0ssi, @titans and @mojociocio to join.
Thank you @sergeyk for another cool class, can't wait for a new one!