Week 1: Introduction to C Programming

Introduction to shell script

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!

#!/bin/bash

echo ""
echo "-- PART 1 --"
echo "My first shell script"; #to print 
ls #to list
echo ""
echo "create directory"
mkdir temp #to create directory
ls -la #to list
echo ""
ls -lh #to list (see differences between 3 styles of ls command?)
echo ""
echo "to go inside the directory"
cd temp #to enter the directory
ls -la
pwd # to show the current directory

echo ""
echo "-- PART 2 --"
date #to print the date and time on screen
echo "FILE" > date.log #to write to file
date >> date.log #to append the file
more date.log #to see what is in the file 
rm -rf date.log #to remove the file 

echo ""
echo "-- PART 3 --"
echo "Inside temp"
ls -la
echo ""
which ls

#HW-1: Check if file "data.log" exists or not. 
#If the file exists, print "file exists"
#If not, print "file does not exist"

#to catenate file
cat <<EOF >data.log
181MMM222MMM33MMM789
11MMM72MMM100MMM1
1MMM661MMM530MMM213
135MMM200MMM623MMM556
243MMM412MMM3MMM9
EOF

#HW-1: Sum the numbers in the third colume
#(the numbers between 2nd and 3rd MMM)
 
rm -rf data.log #Why do we need this line?

Introduction to C

Brief History of C Programming Language:

  1. 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).

  2. 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.

  3. 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.

  4. 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.

Significance of the C Programming Language:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

  8. 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 vs Python, why do we learn C in this class?

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

  8. 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.

  9. 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.

  10. 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.

Writing your first "Hello, World!" program

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

Now, try to submit the assignment.

Basic structure of a C program

Anatomy of a C program:

#include <stdio.h>  // Include the standard input/output library

int main() {  // The main function is where program execution starts
    // Code goes here

    printf("Hello, World!\n");  // Print a message to the console

    return 0;  // Return an exit status to the operating system
}
  1. #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.

  2. 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.

  3. 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.

  4. 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.

Why is 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:

  1. 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.

  2. 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.

  3. 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.

  4. 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:

# Create the simple C program, "Hello World"
cat <<EOF >firstc.c
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
EOF

# Compile
make firstc

# Run the C program
./firstc 
if [ $? -eq 0 ]; then
    echo "Program executed successfully."
else
    echo "Program encountered an error."
fi

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.

A little more on basic structure of a C program

#include <stdio.h>

// Function prototype
void greet();

int main() {
    printf("Inside main function.\n");
    greet(); // Calling the greet function
    return 0;
}

// Function definition
void greet() {
    printf("Hello from the greet function!\n");
}

Variables, Data Types, and Declarations

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.

Common Data Types:

  1. int: Represents whole numbers (integers), e.g., 5, -10, 100.

  2. float: Stores numbers with decimal points, e.g., 3.14, -0.5.

  3. char: Holds a single character or a small integer, e.g., 'A', '1'.

  4. double: Similar to float but with higher precision, e.g., 3.14159265359.

Declaration and Initialization:

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:

#include <stdio.h>

int main() {
    // Variable declarations and initialization
    int age = 25;
    float height = 5.9;
    char grade = 'A';

    // Constants
    const double PI = 3.14159265359;

    printf("Age: %d\n", age);
    printf("Height: %.2f feet\n", height);
    printf("Grade: %c\n", grade);
    printf("Value of PI: %lf\n", PI);

    return 0;
}

Rules for Variable Names:

  • 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.

Input and Output (printf and scanf)

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 (Print Formatted):

  • 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 (Scan Formatted):

  • 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.

#include <stdio.h>

int main() {
    char name[50];
    int age;

    printf("Enter your name: ");
    scanf("%s", name); // %s is used for reading strings without spaces
    printf("Enter your age: ");
    scanf("%d", &age); // Use & to get the address of age for input

    printf("Hello, %s! You are %d years old.\n", name, age);

    return 0;
}

Key Points:

  • 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

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:

Operators and Expressions

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:

  1. Arithmetic Operators: These operators perform basic mathematical operations:

    • + (addition)

    • - (subtraction)

    • * (multiplication)

    • / (division)

    • % (modulo, remainder)

  2. 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)

  3. Logical Operators: These operators are used to perform logical operations on Boolean values:

    • && (logical AND)

    • || (logical OR)

    • ! (logical NOT)

  4. 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)

  5. Increment/Decrement Operators: These operators increase or decrease the value of a variable by 1:

    • ++ (increment)

    • -- (decrement)

#include <stdio.h>

int main() {
    int a = 5, b = 2;

    // Arithmetic operators
    int sum = a + b;
    int difference = a - b;
    int product = a * b;
    int quotient = a / b;
    int remainder = a % b;

    // Relational operators
    int isGreater = (a > b);
    int isEqual = (a == b);

    // Logical operators
    int logicalAnd = (isGreater && isEqual);
    int logicalOr = (isGreater || isEqual);
    int logicalNot = !isGreater;

    printf("Sum: %d\n", sum);
    printf("Difference: %d\n", difference);
    printf("Product: %d\n", product);
    printf("Quotient: %d\n", quotient);
    printf("Remainder: %d\n", remainder);
    printf("Is 'a' greater than 'b'? %d\n", isGreater);
    printf("Is 'a' equal to 'b'? %d\n", isEqual);
    printf("Logical AND: %d\n", logicalAnd);
    printf("Logical OR: %d\n", logicalOr);
    printf("Logical NOT of isGreater: %d\n", logicalNot);

    return 0;
}

Rules of Operator Precedence

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:

  1. Parentheses: Operators enclosed in parentheses () are evaluated first. Expressions within parentheses are evaluated before any other part of the expression.

    Example:

    int result = (3 + 5) * 2; // result = 16
  2. Unary Operators: Unary operators, such as unary minus - and logical NOT !, have the highest precedence and are evaluated next.

    Example:

    int x = -5; // x is assigned the value -5
  3. 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:

    int result = 5 * 3 + 2 / 2; // result = 16
  4. 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:

    int result = 10 + 3 - 5; // result = 8
  5. 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:

    int isGreaterThan = 5 > 3; // isGreaterThan = 1 (true)
  6. 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:

    int isEqual = 10 == 5; // isEqual = 0 (false)
  7. 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:

    int result = (x > 0) && (y < 10); // result = 1 (true) if both conditions are true
  8. Assignment Operators: Assignment operators, such as =, +=, -= etc., have the lowest precedence and are evaluated last. They are used to assign values to variables.

    Example:

    int x = 5;
    x += 3; // x is now 8

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 (if, else if, else)

Key Points:

  • 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.

#include <stdio.h>

int main() {
    int num1, num2;
    printf("Enter two numbers: ");
    scanf("%d %d", &num1, &num2);

    if (num1 > num2) {
        printf("%d is greater than %d.\n", num1, num2);
    } else if (num2 > num1) {
        printf("%d is greater than %d.\n", num2, num1);
    } else {
        printf("Both numbers are equal.\n");
    }

    return 0;
}

Classwork - Week 1

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?

Homework - Week 1

Homework-1: Shell script

Using the example of shell script above, complete the shell script

#HW-1: Check if file "data.log" exists or not. 
#If the file exists, print "file exists"
#If not, print "file does not exist"

#HW-1: Sum the numbers in the third colume
#(the numbers between 2nd and 3rd MMM)

Last updated