To better understand how to manipulate array pointers I tried to take my previous copy line program and add output for each address in the character arrays. It went well but there is a bug at the end of my copied string which has me concerned. It is misaligned and has an extra element which makes me wonder why that is happening in the copy and not in the initial string.
TLDR;
Okay, so here are the highlights of what I did:
- Continued to work on the “Technical Questions” section of the book “Cracking the Coding Interview” by Gayle Laakmann McDowell. Within that, I continued my work on Tree data structures. Started trying to replicate the example pretty print functions provided in the article I am reading through. I covered
enum
s inC
and how to construct enumerations. The syntax was a little confusing at first but I finally got it. I took a ton of notes which you can see below. They aren’t perfect but they helped me make sense of it all at least. I also modified my “copy line” program to add the array element addresses as an additional output. It went somewhat well but I have some questions on the last element in the copied string array.
C
Modified Copy string Program
/*
* This program will take an existing string (char array)
* and copy it into a new string (char array).
*
* This program will also print out the corresponding
* addresses for each character array element
*
* */
#include <stdlib.h>
#include <stdio.h>
int main(){
char charString[] = "Hello World";
char charStringCopy[12];
char* charPtr;
char* copyCharPtr;
charPtr = charString; // Pointer is assigned to the address of the first element in the array
copyCharPtr = charStringCopy; // Pointer is assigned to the address of the first element in the array
//printf("String value pointed by pointer is: %s\n", *charPtr);
int i = 0;
while(*charPtr != '\0'){
printf("Original String: %c\tAddress: %d\tArray Index: %i\n", *charPtr, charPtr, i++); // Displays the value pointed at by the pointer.
*copyCharPtr++ = *charPtr++; // Copies the value pointed at by charPtr into address pointed at by copyCharPtr
// Then increments the address stored in each pointer by one to access the next element in the string
}
*copyCharPtr = '\0';
//printf("\n\nNew copied string pointer is: %s\n", *copyCharPtr);
//puts(charStringCopy);
printf("\n");
copyCharPtr -= i+1;
i = 0;
while(*copyCharPtr != '\0'){
printf("Copied String: %c\tAddress: %d\tArray Index: %i\n", *copyCharPtr, copyCharPtr++, i++);
}
return 0;
}
# Output
Original String: H Address: 6422296 Array Index: 0
Original String: e Address: 6422297 Array Index: 1
Original String: l Address: 6422298 Array Index: 2
Original String: l Address: 6422299 Array Index: 3
Original String: o Address: 6422300 Array Index: 4
Original String: Address: 6422301 Array Index: 5
Original String: W Address: 6422302 Array Index: 6
Original String: o Address: 6422303 Array Index: 7
Original String: r Address: 6422304 Array Index: 8
Original String: l Address: 6422305 Array Index: 9
Original String: d Address: 6422306 Array Index: 10
Copied String: H Address: 6422283 Array Index: 0
Copied String: e Address: 6422284 Array Index: 1
Copied String: l Address: 6422285 Array Index: 2
Copied String: l Address: 6422286 Array Index: 3
Copied String: o Address: 6422287 Array Index: 4
Copied String: Address: 6422288 Array Index: 5
Copied String: W Address: 6422289 Array Index: 6
Copied String: o Address: 6422290 Array Index: 7
Copied String: r Address: 6422291 Array Index: 8
Copied String: l Address: 6422292 Array Index: 9
Copied String: d Address: 6422293 Array Index: 10
Copied String: Address: 6422294 Array Index: 11
Notes on enum
data type in C
An enumeration consists of a set of named integer constants. An enumeration type declaration gives the name of the (optional) enumeration tag/identifier. It defines the set of named integer identifiers (called the enumeration set, enumerator constants, enumerators, or members). A variable of the enumeration type stores one of the values of the enumeration set defined by that type.
Variables of enum
type can be used in indexing expressions and as operands of all arithmetic and relational operators. Enumerations provide an alternative to the #define
preprocessor directive with the advantages that the values can be generated for you and obey normal scoping rules.
In ANSI C
, the expressions that define the value of an enumerator constant always have int
type. That means the storage associated with an enumeration variable is the storage required for a single int value. An enumeration constant or a value of enumerated type can be used anywhere the C language permits an integer expression.
// Syntax
// Enumeration type declaration syntax:
enum identifier(optional) { enumerator-list }
enum identifier
// Enumerator list syntax:
enumerator
enumerator-list, ... , enumerator
// Enumerator syntax:
enumeration-constant
enumeration-constant = constant-expression(int value)
// Enumeration-constant syntax:
identifier(i.e. constant variable name)
The optional identifier
names the enumeration type defined by enumerator-list
. This identifier is often called the “tag” of the enumeration specified by the list. When declaring variables that will hold a value of this enumeration type we will use both enum
and the identifier
to associated the created type with the enumerator-list
Here is an example:
enum identifier {
// enumeration-list
}
enum identifier variable_name; // Declare a variable of the constructed enum type.
The integer constant value assigned to each enumeration-constant in the list can be assigned a constant integer value or by default have an auto-incremented value assigned to each of them. The auto-incrementation starts at the first value holding 0
, then 1
, then 2
, etc… until the end of the enumeration-list. The same value can be assigned to multiple enumeration-constants in the same list.
Because enumaration-constants
are still constants, there can only be one unique constant-expression per program. If two different enumerator-lists
contains the same constant-expression
, the compiler will give us an error. For example, this code will give us an error.
#include <stdio.h>
enum bool {false, true};
// Causes an error (Cannot re-declare a constant)
enum bool2 {false, true} false2, true2;
enum bool3 {F, T} false3, true3;
Also, by default all declared but uninitialized enum variables receive a default value of 0
not the first enumeration-constant
in the enumator-list
.
Also the auto-incrementation for undeclared enumeration-constant values starts from the last value assigned or 0
by defualt. It doesn’t start where it last left off. I think?? There are more things that I need to test out but for now I have a decent enough understanding to move forward.
Enumeration Type Examples:
Here is a simple example that I wrote myself. It declares the same enum
type and corresponding variables in three different ways.
#include <stdio.h>
enum bool {false, true};
enum bool2 {F, T} true2, false2;
enum bool3 {False, True} false3, true3 = True;
int main(){
enum bool trueVal = true;
enum bool falseVal = false;
printf("True value = %d\n", trueVal);
printf("False value = %d\n", falseVal);
printf("\n------------\n");
true2 = T;
false2 = F;
printf("True value = %d\n", true2);
printf("False value = %d\n", false2);
printf("\n------------\n");
printf("True value = %d\n", true3);
printf("False value = %d\n", false3);
return 0;
}
# Output
True value = 1
False value = 0
------------
True value = 1
False value = 0
Here is an example that covers multiple use cases. The identifier
is called DAY
and the enumeration-list
contains both assigned and auto-incremented enumeration-constants
.
enum DAY /* Defines an enumeration type */
{
saturday, /* Names day and declares a */
sunday = 0, /* variable named workday with */
monday, /* that type */
tuesday,
wednesday, /* wednesday is associated with 3 */
thursday,
friday
} workday;
In this example DAY
is given as the enumeration type identifier
and the enumeration-list
is provided. The workday
variable is included as the declartion of the enumeration type and the variable takes places on the same line. After the enumeration type is given the workday
variable is then declared as an enum type with a value from the DAY
enumeration type.
In this example, a value from the set DAY
is assigned to the variable today
.
enum DAY today = wednesday;
The name of the enumeration constant is used to assign the value. Since the DAY
enumeration type was previously declared, only the enumeration tag (identifier) DAY
is necessary.
Conclusion
That’s all for today. This is my sixth round of the “#100daysofcode” challenge. I will be continuing my work from round five into round six. I am currently working through the book “Cracking the Coding Interview” by Gayle Laakmann McDowell. My goal is to become more familiar with algorithms and data structures. This goal was derived from my goal to better understand operating systems and key programs that I use in the terminal regularly e.g. Git. This goal was in term derived from my desire to better understand the fundamental tools used for coding outside of popular GUIs. This in turn was derived from my desire to be a better back-end developer.
I have no idea if my path is correct but I am walking down this road anyways. Worst case scenario I learn a whole bunch of stuff that will help me out on my own personal projects.