Week 1: Introduction to C Programming
Last updated
Last updated
A shell script is a computer program or script written in a shell programming language, which is primarily used for interacting with an operating system's command-line interface (CLI). Shell scripts are often employed in Unix-like operating systems, including Linux and macOS, but they can also be used on Windows through programs like Cygwin or Windows Subsystem for Linux (WSL).
Here's a simple example in a Unix BASH shell script. It's a time to try OnlineGDB!
Development at Bell Labs (1969-1973): The C programming language was developed at Bell Laboratories (Bell Labs) by Dennis Ritchie between 1969 and 1973. Ritchie's work on C was an evolution of an earlier programming language called B, which itself had roots in BCPL (Basic Combined Programming Language).
Creation of C: C was created as a systems programming language to support the development of the Unix operating system. Unix itself was also developed at Bell Labs, and C became an integral part of Unix's success.
Standardization (ANSI C): In the late 1970s and early 1980s, C's popularity grew beyond Unix, and it started being used for a wide range of applications. To standardize the language and make it more portable, the American National Standards Institute (ANSI) developed the ANSI C standard (commonly referred to as C89 or ANSI C) in 1989. This standardization effort established a clear and consistent set of rules for C programming.
Further Standardization (C99 and C11): Subsequent updates to the C standard were released as C99 (published in 1999) and C11 (published in 2011). These updates introduced new features and improvements while maintaining backward compatibility with ANSI C.
Portability: C is known for its portability, which means that C programs can run on a wide range of computer architectures and operating systems with minimal modifications. This portability is a result of C's low-level nature and its ability to access hardware directly when needed.
Efficiency: C is a low-level programming language that offers fine-grained control over hardware resources. This makes it suitable for systems programming, embedded systems, and applications where performance is critical. C code can be highly optimized, and it allows programmers to write code that runs efficiently.
Widespread Use: C has been used to develop many fundamental software systems and applications, including operating systems (e.g., Unix, Linux), compilers, databases, networking protocols, and embedded systems (e.g., microcontrollers and IoT devices). Its influence can be seen in most modern programming languages.
Foundation for Other Languages: Many other programming languages, such as C++, C#, and Objective-C, have been built on top of C. C provided a solid foundation for these languages, and they inherit C's syntax and some of its features.
Teaching and Learning: C is often used as a teaching language in computer science courses. Its simplicity, combined with the ability to teach low-level programming concepts, makes it an excellent choice for beginners in programming.
Flexibility: C is a versatile language that can be used for a wide variety of applications, from systems programming to scientific computing. It provides both low-level memory control and high-level abstraction through libraries.
Community and Libraries: C has a strong and active programming community, which has contributed to the creation of a vast ecosystem of libraries and tools that extend its capabilities.
Time-Tested Reliability: C has been in use for several decades and has proven its reliability and stability in many critical applications. Its longevity and continued use attest to its enduring significance.
C and Python are two programming languages that serve different purposes and have their own strengths and weaknesses. The choice between C and Python depends on the specific requirements of a project. Here are some benefits of using C over Python:
Performance: C is a compiled language and is typically much faster than Python, which is an interpreted language. C programs have direct control over memory management and can be highly optimized for performance-critical tasks. This makes C a preferred choice for systems programming, embedded systems, and high-performance applications.
Low-Level Control: C provides fine-grained control over hardware resources, making it suitable for tasks that require low-level memory manipulation, direct hardware interaction, and resource-constrained environments. It is commonly used in operating systems, device drivers, and firmware development.
Portability: C code can be easily ported to different platforms with minimal modifications, thanks to its low-level nature and minimal reliance on platform-specific features. This portability is essential for developing software that needs to run on various operating systems and hardware architectures.
Resource Efficiency: C programs typically have a smaller memory footprint and use fewer system resources compared to Python programs. This efficiency is important in scenarios where resource constraints are a concern, such as embedded systems and real-time applications.
Legacy Systems: C is often used for maintaining and extending legacy systems and software that were originally written in C or C++. Many older software systems, libraries, and operating systems are written in C, making C knowledge valuable for maintaining and enhancing such systems.
Real-Time Systems: C is commonly used in real-time systems, where predictability and deterministic behavior are crucial. Real-time systems must respond to events within strict timing constraints, and C's control over hardware and memory is beneficial in this context.
Static Typing: C is statically typed, which means that variable types are determined at compile time. This can help catch type-related errors early in the development process and can lead to more robust and efficient code.
Performance Critical Applications: In applications such as gaming engines, graphics rendering, numerical simulations, and high-frequency trading systems, C's performance advantage becomes critical for achieving low latency and high throughput.
Security: C allows for precise control over memory, reducing the risk of common security vulnerabilities like buffer overflows and memory leaks. This is especially important in security-critical applications.
Extended Libraries: C has a rich ecosystem of libraries and frameworks for various domains, including networking, graphics, cryptography, and more. These libraries can be leveraged to accelerate development.
However, it's important to note that C also comes with challenges, including a steeper learning curve, manual memory management (which can lead to bugs like segmentation faults if not handled properly), and a less expressive and more verbose syntax compared to Python. Additionally, development in C may take longer due to manual memory management and lower-level coding requirements.
Ultimately, the choice between C and Python depends on the specific project requirements, performance goals, resource constraints, and the experience and expertise of the development team. In many cases, both languages can complement each other within a larger software system, with C handling performance-critical components and Python providing a high-level and easy-to-use interface.
Now, try to submit the assignment.
#include <stdio.h>
: This line is a preprocessor directive that includes the standard input/output library, <stdio.h>
. It allows you to use functions like printf()
for output and scanf()
for input in your program. The #include
directive is used to include external libraries or header files in your program.
int main() { ... }
: This is the main function of the program. Every C program must have a main()
function, which serves as the entry point for program execution. The int
before main()
indicates the return type of the function, which in this case is an integer. The { ... }
curly braces enclose the body of the function, where you write the program's instructions.
printf("Hello, World!\n");
: Inside the main()
function, you have the printf()
statement. printf()
is a function from the standard input/output library (<stdio.h>
) used for formatted output. In this example, it prints the message "Hello, World!" to the console. The represents a newline character, which moves the cursor to the next line after printing the message.
return 0;
: The return
statement is used to exit the main()
function and return a value to the operating system. In this case, 0
is returned, which conventionally indicates a successful program execution. Other non-zero values can be used to indicate errors or different exit statuses.
So, in summary, the #include
, main()
, printf()
, and return
statements are fundamental components of a C program. The #include
directive allows you to include libraries, main()
is the entry point for execution, printf()
is used for output, and return
is used to provide an exit status to the operating system.
main()
int?In C, the int main()
function returns an integer value to indicate the exit status of the program. The return value 0
from main()
is a convention used in C and many other programming languages to indicate that the program has executed successfully, without encountering any errors. It signifies a "normal" or "clean" exit from the program.
Here's why 0
is commonly used as the return value for a successful program execution:
Success Indicator: A return value of 0
is easy to recognize as a success indicator. It's a simple and widely understood convention that programmers and systems administrators can use to check whether a program ran without issues.
Error Codes: In contrast to 0
, non-zero values returned from main()
can represent error codes or specific exit statuses that indicate various types of errors or exceptional conditions. By convention, a non-zero value usually signifies an error or an abnormal termination.
Scripting and Automation: Many scripting and automation tools, including shell scripts and batch files, rely on the exit status of a program to determine whether it completed successfully. Using 0
for success simplifies scripting and makes it easier to automate tasks.
Operating System Standards: The convention of using 0
for success is not limited to C; it's a standard practice in many operating systems and programming languages. When a program returns 0
, it aligns with the expectations of the operating system and other programs that may interact with it.
For example, when you run a C program from the command line or a script, you can often check the program's exit status to determine whether it succeeded. In Unix-like systems, you can use the $?
variable to access the exit status of the last executed command, and a value of 0
typically indicates success.
Here is an example of return 0
to check status:
So, returning 0
from main()
in C is a widely adopted convention that helps with program status reporting, error handling, and automation. It's not required to use 0
specifically, but it's a recommended practice for clarity and compatibility with standard conventions.
Variables in C are like containers that store data. Data can be of different types, and each type is called a "data type." Data types define what kind of data a variable can hold and how it is stored in memory.
int: Represents whole numbers (integers), e.g., 5, -10, 100.
float: Stores numbers with decimal points, e.g., 3.14, -0.5.
char: Holds a single character or a small integer, e.g., 'A', '1'.
double: Similar to float but with higher precision, e.g., 3.14159265359.
To use a variable, you need to declare it first. Declaration tells the compiler the variable's name and data type. Initialization to giving variables can also be done. For example:
Variable names should start with a letter (a-z, A-Z) or an underscore (_).
After the first character, variable names can contain letters, digits (0-9), and underscores.
Variable names are case-sensitive, meaning 'age' and 'Age' are considered different names.
In C, you can interact with the user and display information on the screen using input and output functions. Two essential functions for this purpose are printf
and scanf
.
printf
is used to display information on the screen (standard output).
It allows you to format and print text, numbers, and variables.
You can include placeholders in your text, indicated by %
, to insert values or variables into the output.
scanf
is used to read input from the user (standard input).
It allows you to specify the format of the input and store the values entered by the user into variables.
You need to provide the memory address of the variable where you want to store the input using the &
operator.
printf
is for output, while scanf
is for input.
Format specifiers, like %d
, %f
, %c
, etc., specify the type of data being printed or read.
Always use &
before variable names with scanf
to indicate where the input should be stored.
printf
and scanf
are part of the <stdio.h>
library, so you need to include this library using #include <stdio.h>
at the beginning of your program.
Escape sequences in C are special combinations of characters that are used to represent certain non-printable or special characters in strings and character constants. Escape sequences begin with a backslash \
followed by one or more characters. Here's an explanation of some common escape sequences in C:
\n
This will move the cursor to the beginning of the next line.
\t
This will move the cursor to the next horizontal tab stop.
\a
This will produces a sound or visible alert without changing the current cursor position.
\\
Because the backslash has special meaning in a string, \\
is required to insert a backslash character in a string.
\"
Because strings are enclosed in double quotes, \"
is required to insert a double-quote character in a string.
\b
This will move the cursor one position backward. It's often used to erase the preceding character.
\r
This will move the cursor to the beginning of the current line. It's often used in combination with \n
to create Windows-style line endings.
Operators are special symbols or keywords in C that perform various operations on one or more operands (values or variables). Here are some common types of operators:
Arithmetic Operators: These operators perform basic mathematical operations:
+
(addition)
-
(subtraction)
*
(multiplication)
/
(division)
%
(modulo, remainder)
Relational Operators: These operators compare two values and return a Boolean result (true or false):
==
(equal to)
!=
(not equal to)
<
(less than)
>
(greater than)
<=
(less than or equal to)
>=
(greater than or equal to)
Logical Operators: These operators are used to perform logical operations on Boolean values:
&&
(logical AND)
||
(logical OR)
!
(logical NOT)
Assignment Operators: These operators are used to assign values to variables:
=
(assignment)
+=
(add and assign)
-=
(subtract and assign)
*=
(multiply and assign)
/=
(divide and assign)
%=
(modulo and assign)
Increment/Decrement Operators: These operators increase or decrease the value of a variable by 1:
++
(increment)
--
(decrement)
Operator precedence is a set of rules that determines the order in which operators are evaluated in an expression when there are multiple operators present. These rules ensure that expressions are evaluated consistently and correctly. In C, and many other programming languages, operator precedence follows a set of well-defined rules. Here are the key rules of operator precedence in C:
Parentheses: Operators enclosed in parentheses ()
are evaluated first. Expressions within parentheses are evaluated before any other part of the expression.
Example:
Unary Operators: Unary operators, such as unary minus -
and logical NOT !
, have the highest precedence and are evaluated next.
Example:
Multiplication and Division: Multiplication *
and division /
operators are evaluated before addition +
and subtraction -
operators. If multiple multiplication or division operators are present, they are evaluated from left to right.
Example:
Addition and Subtraction: Addition +
and subtraction -
operators are evaluated after multiplication and division. If multiple addition or subtraction operators are present, they are evaluated from left to right.
Example:
Relational Operators: Relational operators, such as less than <
, greater than >
, less than or equal to <=
, and greater than or equal to >=
, are evaluated next. These operators are used for comparisons.
Example:
Equality Operators: Equality operators, such as equal to ==
and not equal to !=
, are evaluated after relational operators. These operators are used for equality comparisons.
Example:
Logical AND (&&
) and Logical OR (||
) Operators: Logical AND and logical OR operators are evaluated after equality operators. They are used for combining multiple conditions.
Example:
Assignment Operators: Assignment operators, such as =
, +=
, -=
etc., have the lowest precedence and are evaluated last. They are used to assign values to variables.
Example:
It's important to note that operator precedence can be overridden by using parentheses. Expressions within parentheses are always evaluated first. Using parentheses also makes your code more readable and explicit, as it removes any ambiguity about the order of evaluation.
Conditional statements allow you to make decisions in your programs based on conditions.
if
statements are used to execute code when a condition is true.
else if
statements allow you to test multiple conditions sequentially.
The else
statement provides a default code block to execute when none of the previous conditions are met.
Write a simple calculator program. Program should get two numbers as inputs, and perform basic calculation (+, -, x, /)
, then print output.
How can you improve your program?
Using the example of shell script above, complete the shell script