|
CS256 - Principles of Structured Design
Fall 2021
| Reading:
Arrays
Briefly an array is a sequence of similarly typed data under one name. Arrays can be
single dimensional, like a column of data in a spreadsheet, 2 dimensional, like rows
and columns in a spreadsheet or 3 or more dimensional. Most array we'll have to worry
about are 1 or 2 dimensional.
Example:
int ar[5] = { 5, 2, 0, -10, 15 }; // An array of 5 integers
ar |
|
|
index |
value |
reference |
0 |
5 |
ar[0] |
1 |
2 |
ar[1] |
2 |
0 |
ar[2] |
3 |
-10 |
ar[3] |
4 |
15 |
ar[4] |
Defining Arrays
Consider the simple one dimensional case. To define an array of 30 integers for example
would look like:
int ar[30];
The grammar then for an array definition is:
data-type variable-name [ integer-size ]
The size of the array for each dimension is enclosed in square brackets ([] ), thus
for a 2-dimensional array, the grammar would be:
data-type variable-name [ integer-size ][ integer-size ]
So to define a 10 row by 20 column array of characters, would be:
char strs[10][20];
To assign a value to arrays while defining them, use a compound literal as described
below. When assigning values to an array using a compound literal it is unecessary to
specify the size of the array, as the size will be big enough to hold all the values
in the compound literal, i.e.:
int ar[] = {1,2,3,4}; // ar will be 4 integers in size.
Array Indexes
To access or change data in an array, you provide a zero based index value to that
location, i.e. the first location in the array is at index 0, the second at 1 and
so on. Thus if an array is of size 10, the value index values for an array are 0
through 9.
Example:
char str[4]; // Defines space for 4 characters.
str[0] = 'H'; // The first character
str[1] = 'i'; // The second
str[2] = '!'; // The third
str[3] = '\0'; // The fourth, which is the null character, terminating the string.
printf("%s\n", str);
// Prints: Hi!
if (str[0] >= 'A' && str[0] <= 'Z')
printf("The string starts with an upper-case letter\n");
If the index is negative or beyond the length of the array the result could
be a program crash, most likely a segmentation fault, which is an attempt to
access invalid memory by your program. It could also access the data stored
in other variables, in other words, strange things could happen, so while
programming in C, one needs to be careful with your indexes.
Compound Literals
A compound literal is a sequence of comma separated values enclosed in curly
braces ({} ). A compound literal is essentially an array, although they can
also be used to initialize/represent structured data (yet to be talked about.)
Compound literals can be used to assign values to an array when its being
defined, and can be used directly as an array, but usually require that they
are cast to the correct type in order for the compiler to make sense of the
data.
Examples:
// Sets all the elements of ar to 0. This is a special form just for initialization.
int ar[5] = {0};
int ar[5] = {1, 2, 3, 4, 5};
float ar[] = {5.0, 4.8, 3.14, 2.1, 1.1};
char hi[10] = {'H', 'i', '\0'}; // Size of the array can be bigger than the literal
for(int i=0; i < 5; i++)
printf("%d\n", (int[]){5,4,3,2,1}[i]);
└──┬──┘└────┬────┘└─┴─ The index into the array
│ └───────── The compound literal as an array
└────────────────── The type-cast that makes it an integer array
Example of reading values into an array:
#include <stdio.h>
int main(void)
{
int n = 0; // This will store how many valid integers in 'values'
int values[1000]; // A place for up to 1000 integers
while(scanf("%d", &values[n]) == 1) {
n++;
// If we run out of space (1000 integers), stop reading numbers.
if (n >= 1000) break;
}
// At this point n will be the number of valid integers in 'values', so we'll
// print them out.
for(int i=0; i < n; i++) {
printf("%d: %d\n", i, values[i]);
}
return 0;
}
Strings:
Strings as we've seen are lists of characters enclosed in double quotes. In C
these lists of characters are just a special form of character array with a
null character at the end to terminate or signal the end of the string.
Each character in the string can be accessed individually by specifying
the integer index inside of [] 's that are appended to the variable name or
string constant. i.e.:
str[i]
or:
"abc"[i]
Just like with arrays, the first character in a string is at index 0, the second
at index 1, etc. If a string array has been allocated 20 characters, then only
indexes 0-19 are valid (and one of those indexes needs to contain the null
character ('\0' ) terminator character.)
The strlen() function will give us the length of a string:
int len = strlen(str);
would give us the length of str in characters (not counting the null character)
and that length would then be saved in len .
Defining a string
#include <stdio.h>
int main(void)
{
// 3 different ways to define a string:
char s1[] = "Hello 1"; // Array method 1
char *s2 = "Hello 2"; // Pointer method (to be discussed later)
char s3[] = {'H', 'e', 'l', 'l', 'o', ' ', '3', '\0'}; // Array method 2
// Note that the last way requires a null character ('\0') at the end.
// The \" is so we can print a double quote inside of double quotes.
printf("s1 = \"%s\"\n", s1);
printf("s3 = \"%s\"\n", s3);
printf("s2 = \"%s\"\n", s2);
return 0;
}
// Outputs:
s1 = "Hello 1"
s2 = "Hello 2"
s3 = "Hello 3"
String array vs. String pointer
Without going to much into detail about what pointers are, a string pointer
might look something like:
char *str = "Hello";
Note the * which defines the variable as a pointer. Pointers do not allocate
space in memory for data, but merely point to data defined elsewhere. In the
above example, the "Hello" string constant is defined in memory elsewhere and
str is made to point to it. The data in the string constant can be accessed
via str using the array indexes (e.g. str[0] ), just like normal, however
the data cannot be modified in this case (string constants are read-only data.)
String pointers can point to non-constant strings, and they are often the
preferred method of passing strings to functions.
char buf[1024]; // A string array
char *p = buf; // A string pointer pointing to the string array
// p and buf are now essentially the same string.
// This is essentially the strlen() function:
int strlen(char *s)
{
int len = 0;
while (s[len] != '\0') {
len++;
}
return len;
}
String pointers can be incremented or decremented to make them point at the next
or previous character, but we'll cover that sort of idea more in depth when we
get to pointers.
Examples
int main(void)
{
char strbuf[1000];
// Reads a "word" (sequence of characters terminated by a space, newline or tab
// character) into strbuf. Note we don't use & for strings w/ scanf.
while (scanf("%s", strbuf) == 1) {
printf("The word read was: %s\n", strbuf);
}
return 0;
}
// Print each character in the string 's' one to a line:
void printchars(char *s)
{
for(int i=0; s[i] != '\0'; i++) {
printf("%c\n", s[i]);
}
}
// Will print out the string 's' in reverse. Starts at the last character
// (at index len-1) and decrements the index towards 0.
void reverse(char *s)
{
int len = strlen(s);
for(int i = len-1; i >= 0; i--) {
printf("%c", s[i]);
}
}
|