Week 4: Arrays (1)
Last updated
Last updated
Arrays in C are a collection of variables of the same type, stored in contiguous memory locations. They allow for efficient storage and access to a series of data elements.
Here's a brief introduction to arrays in C, how to define them, and an example:
To define an array in C, you specify the type of the elements and the number of elements required by an array as follows:
type
: The data type of the elements in the array (e.g., int
, float
, char
).
arrayName
: The name of the array.
arraySize
: The number of elements the array will hold. This must be a constant value.
sizeof
is a unary operator in C and C++ that returns the size in bytes of its operand, which can be a data type, a variable, an array, or a structure. The size is determined based on the architecture and compiler implementation, as the storage size of different data types can vary from one system to another.
Using size_t
in the array example is a good practice, especially when it comes to indexing or defining the size of an array, as size_t
is an unsigned integer type and is the result of the sizeof
operator. This type ensures that you don't encounter negative indices or sizes.
size_t
is used for the loop counter and for storing the size of the array. The %zu
format specifier is used in the printf
function to print a size_t
value. Using size_t
for array indexing and loop counters is a good habit because it's guaranteed to be large enough to represent the size of the largest possible object on the target platform, making your code more portable and safe from integer overflows or underflows.
sizeof
:Compile-time Operation: sizeof
is computed at compile time, not run time, so it does not impose a performance penalty during execution.
Operand Types: The operand can be a data type (like int
, float
), an expression, or a variable. When the operand is a data type, parentheses are required (sizeof(int)
). When it's an expression or a variable, parentheses are optional but often used for clarity (sizeof x
or sizeof(x)
).
Return Type: The result of sizeof
is of type size_t
, an unsigned integer type.
In C, there are several ways to initialize an array. Below is a single C program that demonstrates different methods of array initialization:
Assuming you have a survey with 6 choices (labeled as 1 to 6), and you've collected 20 responses, you want to summarize the results.
This example simulates rolling a six-sided dice 10,000 times and then summarizes the results.
The above example uses rand()
to simulate dice rolls, and time(NULL)
to seed the random number generator to ensure the rolls are different each time the program is run.
In C, strings are essentially arrays of characters, terminated by a null character \0
. This null character is crucial as it indicates the end of the string, allowing functions to determine where a string stops in memory. Here's how arrays are used to store and manipulate strings:
Initialization at Declaration:
str
is an array of 6 characters ('H'
, 'e'
, 'l'
, 'l'
, 'o'
, '\0'
).
Explicitly Defining Array Size:
Here, the size of str
is specified explicitly, including space for the null character.
Assigning Characters Individually:
Accessing Characters: Characters in a string can be accessed and modified using their indices.
String Functions: The C Standard Library provides various functions to manipulate strings, such as strcpy
(copy), strcat
(concatenate), strlen
(length), strcmp
(compare), and more. Remember, these functions expect null-terminated strings.
Reading and Writing Strings: You can use scanf
, gets
(not safe due to potential buffer overflow), fgets
for reading strings from the user, and printf
for writing strings to the output.
Always ensure there's enough space in the array to include the null terminator (\0
). Not having it can lead to undefined behavior as functions won't know where the string ends.
Be cautious with buffer overflows, particularly when using functions like strcpy
and strcat
. Functions like strncpy
and strncat
are safer as they take the size of the destination buffer as an argument.
When using scanf
to read strings, be aware that it stops reading at the first whitespace. fgets
is often a safer alternative for reading lines of text.
scanf
to read input string?Using scanf
with a limit on the number of characters read is crucial to prevent buffer overflow, a common issue in C programming. Here's an example of reading a string from the user with scanf
, limiting the input to a certain number of characters:
In this example:
%49s
in scanf
ensures that no more than 49 characters are read, preventing a buffer overflow. This reserves one space for the automatic null terminator \0
that scanf
appends at the end of the input string.
str
is the buffer where the input string is stored. It's declared with a size of 50 characters, so it can safely store 49 characters plus the null terminator.
scanf
stops reading input at the first whitespace character. If you need to read a full line including spaces, consider using fgets(str, sizeof(str), stdin)
instead.
It's important to always be cautious about the size of the buffers when dealing with strings in C, and scanf
with a width specifier is a handy tool for that. However, remember that scanf
might leave the newline character in the input buffer, which can affect subsequent reads. You might need to clear the input buffer using something like while ((getchar()) != '\n');
after reading the string if you're going to read more input from the user.
If time allows, we will revisit the potential security issue raised by inputting into a character array and discuss the C standard’s scanf_s function.
In C, a character array that represents a string is a sequence of characters terminated by a null character ('\0'
). This null character signifies the end of the string, which is crucial for various string-handling functions to work properly. Outputting such a string is commonly done using the printf
function, which is part of the C standard I/O library.
When outputting a character array with printf
, the %s
format specifier is used to indicate that you are printing a string. The function automatically reads characters from the provided character array and outputs them until it encounters the null terminator.
Here's a simple example demonstrating how to output a character array that represents a string:
In this example:
str
is a character array initialized with the string "Hello, World!"
. The compiler automatically adds a null character '\0'
at the end of the array.
The printf
function is used to output the string. %s
in the printf
function tells the compiler that the corresponding argument is a string (a null-terminated character array).
The characters in the array str
are printed sequentially by printf
until the null terminator is encountered.
Remember, when dealing with strings in C, it's important to ensure that character arrays are properly null-terminated, as many functions rely on the null terminator to determine the end of the string.
Passing an array to a function in C involves sending the array's base address to the function, essentially passing a pointer to the first element of the array. Arrays are always passed by reference, not by value. This means that any modifications made to the array elements in the function will affect the original array.
Passing the Array:
When passing an array to a function, you just need to specify the array's name without square brackets.
The function that receives the array should be declared with parameters that indicate it expects an array (or a pointer, since arrays decay to pointers when passed to functions).
Function Declaration:
The function that takes an array as an argument can declare the parameter in various ways, such as type name[]
or type *name
. Both forms allow array access within the function.
It's often useful to pass an additional parameter specifying the size of the array, especially since the function receiving the array doesn't inherently know the array's length.
Accessing Array Elements:
Inside the function, array elements can be accessed just like in the main program, using square bracket notation.
No Size Information:
Arrays in C don't carry size information. Hence, when passing arrays to functions, it's a common practice to pass the size of the array as an additional parameter.
Bubble Sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted. Although it's not suitable for large data sets due to its poor performance (O(n²) complexity), it's intuitive and easy to implement.
Here's how you can implement Bubble Sort in C:
Objective: Write a C program to count the frequency of each element in an array.
Description: In this exercise, students will create a program that takes an array of integers as input and then calculates and prints the frequency of each unique element present in the array. The program should work for arrays of any size. The students should ensure that each element's frequency is counted only once.
Instructions:
Input:
Hardcode the array for simplicity, e.g., int arr[] = {2, 1, 2, 4, 3, 5, 4, 6, 4, 7};
Output:
Display the elements of the arr
array and their corresponding frequencies.
Ensure that each element is displayed only once along with its frequency.
Sample Output Structure:
Extend the classwork exercise by
Your program asks the user to input the size and elements of the array.
Sorting the element output.
Implement input validation to check if the user inputs are integers.
Extend the program to handle negative numbers and zeros correctly.