❖ 1. Introduction to C

1.1 What is C?រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

C គឺជាភាសាសរសេរកម្មវិធីទូទៅ (General-Purpose Programming Language) ដែលត្រូវបានបង្កើតឡើងដោយ Dennis Ritchie នៅឆ្នាំ 1972 នៅក្នុងក្រុមហ៊ុន Bell Labs។ C ជាភាសាដែលប្រើ procedural programming paradigm គឺជាភាសានៃការបង្ហាត់ programming មូលដ្ឋានដ៏ល្អបំផុត។

C ត្រូវបានគេប្រើប្រាស់យ៉ាងទូលំទូលាយក្នុងការអភិវឌ្ឍន៍ដូចជា៖

1.2 Features and Benefits of Cរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

1. Procedural Language (ភាសា Procedural)

C ប្រើ procedural programming ដែលកម្មវិធីត្រូវបានរៀបចំជា functions/procedures។ ការប្រតិបត្តិ statements ធ្វើតាមលំដាប់ស្ដង់ដារ។

2. Low-Level Access (ចូលប្រើកម្រិតទាប)

C អនុញ្ញាតឱ្យចូលប្រើ hardware ដោយផ្ទាល់តាមរយៈ pointers និង memory addresses ធ្វើឱ្យវាល្អសម្រាប់ system programming។

3. Fast and Efficient (លឿន និងមានប្រសិទ្ធភាព)

C ត្រូវបាន compile ទៅជា machine code ដោយផ្ទាល់ ធ្វើឱ្យវាមានល្បឿនលឿនខ្លាំង។ Programs មានទំហំតូច និងប្រើ memory បានប្រសិទ្ធភាព។

4. Portability (ភាពអាចប្តូរ platform)

កូដ C ដែលសរសេរនៅ platform មួយ អាចដំណើរការលើ platforms ផ្សេងៗ ដោយ recompile ម្ដងទៀតប៉ុណ្ណោះ។

5. Rich Library (Library សម្បូរ)

C Standard Library (libc) ផ្ដល់ functions ជាច្រើន ដូចជា I/O, string manipulation, math operations, memory management, etc.

6. Middle-Level Language

C ស្ថិតនៅចន្លោះ low-level languages (Assembly) និង high-level languages (Python, Java)។ វាអាចធ្វើ low-level operations ដូច assembly ប៉ុន្តែក៏ងាយ program ដូច high-level languages ផងដែរ។

1.3 History of Cរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Dennis Ritchie បានបង្កើត C នៅ Bell Labs ក្នុងអំឡុងពេល 1969-1973 ក្នុងបំណងសរសេរ UNIX operating system។

1.4 Structure of a C Programរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

មុនពេលចូលសិក្សាលម្អិត សូមមើលកម្មវិធី C ដំបូង (Hello World):

#include <stdio.h>

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

ពន្យល់ផ្នែកនីមួយៗ៖

1.4.1 #include <stdio.h>

#include គឺជា preprocessor directive ដែលប្រាប់ compiler ឱ្យ include header file មួយ។ stdio.h (Standard Input/Output) ផ្ដល់ functions ដូចជា printf() និង scanf()

Header files ដែលប្រើជាញឹកញាប់ក្នុង C:

#include <stdio.h>    // printf, scanf, file operations
#include <stdlib.h>   // malloc, free, exit, rand
#include <string.h>   // strlen, strcpy, strcmp
#include <math.h>     // sqrt, pow, sin, cos
#include <ctype.h>    // isdigit, isalpha, toupper
#include <time.h>     // time, clock
ភាពខុសគ្នារវាង C និង C++: C ប្រើ <stdio.h> ចំណែក C++ ប្រើ <iostream>។ ក្នុង C គ្មាន coutcin ទេ គឺប្រើ printf() និង scanf() ជំនួស។

1.4.2 Header Files ក្នុង C

Header files មាន 2 ប្រភេទ:

1.4.3 main() Function

int main() ជា entry point (ចំណុចចូល) នៃរាល់កម្មវិធី C ទាំងអស់។ Execution ចាប់ផ្ដើមពី function នេះ។

1.4.4 printf() Function

printf() (print formatted) ប្រើសម្រាប់បង្ហាញ output លើ screen។ ខុសពី C++ ដែលប្រើ cout

printf("Hello, World!\n");   // \n = newline character

1.4.5 return 0;

return 0; ប្រាប់ OS ថាកម្មវិធីបានបញ្ចប់ដោយជោគជ័យ។

1.5 Basic Syntax Rulesរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

1.5.1 Semicolon (;)

រាល់ statement ក្នុង C ត្រូវបញ្ចប់ដោយ semicolon (;)។

int x = 10;          // ត្រឹមត្រូវ
printf("Hello");     // ត្រឹមត្រូវ
int y = 20           // ERROR - ខ្វះ semicolon

1.5.2 Case Sensitivity

C មានលក្ខណៈ case-sensitive ។ Main, main, MAIN ខុសគ្នាទាំងស្រុង។

int Number = 10;   // Variable ឈ្មោះ Number
int number = 20;   // Variable ឈ្មោះ number (ខុសពី Number)
int NUMBER = 30;   // Variable ឈ្មោះ NUMBER

1.5.3 Comments

Comments គឺជាអត្ថបទដែល compiler មិនប្រតិបត្តិ ប្រើសម្រាប់ពន្យល់កូដ:

// Single-line comment (C99 and later)
/* Multi-line comment
   C ប្រើ comment ប្រភេទនេះ
   ពី version ដំបូង */

int x = 10;   /* comment ក្នុងបន្ទាត់ */
សំខាន់: C89/C90 ដំបូង គាំទ្រតែ /* */ ប៉ុណ្ណោះ។ // ត្រូវបានបន្ថែមក្នុង C99។ ក្នុង compiler ចាស់ // អាចបង្ករបញ្ហា។

1.5.4 Curly Braces { }

Curly braces ប្រើដើម្បីកំណត់ block នៃកូដ ដូចជា function body, if block, loop block:

int main() {
    // Code block សម្រាប់ main function
    if (1 == 1) {
        // Code block សម្រាប់ if statement
        printf("True!");
    }
    return 0;
}

1.6 Compilation Processរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ដំណើរការ compile កូដ C មាន 4 ជំហាន:

ជំហានទី 1: Preprocessing

Preprocessor ដំណើរការ #include, #define។ វារួម include header files ហើយ expand macros។

ជំហានទី 2: Compilation

Compiler បម្លែង C code ទៅជា Assembly code ហើយពិនិត្យ syntax errors។

ជំហានទី 3: Assembly

Assembler បម្លែង Assembly code ទៅជា machine code (object files .o)។

ជំហានទី 4: Linking

Linker បញ្ចូល object files និង library files ដើម្បីបង្កើត executable file។

Compilation Flow:

Source (.c)  →  Preprocessor  →  Compiler  →  Assembler  →  Linker  →  Executable

Commands ដើម្បី Compile:

/* Linux / Mac */
gcc myprogram.c -o myprogram
./myprogram

/* Windows (MinGW) */
gcc myprogram.c -o myprogram.exe
myprogram.exe

/* Compile ជាមួយ math library */
gcc myprogram.c -o myprogram -lm
ដំបូន្មាន: ប្រើ flag -Wall ដើម្បីឱ្យ compiler បង្ហាញ warnings ទាំងអស់: gcc -Wall myprogram.c -o myprogram

1.7 Variables & Data Typesរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

1.7.1 Variables (អថេរ)

Variable ជាទីតាំងក្នុង memory ប្រើរក្សាទុកទិន្នន័យ។ ក្នុង C ត្រូវប្រកាស variable មុន ហើយទើបប្រើ។

Declaration (ប្រកាស):

int age;           /* ប្រកាស variable ប្រភេទ int */
float salary;      /* ប្រកាស variable ប្រភេទ float */
char grade;        /* ប្រកាស variable ប្រភេទ char */

Initialization (ប្រកាស + ផ្ដល់តម្លៃ):

int age = 25;
float salary = 1500.50;
char grade = 'A';

ប្រកាស variables ច្រើននៅក្នុងមួយបន្ទាត់:

int x = 10, y = 20, z = 30;
float a, b, c = 3.14f;
ខុសពី C++: C89/C90 តម្រូវឱ្យប្រកាស variables ទាំងអស់ នៅដើម function មុនពេល statements ផ្សេង។ C99 ឡើងទៅ អាចប្រកាស variables នៅគ្រប់ទីកន្លែង (ដូច C++)។

1.7.2 Data Types ក្នុង C

1. Integer Types (ប្រភេទចំនួនគត់)

TypeSizeRangeExample
int4 bytes-2,147,483,648 to 2,147,483,647int age = 25;
short2 bytes-32,768 to 32,767short count = 100;
long4/8 bytesvaries by platformlong pop = 15000000;
long long8 bytes-9.2×10¹⁸ to 9.2×10¹⁸long long big = 9876543210;
unsigned int4 bytes0 to 4,294,967,295unsigned int u = 100;

2. Floating-Point Types (ប្រភេទទសភាគ)

TypeSizePrecisionExample
float4 bytes~7 digitsfloat price = 19.99f;
double8 bytes~15 digitsdouble pi = 3.14159265359;
long double12-16 bytes~19 digitslong double x = 3.14L;

3. Character Type

TypeSizeRangeExample
char1 byte-128 to 127char letter = 'A';
unsigned char1 byte0 to 255unsigned char c = 200;
សម្គាល់: C មិនមាន bool type (true/false) ក្នុង C89 ទេ។ C99 បន្ថែម <stdbool.h> ដែលផ្ដល់ bool, true, false។ ក្នុង C89 គេប្រើ int ជំនួស (0 = false, non-zero = true)។

1.7.3 Format Specifiers ក្នុង printf/scanf

C ប្រើ format specifiers ដើម្បីកំណត់ប្រភេទទិន្នន័យដែលបង្ហាញ ឬ input:

SpecifierTypeExample
%dint (decimal)printf("%d", 42);
%iint (integer)printf("%i", 42);
%ffloat/doubleprintf("%f", 3.14);
%lfdouble (scanf)scanf("%lf", &x);
%ccharprintf("%c", 'A');
%sstring (char array)printf("%s", name);
%ldlongprintf("%ld", 100L);
%lldlong longprintf("%lld", 100LL);
%uunsigned intprintf("%u", 100u);
%ooctalprintf("%o", 8);
%xhexadecimalprintf("%x", 255);
%ppointer addressprintf("%p", ptr);
%%percent signprintf("100%%");

1.8 Input / Output (printf / scanf)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

1.8.1 Output with printf()

printf() (print formatted) ប្រើបង្ហាញ output ។

Syntax:

printf("format string", variable1, variable2, ...);

ឧទាហរណ៍:

#include <stdio.h>

int main() {
    int age = 20;
    float score = 95.5;
    char grade = 'A';

    printf("Hello, World!\n");
    printf("Age: %d\n", age);
    printf("Score: %.2f\n", score);    /* .2 = 2 decimal places */
    printf("Grade: %c\n", grade);
    printf("Age: %d, Score: %.2f, Grade: %c\n", age, score, grade);

    return 0;
}

Escape Sequences (តួអក្សរពិសេស):

SequenceDescription
\nNewline (ចុះបន្ទាត់)
\tTab (ចន្លោះ Tab)
\rCarriage Return
\\Backslash
\"Double Quote
\'Single Quote
\0Null character

1.8.2 Input with scanf()

scanf() (scan formatted) ប្រើទទួល input ពីអ្នកប្រើប្រាស់។

Syntax:

scanf("format string", &variable1, &variable2, ...);
សំខាន់ណាស់: ក្នុង scanf() ត្រូវដាក់ & (address-of operator) មុន variable name ។ ដូចជា scanf("%d", &age); មិនមែន scanf("%d", age);

ឧទាហរណ៍:

#include <stdio.h>

int main() {
    int age;
    float height;
    char initial;

    printf("Enter your age: ");
    scanf("%d", &age);

    printf("Enter your height (m): ");
    scanf("%f", &height);

    printf("Enter your initial: ");
    scanf(" %c", &initial);   /* space before %c ដើម្បីរំលង whitespace */

    printf("\n--- Your Information ---\n");
    printf("Age: %d years\n", age);
    printf("Height: %.2f m\n", height);
    printf("Initial: %c\n", initial);

    return 0;
}

Input ច្រើន variables ក្នុងមួយ scanf:

#include <stdio.h>

int main() {
    int day, month, year;

    printf("Enter date (day month year): ");
    scanf("%d %d %d", &day, &month, &year);

    printf("Date: %02d/%02d/%d\n", day, month, year);
    /* %02d = បង្ហាញ 2 ខ្ទង់ ប្រសិនបើ 1 ខ្ទង់ ដាក់ 0 ទៅមុខ */

    return 0;
}

1.8.3 Naming Rules for Variables

/* ឈ្មោះត្រឹមត្រូវ */
int studentAge;
float _price;
int count123;

/* ឈ្មោះមិនត្រឹមត្រូវ */
int 123count;       /* ERROR - ចាប់ផ្ដើមដោយលេខ */
float my-price;     /* ERROR - មាន hyphen */
int for;            /* ERROR - keyword */

ឧទាហរណ៍ពេញលេញ - Student Information:

#include <stdio.h>

int main() {
    /* ប្រកាស variables */
    char name[50];
    int age;
    float score;
    char grade;

    /* Input */
    printf("===== Student Information =====\n");
    printf("Enter student name: ");
    scanf("%s", name);

    printf("Enter student age: ");
    scanf("%d", &age);

    printf("Enter student score: ");
    scanf("%f", &score);

    printf("Enter student grade (A/B/C/D/F): ");
    scanf(" %c", &grade);

    /* Output */
    printf("\n===== Student Report =====\n");
    printf("Name  : %s\n", name);
    printf("Age   : %d years old\n", age);
    printf("Score : %.2f\n", score);
    printf("Grade : %c\n", grade);

    return 0;
}

លំហាត់ប្រចាំមេរៀនទី 1 - Introduction to C (printf, scanf, data types)

  1. សរសេរកម្មវិធីបង្ហាញពាក្យ "Hello, C Programming!" នៅលើអេក្រង់។
  2. សរសេរកម្មវិធីប្រកាសអថេរប្រភេទ int, float, និង char រួចកំណត់តម្លៃ និងបង្ហាញវាមកវិញ។
  3. សរសេរកម្មវិធីទទួលយកអាយុ (ជាចំនួនគត់) ពីក្តារចុចដោយប្រើ scanf ហើយបង្ហាញអាយុនោះមកវិញ។
  4. សរសេរកម្មវិធីទទួលយកចំនួនគត់ពីរពីអ្នកប្រើប្រាស់ រួចគណនា និងបង្ហាញផលបូករបស់វា។
  5. សរសេរកម្មវិធីគណនាផ្ទៃក្រឡាចតុកោណកែង (ដោយឲ្យអ្នកប្រើប្រាស់បញ្ចូលបណ្តោយ និងទទឹងជាប្រភេទ float)។
  6. សរសេរកម្មវិធីទទួលយកតួអក្សរមួយ (char) ពីអ្នកប្រើប្រាស់ ហើយបង្ហាញតួអក្សរនោះ។
  7. សរសេរកម្មវិធីប្តូរតម្លៃពីឯកតាម៉ែត្រ ទៅជាសង់ទីម៉ែត្រ។
  8. សរសេរកម្មវិធីគណនាមធ្យមភាគនៃពិន្ទុមុខវិជ្ជាចំនួន៣ (ជាប្រភេទ float)។
  9. សរសេរកម្មវិធីប្រើប្រាស់ sizeof() ដើម្បីរកទំហំ (Bytes) របស់ប្រភេទ int, float, double, និង char
  10. សរសេរកម្មវិធីទទួលយកឈ្មោះមួយម៉ាត់ (string ដោយប្រើ %s ក្នុង scanf) រួចបង្ហាញពាក្យស្វាគមន៍ទៅកាន់ឈ្មោះនោះ។

❖ 2. Operators & Expressions in C

2.1 What are Operators?រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Operators គឺជានិមិត្តសញ្ញាពិសេស ដែលប្រាប់ compiler ឱ្យធ្វើប្រមាណវិធីលើ operands។ Expression គឺជាបន្សំ variables, values, operators ដែលផ្ដល់លទ្ធផល (value) មួយ។

int result = 10 + 5;
/* + = operator
   10 និង 5 = operands
   10 + 5 = expression
   result = variable ដែលទទួល value */

2.2 #define - Constantsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង C គេប្រើ #define (preprocessor macro) ដើម្បីកំណត់ constants ។ C99 ក៏អនុញ្ញាតឱ្យប្រើ const ក្នុង C++ style ផងដែរ។

Syntax:

#define NAME value

ឧទាហរណ៍:

#include <stdio.h>

#define PI 3.14159
#define MAX_SIZE 100
#define SCHOOL "ABC High School"
#define DAYS_IN_WEEK 7

int main() {
    printf("PI = %f\n", PI);
    printf("Max Size = %d\n", MAX_SIZE);
    printf("School: %s\n", SCHOOL);
    printf("Days in week: %d\n", DAYS_IN_WEEK);

    /* PI = 3.14;  // ERROR - cannot modify #define */

    /* C99 style - const */
    const double gravity = 9.81;
    printf("Gravity: %.2f m/s2\n", gravity);

    return 0;
}
ភាពខុសគ្នា #define vs const:
  • #define - preprocessor macro, replacement ពីមុន compile, គ្មាន type checking
  • const - variable ពិតប្រាកដ, មាន type, type-safe, debuggable
  • C89/C90 ប្រើ #define ជាញឹកញាប់ ព្រោះ const ក្នុង C89 មិនស្មើ compile-time constant

2.3 Arithmetic Operators (សញ្ញាគណិត)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

OperatorNameExampleResult
+Addition (ផលបូក)10 + 515
-Subtraction (ផលដក)10 - 55
*Multiplication (ផលគុណ)10 * 550
/Division (ផលចែក)10 / 52
%Modulus (នៃសល់)10 % 31
#include <stdio.h>

int main() {
    int a = 20, b = 6;

    printf("a + b = %d\n", a + b);   /* 26 */
    printf("a - b = %d\n", a - b);   /* 14 */
    printf("a * b = %d\n", a * b);   /* 120 */
    printf("a / b = %d\n", a / b);   /* 3 (integer division!) */
    printf("a %% b = %d\n", a % b);  /* 2 (remainder) */

    /* Division ជាមួយ floating-point */
    float x = 20.0, y = 6.0;
    printf("x / y = %.4f\n", x / y); /* 3.3333 */

    return 0;
}
Integer Division: ការចែក integers ២ ផ្ដល់ integer result (កាត់ decimal)។ 7 / 2 = 3 មិនមែន 3.5 ។ ប្រើ (float)7 / 2 (type casting) ដើម្បីទទួល 3.5

2.4 Assignment Operatorsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

OperatorExampleEquivalent
=x = 5x = 5
+=x += 3x = x + 3
-=x -= 3x = x - 3
*=x *= 3x = x * 3
/=x /= 3x = x / 3
%=x %= 3x = x % 3
#include <stdio.h>

int main() {
    int x = 10;
    printf("Initial: x = %d\n", x);

    x += 5;
    printf("After x += 5: x = %d\n", x);   /* 15 */

    x -= 3;
    printf("After x -= 3: x = %d\n", x);   /* 12 */

    x *= 2;
    printf("After x *= 2: x = %d\n", x);   /* 24 */

    x /= 4;
    printf("After x /= 4: x = %d\n", x);   /* 6 */

    x %= 4;
    printf("After x %%= 4: x = %d\n", x);  /* 2 */

    return 0;
}

2.5 Comparison Operatorsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Comparison operators ប្រើប្រៀបធៀប 2 តម្លៃ ហើយ return 1 (true) ឬ 0 (false)។

OperatorMeaningExampleResult
==Equal to5 == 51 (true)
!=Not equal to5 != 31 (true)
>Greater than5 > 31 (true)
<Less than5 < 30 (false)
>=Greater or equal5 >= 51 (true)
<=Less or equal5 <= 30 (false)
#include <stdio.h>

int main() {
    int a = 10, b = 20;
    printf("a = %d, b = %d\n", a, b);
    printf("a == b : %d\n", a == b);  /* 0 */
    printf("a != b : %d\n", a != b);  /* 1 */
    printf("a > b  : %d\n", a > b);   /* 0 */
    printf("a < b  : %d\n", a < b);   /* 1 */
    printf("a >= b : %d\n", a >= b);  /* 0 */
    printf("a <= b : %d\n", a <= b);  /* 1 */
    return 0;
}
កុំច្រឡំ! == (ប្រៀបធៀប) ≠ = (ផ្ដល់តម្លៃ)។ if (x = 5) គឺ bug ព្រោះ assign 5 ទៅ x ហើយ always true!

2.6 Logical Operatorsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

OperatorNameDescriptionExampleResult
&&ANDពិត ប្រសិនបើទាំងពីរពិត1 && 00
||ORពិត ប្រសិនបើមួយណាពិត1 || 01
!NOTបញ្ច្រាស់តម្លៃ!10
#include <stdio.h>

int main() {
    int age = 20;
    int hasID = 1;   /* 1 = true, 0 = false ក្នុង C */

    /* AND - ទាំងពីរត្រូវ true */
    if (age >= 18 && hasID) {
        printf("You can enter!\n");
    }

    /* OR - មួយណាពិត */
    int isWeekend = 0;
    int isHoliday = 1;
    if (isWeekend || isHoliday) {
        printf("Day off!\n");
    }

    /* NOT */
    int isRaining = 0;
    if (!isRaining) {
        printf("Go outside!\n");
    }

    /* Short-circuit evaluation */
    int x = 0;
    if (x != 0 && 10/x > 2) {  /* 10/x មិន evaluate ប្រសិនបើ x==0 */
        printf("Safe!\n");
    }

    return 0;
}

2.7 Increment & Decrement Operatorsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

OperatorNameDescription
++xPre-incrementបន្ថែមមុន ហើយប្រើ
x++Post-incrementប្រើមុន ហើយបន្ថែម
--xPre-decrementដកមុន ហើយប្រើ
x--Post-decrementប្រើមុន ហើយដក
#include <stdio.h>

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

    /* Pre-increment: increment before use */
    printf("++a = %d\n", ++a);  /* print 6, a = 6 */
    printf("a = %d\n", a);      /* a = 6 */

    /* Post-increment: use then increment */
    printf("b++ = %d\n", b++);  /* print 5, b = 6 */
    printf("b = %d\n", b);      /* b = 6 */

    int x = 5;
    int y = ++x;  /* x = 6, y = 6 */

    int p = 5;
    int q = p++;  /* p = 6, q = 5 */

    printf("x=%d, y=%d\n", x, y);
    printf("p=%d, q=%d\n", p, q);

    return 0;
}

2.8 Bitwise Operators (ប្រមាណ Bit)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

C ប្រើ bitwise operators ដែលធ្វើការលើ bits ដោយផ្ទាល់ ។ នេះជាលក្ខណៈពិសេសរបស់ C ដែល high-level languages ជាច្រើនពុំមាន:

OperatorNameExample (a=5, b=3)Result
&Bitwise AND5 & 3 (0101 & 0011)1 (0001)
|Bitwise OR5 | 3 (0101 | 0011)7 (0111)
^Bitwise XOR5 ^ 3 (0101 ^ 0011)6 (0110)
~Bitwise NOT~5-6
<<Left Shift5 << 110
>>Right Shift5 >> 12
#include <stdio.h>

int main() {
    int a = 5;   /* binary: 00000101 */
    int b = 3;   /* binary: 00000011 */

    printf("a & b  = %d\n", a & b);   /* 1  (00000001) */
    printf("a | b  = %d\n", a | b);   /* 7  (00000111) */
    printf("a ^ b  = %d\n", a ^ b);   /* 6  (00000110) */
    printf("~a     = %d\n", ~a);      /* -6 */
    printf("a << 1 = %d\n", a << 1);  /* 10 (គុណ 2) */
    printf("a >> 1 = %d\n", a >> 1);  /* 2  (ចែក 2) */

    return 0;
}

2.9 Type Casting (បម្លែងប្រភេទ)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Type casting ជាការបម្លែង variable ពីប្រភេទមួយទៅប្រភេទផ្សេង:

Implicit Casting (ស្វ័យប្រវត្ត):

int x = 10;
float y = x;    /* int → float ស្វ័យប្រវត្ត */
printf("%f\n", y); /* 10.000000 */

Explicit Casting (ដោយប្រើ cast operator):

#include <stdio.h>

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

    /* Without cast - integer division */
    printf("7 / 2 = %d\n", a / b);           /* 3 */

    /* With cast - float division */
    printf("7 / 2 = %.2f\n", (float)a / b);  /* 3.50 */
    printf("7 / 2 = %.2f\n", (double)a / b); /* 3.50 */

    /* Cast float to int - cut decimal */
    float pi = 3.14159;
    int whole = (int)pi;
    printf("(int)3.14159 = %d\n", whole);   /* 3 */

    return 0;
}

លំហាត់ប្រចាំមេរៀនទី 2 - Operators & Expressions (#define, bitwise, cast)

  1. ប្រើប្រាស់ #define ដើម្បីកំណត់តម្លៃអថេរថេរ PI = 3.14159 ហើយគណនាបរិមាត្ររង្វង់។
  2. សរសេរកម្មវិធីរកសំណល់នៃការចែក (Modulus %) នៃចំនួនគត់ពីរ។
  3. សរសេរកម្មវិធីបង្ហាញពីការប្រើប្រាស់ Bitwise AND (&) លើចំនួនគត់ពីរ។
  4. សរសេរកម្មវិធីបង្ហាញពីការប្រើប្រាស់ Bitwise OR (|) និង XOR (^) លើចំនួនគត់ពីរ។
  5. សរសេរកម្មវិធីប្រើ Left Shift (<<) និង Right Shift (>>) ដើម្បីគុណ និងចែកចំនួនមួយនឹង ២ តាមប្រព័ន្ធគោលពីរ។
  6. សរសេរកម្មវិធីប្រើ Type Casting ដើម្បីបំប្លែងតម្លៃ float ទៅជា int បង្ហាញតែផ្នែកចំនួនគត់។
  7. សរសេរកម្មវិធីប្រៀបធៀបចំនួនពីរដោយប្រើ Relational Operators (>, <, ==, !=) រួចបង្ហាញលទ្ធផល 1 (ពិត) ឬ 0 (មិនពិត)។
  8. សរសេរកម្មវិធីប្រើ Logical AND (&&) និង Logical OR (||) ដើម្បីពិនិត្យលក្ខខណ្ឌច្រើនក្នុងពេលតែមួយ។
  9. សរសេរកម្មវិធីបង្ហាញពីភាពខុសគ្នារវាង Pre-increment (++x) និង Post-increment (x++)។
  10. សរសេរកម្មវិធីប្រើ Conditional (Ternary) Operator (? :) ដើម្បីរកចំនួនធំជាងគេក្នុងចំណោមចំនួនពីរ។

❖ 3. Mathematical Functions in C

3.1 Header <math.h>រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

C ផ្ដល់ mathematical functions ក្នុង <math.h> header file ។ ខុសពី C++ ដែលប្រើ <cmath>

#include <math.h>
សំខាន់ - Linking Math Library: ក្នុង Linux/Unix ត្រូវ link math library ក្នុង compile command:
gcc myprogram.c -o myprogram -lm
Windows (MinGW) ជាធម្មតា link ដោយស្វ័យប្រវត្ត ប៉ុន្តែ Linux ត្រូវ explicit -lm

3.2 Basic Mathematical Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

3.2.1 sqrt() - Square Root

ផ្ដល់ square root (ការ៉េ) នៃ number។

Syntax: double sqrt(double x)

#include <stdio.h>
#include <math.h>

int main() {
    double numbers[] = {4, 9, 16, 25, 2};
    int i;

    for (i = 0; i < 5; i++) {
        printf("sqrt(%.0f) = %.4f\n", numbers[i], sqrt(numbers[i]));
    }
    /* Output:
       sqrt(4)  = 2.0000
       sqrt(9)  = 3.0000
       sqrt(16) = 4.0000
       sqrt(25) = 5.0000
       sqrt(2)  = 1.4142 */

    return 0;
}

3.2.2 pow() - Power (ស្វ័យគុណ)

គណនា xy (x raised to the power y)。

Syntax: double pow(double x, double y)

#include <stdio.h>
#include <math.h>

int main() {
    printf("2^3   = %.0f\n", pow(2, 3));    /* 8 */
    printf("5^2   = %.0f\n", pow(5, 2));    /* 25 */
    printf("10^0  = %.0f\n", pow(10, 0));   /* 1 */
    printf("4^0.5 = %.1f\n", pow(4, 0.5)); /* 2.0 (same as sqrt) */
    printf("2^-1  = %.1f\n", pow(2, -1));  /* 0.5 */

    return 0;
}

3.2.3 fabs() - Absolute Value (តម្លៃដាច់ខាត)

ផ្ដល់ absolute value (positive value) ។ ក្នុង C ប្រើ fabs() សម្រាប់ double, abs() ពី <stdlib.h> សម្រាប់ int។

Syntax: double fabs(double x)

#include <stdio.h>
#include <math.h>
#include <stdlib.h>  /* for abs() */

int main() {
    int a = -10;
    double b = -15.5;

    printf("abs(%d)    = %d\n", a, abs(a));     /* 10 */
    printf("fabs(%.1f) = %.1f\n", b, fabs(b));  /* 15.5 */

    /* ចម្ងាយរវាង 2 ចំណុច */
    int p1 = 5, p2 = -3;
    printf("Distance: %d\n", abs(p1 - p2));   /* 8 */

    return 0;
}

3.2.4 ceil() - Ceiling (បង្គត់ឡើង)

Syntax: double ceil(double x)

printf("ceil(4.2)  = %.0f\n", ceil(4.2));  /* 5 */
printf("ceil(4.8)  = %.0f\n", ceil(4.8));  /* 5 */
printf("ceil(-4.2) = %.0f\n", ceil(-4.2)); /* -4 */
printf("ceil(5.0)  = %.0f\n", ceil(5.0));  /* 5 */

3.2.5 floor() - Floor (បង្គត់ចុះ)

Syntax: double floor(double x)

printf("floor(4.2)  = %.0f\n", floor(4.2));  /* 4 */
printf("floor(4.8)  = %.0f\n", floor(4.8));  /* 4 */
printf("floor(-4.2) = %.0f\n", floor(-4.2)); /* -5 */
printf("floor(5.0)  = %.0f\n", floor(5.0));  /* 5 */

3.2.6 round() - Round (C99)

Syntax: double round(double x) (C99 លើ)

printf("round(4.2)  = %.0f\n", round(4.2));  /* 4 */
printf("round(4.5)  = %.0f\n", round(4.5));  /* 5 */
printf("round(4.8)  = %.0f\n", round(4.8));  /* 5 */
printf("round(-4.5) = %.0f\n", round(-4.5)); /* -5 */
C89 មិនមាន round(): ប្រើ floor(x + 0.5) ជំនួសសម្រាប់ positive numbers ក្នុង C89។

ឧទាហរណ៍ - Math Functions Calculator:

#include <stdio.h>
#include <math.h>

int main() {
    double num;

    printf("Enter a number: ");
    scanf("%lf", &num);

    printf("\n===== Math Functions Results =====\n");
    printf("Original  : %.4f\n", num);
    printf("sqrt      : %.4f\n", sqrt(num));
    printf("num^2     : %.4f\n", pow(num, 2));
    printf("num^3     : %.4f\n", pow(num, 3));
    printf("fabs      : %.4f\n", fabs(num));
    printf("ceil      : %.0f\n", ceil(num));
    printf("floor     : %.0f\n", floor(num));
    printf("round     : %.0f\n", round(num));

    return 0;
}

3.3 Trigonometric Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

អនុគមន៍ Trigonometric ប្រើ radians (មិនមែន degrees)!

រូបមន្ត conversion:
radians = degrees × π / 180
degrees = radians × 180 / π

sin(), cos(), tan():

#include <stdio.h>
#include <math.h>

#define PI 3.14159265359

int main() {
    double degrees, radians;

    printf("Enter angle in degrees: ");
    scanf("%lf", °rees);

    radians = degrees * PI / 180.0;

    printf("\nAngle: %.2f degrees = %.4f radians\n", degrees, radians);
    printf("sin(%.2f) = %.4f\n", degrees, sin(radians));
    printf("cos(%.2f) = %.4f\n", degrees, cos(radians));
    printf("tan(%.2f) = %.4f\n", degrees, tan(radians));

    /* Inverse trig */
    printf("\nasin(0.5) = %.2f degrees\n", asin(0.5) * 180.0 / PI);
    printf("acos(0.5) = %.2f degrees\n", acos(0.5) * 180.0 / PI);
    printf("atan(1.0) = %.2f degrees\n", atan(1.0) * 180.0 / PI);

    return 0;
}

3.4 Exponential & Logarithmic Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

#include <stdio.h>
#include <math.h>

int main() {
    /* Exponential */
    printf("exp(0) = %.5f\n", exp(0));   /* 1.00000 */
    printf("exp(1) = %.5f\n", exp(1));   /* 2.71828 (e) */
    printf("exp(2) = %.5f\n", exp(2));   /* 7.38906 */

    /* Natural log */
    printf("log(1)  = %.5f\n", log(1));   /* 0 */
    printf("log(M_E)= %.5f\n", log(exp(1))); /* 1 */

    /* Log base 10 */
    printf("log10(10)  = %.1f\n", log10(10));   /* 1.0 */
    printf("log10(100) = %.1f\n", log10(100));  /* 2.0 */

    /* log base 2 (C99) */
    printf("log2(8) = %.1f\n", log2(8));  /* 3.0 */

    return 0;
}

Summary Table - Math Functions:

FunctionHeaderDescriptionExample → Result
sqrt(x)math.hការ៉េsqrt(16) → 4
pow(x,y)math.hx^ypow(2,3) → 8
abs(x)stdlib.h|x| (int)abs(-5) → 5
fabs(x)math.h|x| (double)fabs(-5.5) → 5.5
ceil(x)math.hបង្គត់ឡើងceil(4.2) → 5
floor(x)math.hបង្គត់ចុះfloor(4.8) → 4
round(x)math.hបង្គត់ជិត (C99)round(4.5) → 5
sin(x)math.hSine (radians)sin(0) → 0
cos(x)math.hCosine (radians)cos(0) → 1
tan(x)math.hTangent (radians)tan(0) → 0
exp(x)math.he^xexp(1) → 2.71828
log(x)math.hln(x)log(10) → 2.30259
log10(x)math.hlog₁₀(x)log10(100) → 2
log2(x)math.hlog₂(x) (C99)log2(8) → 3

លំហាត់ប្រចាំមេរៀនទី 3 - Mathematical Functions (math.h)

  1. សរសេរកម្មវិធីទទួលយកចំនួនពីរ (គោល និងនិទស្សន្ត) រួចគណនាស្វ័យគុណដោយប្រើអនុគមន៍ pow()
  2. សរសេរកម្មវិធីរកឫសការ៉េ (Square Root) នៃចំនួនមួយដែលបញ្ចូលពីក្តារចុចដោយប្រើ sqrt()
  3. សរសេរកម្មវិធីរកតម្លៃដាច់ខាត (Absolute value) នៃចំនួនអវិជ្ជមានដោយប្រើ abs() (សម្រាប់ int) ឬ fabs() (សម្រាប់ float)។
  4. សរសេរកម្មវិធីធ្វើការបង្គត់ឡើង (Round up) នៃចំនួនទសភាគដោយប្រើអនុគមន៍ ceil()
  5. សរសេរកម្មវិធីធ្វើការបង្គត់ចុះ (Round down) នៃចំនួនទសភាគដោយប្រើអនុគមន៍ floor()
  6. សរសេរកម្មវិធីរកតម្លៃស៊ីនុស នៃមុំមួយ (គិតជារ៉ាដ្យង់) ដោយប្រើ sin()
  7. សរសេរកម្មវិធីរកតម្លៃកូស៊ីនុស នៃមុំមួយដោយប្រើ cos()
  8. សរសេរកម្មវិធីរកលោការីតធម្មជាតិ (Natural log base e) ដោយប្រើ log()
  9. សរសេរកម្មវិធីរកលោការីតគោល១០ ដោយប្រើអនុគមន៍ log10()
  10. សរសេរកម្មវិធីប្រើអនុគមន៍ fmod() ក្នុង <math.h> ដើម្បីរកសំណល់នៃការចែកចំនួនទសភាគពីរ។

❖ 4. Control Structures in C

Control Structures គ្រប់គ្រង execution flow នៃ program។ ពួកវាមាន 3 ប្រភេទ: Sequence, Selection, Iteration។

4.1 Sequence Control Structureរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Sequence Control Structure ប្រតិបត្តិ statements តាមលំដាប់ ពីលើទៅក្រោម ។ ចុះបន្ទាត់ស្ដាំ = statement ត្រូវបញ្ចប់ទើបទៅ statement ក្រោយ។

Flowchart: Sequence Control Structure
StartStatement 1Statement 2Statement 3End

📌 ប្រតិបត្តិពីលើទៅក្រោម រហូតដល់ END

#include <stdio.h>

int main() {
    /* ប្រតិបត្តិតាមលំដាប់ */
    double price, tax, total;

    printf("Enter price: $");
    scanf("%lf", &price);

    tax = price * 0.10;       /* Statement 1 */
    total = price + tax;       /* Statement 2 */

    printf("Price : $%.2f\n", price);   /* Statement 3 */
    printf("Tax   : $%.2f\n", tax);     /* Statement 4 */
    printf("Total : $%.2f\n", total);   /* Statement 5 */

    return 0;
}

4.2 Selection Control Structureរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Selection Control Structure (Decision/Conditional) ជ្រើសរើស execution path ផ្អែកលើ condition។

4.2.1 if Statement

Syntax:

if (condition) {
    /* ប្រតិបត្តិ ប្រសិនបើ condition != 0 (true) */
}
Flowchart: if Statement
StartCondition?YesExecute statementEndNo
#include <stdio.h>

int main() {
    int age;
    printf("Enter your age: ");
    scanf("%d", &age);

    if (age >= 18) {
        printf("You are an adult.\n");
        printf("You can vote!\n");
    }

    printf("Program ends.\n");
    return 0;
}

4.2.2 if-else Statement

if (condition) {
    /* true block */
} else {
    /* false block */
}
Flowchart: if-else Statement
StartCondition?YesNoif blockelse blockEnd
#include <stdio.h>

int main() {
    int num;
    printf("Enter a number: ");
    scanf("%d", &num);

    if (num % 2 == 0) {
        printf("%d is EVEN\n", num);
    } else {
        printf("%d is ODD\n", num);
    }

    return 0;
}

4.2.3 if-else if-else Statement

#include <stdio.h>

int main() {
    int score;
    printf("Enter your score (0-100): ");
    scanf("%d", &score);

    if (score >= 90) {
        printf("Grade: A (Excellent!)\n");
    } else if (score >= 80) {
        printf("Grade: B (Very Good)\n");
    } else if (score >= 70) {
        printf("Grade: C (Good)\n");
    } else if (score >= 60) {
        printf("Grade: D (Pass)\n");
    } else {
        printf("Grade: F (Fail)\n");
    }

    return 0;
}

4.2.4 Ternary Operator (? :)

C មាន ternary operator ដែលជា shortcut សម្រាប់ if-else ។

Syntax: condition ? value_if_true : value_if_false

#include <stdio.h>

int main() {
    int a = 10, b = 20;
    int max;

    max = (a > b) ? a : b;   /* if(a>b) max=a; else max=b; */
    printf("Max = %d\n", max);   /* 20 */

    int x = 5;
    printf("%s\n", (x % 2 == 0) ? "Even" : "Odd");  /* Odd */

    return 0;
}

4.2.5 switch Statement

switch ពិនិត្យតម្លៃ integer/char ជាក់លាក់ ។

Flowchart: switch Statement
Startcase 1?YesCode 1breakNocase 2?YesCode 2breakNoDefaultEnd
#include <stdio.h>

int main() {
    int choice;
    double a, b;

    printf("===== Calculator =====\n");
    printf("1. Add\n2. Subtract\n3. Multiply\n4. Divide\n");
    printf("Choice: ");
    scanf("%d", &choice);

    printf("Enter two numbers: ");
    scanf("%lf %lf", &a, &b);

    switch (choice) {
        case 1:
            printf("%.2f + %.2f = %.2f\n", a, b, a + b);
            break;
        case 2:
            printf("%.2f - %.2f = %.2f\n", a, b, a - b);
            break;
        case 3:
            printf("%.2f * %.2f = %.2f\n", a, b, a * b);
            break;
        case 4:
            if (b != 0)
                printf("%.2f / %.2f = %.2f\n", a, b, a / b);
            else
                printf("Error: Division by zero!\n");
            break;
        default:
            printf("Invalid choice!\n");
    }
    return 0;
}

4.3 Iteration Control Structure (Loops)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

4.3.1 for Loop

Syntax:

for (initialization; condition; increment/decrement) {
    /* body */
}
Flowchart: for Loop
Starti = 0i &lt; n?YesLoop Body + i++Loop backNoEnd
#include <stdio.h>

int main() {
    int i, n, sum = 0;

    printf("Enter n: ");
    scanf("%d", &n);

    /* for loop - loop n times */
    for (i = 1; i <= n; i++) {
        sum += i;
        printf("i=%d, sum=%d\n", i, sum);
    }
    printf("Total sum = %d\n", sum);

    /* Multiplication table */
    int num = 5;
    printf("\nMultiplication table of %d:\n", num);
    for (i = 1; i <= 10; i++) {
        printf("%d x %d = %d\n", num, i, num * i);
    }

    return 0;
}

4.3.2 while Loop

Syntax:

while (condition) {
    /* body */
}
Flowchart: while Loop
StartCondition?YesLoop BodyLoop backNoEnd

📌 ពិនិត្យ Condition មុន → ប្រសិនបើ FALSE ពីដំបូង Loop Body មិនប្រតិបត្តិ (0 ដង)

#include <stdio.h>

int main() {
    /* Guess the number game */
    int secret = 7, guess;

    printf("Guess the number (1-10): ");
    scanf("%d", &guess);

    while (guess != secret) {
        if (guess < secret)
            printf("Too low! Try again: ");
        else
            printf("Too high! Try again: ");
        scanf("%d", &guess);
    }

    printf("Congratulations! Correct!\n");
    return 0;
}

4.3.3 do-while Loop

Syntax:

do {
    /* body - executes at least once */
} while (condition);
Flowchart: do-while Loop
StartExecute Loop Body (do)Condition? (while)YesNoEnd

⚠️ Loop Body ប្រតិបត្តិមុន → ពិនិត្យ Condition ក្រោយ → យ៉ាងហោចណាស់ 1 ដង!

#include <stdio.h>

int main() {
    int choice;

    do {
        printf("\n===== Menu =====\n");
        printf("1. Say Hello\n");
        printf("2. Show Date\n");
        printf("3. Exit\n");
        printf("Choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1: printf("Hello, User!\n"); break;
            case 2: printf("Today is a great day!\n"); break;
            case 3: printf("Goodbye!\n"); break;
            default: printf("Invalid choice!\n");
        }
    } while (choice != 3);

    return 0;
}

ប្រៀបធៀប Loops:

Featurefor Loopwhile Loopdo-while Loop
ចំនួនដងដឹងជាមុនមិនដឹងមិនដឹង, ≥1
ពិនិត្យ conditionមុន executeមុន executeបន្ទាប់ execute
Minimum executions001
ឧទាហរណ៍Loop arraysInput validationMenu system

4.3.4 break និង continue

Flowchart: break Statement
StartLoop Condition?YesBreak?YesBREAK!NoLoop Body ContinuesLoop backEndNo
#include <stdio.h>

int main() {
    int i;

    /* break - ចេញពី loop */
    for (i = 1; i <= 100; i++) {
        if (i % 7 == 0) {
            printf("First multiple of 7: %d\n", i);
            break;
        }
    }

    /* continue - រំលង iteration បច្ចុប្បន្ន */
    printf("Odd numbers: ");
    for (i = 1; i <= 10; i++) {
        if (i % 2 == 0) continue;  /* រំលងលេខគូ */
        printf("%d ", i);
    }
    printf("\n");  /* Output: 1 3 5 7 9 */

    return 0;
}

4.3.5 Nested Loops

#include <stdio.h>

int main() {
    int i, j, n = 5;

    /* Triangle pattern */
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= i; j++) {
            printf("* ");
        }
        printf("\n");
    }
    /* Output:
       *
       * *
       * * *
       * * * *
       * * * * * */

    return 0;
}

4.3.6 goto Statement (C-specific)

C មាន goto statement ដែលលោតទៅ label ណាមួយ ។ ជាធម្មតាមិន recommended ប៉ុន្តែ C ប្រើក្នុង error handling ខ្លះ:

#include <stdio.h>

int main() {
    int i = 0;

start:
    if (i < 5) {
        printf("i = %d\n", i);
        i++;
        goto start;  /* Jump back to label "start" */
    }

    printf("Done!\n");
    return 0;
}
ដំបូន្មាន: ជៀសវាង goto ក្នុងការ programming ធម្មតា ព្រោះវាធ្វើឱ្យកូដអានពិបាក (spaghetti code)។ ប្រើ loops ជំនួស។ goto ប្រើតែក្នុង error cleanup patterns ខ្លះ។

លំហាត់ប្រចាំមេរៀនទី 4 - Control Structures (if, switch, loops, goto)

  1. សរសេរកម្មវិធីពិនិត្យមើលថាចំនួនដែលបញ្ចូល ជាចំនួនគូ (Even) ឬចំនួនសេស (Odd) ដោយប្រើ if-else
  2. សរសេរកម្មវិធីរកចំនួនធំបំផុតក្នុងចំណោមចំនួន៣ ដោយប្រើ Nested if-else
  3. សរសេរកម្មវិធីពិនិត្យឆ្នាំពន្លត់ (Leap year) ដោយផ្អែកលើលក្ខខណ្ឌចែកដាច់នឹង ៤ និងមិនដាច់នឹង ១០០ ឬចែកដាច់នឹង ៤០០។
  4. សរសេរកម្មវិធីបំប្លែងពិន្ទុ (1-100) ទៅជានិទ្ទេស (A, B, C, D, F) ដោយប្រើ if-else if
  5. សរសេរកម្មវិធីម៉ាស៊ីនគិតលេខសាមញ្ញ (ទទួលយក +, -, *, /) ដោយប្រើ switch-case
  6. សរសេរកម្មវិធីបង្ហាញលេខពី 1 ដល់ n ដែលបញ្ចូលដោយអ្នកប្រើប្រាស់ ដោយប្រើរង្វិលជុំ for
  7. សរសេរកម្មវិធីគណនាផលបូកនៃលេខពី 1 ដល់ n ដោយប្រើរង្វិលជុំ while
  8. សរសេរកម្មវិធីបង្កើតតារាងមេគុណនៃលេខមួយ (ឧ. មេ៥ ពី 5x1 ដល់ 5x10) ដោយប្រើ for
  9. សរសេរកម្មវិធីទាមទារឱ្យអ្នកប្រើប្រាស់បញ្ចូលលេខសម្ងាត់រហូតទាល់តែត្រឹមត្រូវ ទើបអាចបន្តទៅមុខបាន ដោយប្រើ do-while
  10. សរសេរកម្មវិធីដែលប្រើ break ដើម្បីបញ្ចប់ loop មុនកំណត់ និងប្រើ goto ដើម្បីលោតទៅកាន់ label បង្ហាញសារបញ្ចប់កម្មវិធី។

❖ 5. Functions in C

5.1 Introduction to Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Function ជា block នៃ code ដែលរៀបចំឡើងដើម្បីធ្វើ task ជាក់លាក់ ហើយ អាចហៅ (call) ច្រើនដងក្នុង program។

ហេតុអ្វីប្រើ Functions:

5.2 Function Structureរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

returnType functionName(parameter1, parameter2, ...) {
    /* Function body */
    /* statements */
    return value;   /* optional */
}

ឧទាហរណ៍:

int add(int a, int b) {
    int sum = a + b;
    return sum;
}
/* int    = return type
   add    = function name
   int a, int b = parameters
   return sum = return statement */

5.3 Function Declaration (Prototype)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Function prototype ជាការប្រកាស function signature មុនពេលប្រើ ។ ត្រូវ declare prototype ដែល compiler ដឹងអំពី function ដែល call ។

Syntax:

returnType functionName(parameterTypes);
#include <stdio.h>

/* Function Prototypes (declarations) */
int add(int, int);
void greet(void);
double circleArea(double);
int isEven(int);

int main() {
    int result = add(5, 3);
    printf("5 + 3 = %d\n", result);

    greet();

    double area = circleArea(5.0);
    printf("Circle area (r=5): %.2f\n", area);

    printf("Is 10 even? %s\n", isEven(10) ? "Yes" : "No");

    return 0;
}

/* Function Definitions */
int add(int a, int b) {
    return a + b;
}

void greet(void) {
    printf("Hello from C!\n");
}

double circleArea(double radius) {
    return 3.14159 * radius * radius;
}

int isEven(int n) {
    return (n % 2 == 0);  /* return 1 (true) or 0 (false) */
}
C vs C++ Prototype: ក្នុង C void ត្រូវ explicit ក្នុង parameter list ប្រសិនបើ function មិនទទួល argument: void greet(void); មិនមែន void greet(); (ក្នុង C89 greet() មានន័យថា accept any parameters!)

5.4 Types of Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

5.4.1 No Parameter, No Return

#include <stdio.h>

void displayWelcome(void) {
    printf("========================================\n");
    printf("   Welcome to C Programming!           \n");
    printf("========================================\n");
}

int main() {
    displayWelcome();
    return 0;
}

5.4.2 With Parameters, No Return

#include <stdio.h>

void printSquare(int num) {
    printf("Square of %d = %d\n", num, num * num);
}

void greetUser(char name[]) {
    printf("Hello, %s!\n", name);
}

int main() {
    printSquare(5);
    printSquare(10);
    greetUser("Sokha");
    return 0;
}

5.4.3 No Parameter, With Return

#include <stdio.h>

double getPi(void) {
    return 3.14159265359;
}

int getMaxInt(void) {
    return 2147483647;
}

int main() {
    printf("PI = %.10f\n", getPi());
    printf("Max int = %d\n", getMaxInt());
    return 0;
}

5.4.4 With Parameters, With Return (ប្រើច្រើនបំផុត)

#include <stdio.h>
#include <math.h>

int findMax(int a, int b) {
    return (a > b) ? a : b;
}

double power(double base, double exp) {
    return pow(base, exp);
}

int isPrime(int n) {
    int i;
    if (n <= 1) return 0;
    if (n == 2) return 1;
    for (i = 2; i <= (int)sqrt(n); i++) {
        if (n % i == 0) return 0;
    }
    return 1;
}

int main() {
    printf("Max(10, 25) = %d\n", findMax(10, 25));
    printf("2^8 = %.0f\n", power(2, 8));
    printf("Is 17 prime? %s\n", isPrime(17) ? "Yes" : "No");
    return 0;
}

5.5 Pass by Valueរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង C by default, arguments ត្រូវបាន pass by value គឺ function ទទួល copy ។ ផ្លាស់ប្ដូរ parameter ក្នុង function មិនប៉ះពាល់ original variable ។

#include <stdio.h>

void modifyValue(int x) {
    x = x * 2;
    printf("Inside function: x = %d\n", x);
}

int main() {
    int num = 10;
    printf("Before: num = %d\n", num);
    modifyValue(num);
    printf("After : num = %d\n", num);  /* នៅតែ 10! */
    return 0;
}
/* Output:
   Before: num = 10
   Inside function: x = 20
   After : num = 10   ← មិនផ្លាស់ប្ដូរ */

5.6 Pass by Pointer (Pass by Reference in C)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង C គ្មាន pass by reference ដូច C++ ទេ ។ ជំនួស ប្រើ pointers ដើម្បីផ្លាស់ប្ដូរ original variable ។

#include <stdio.h>

void modifyValue(int *x) {  /* ទទួល pointer */
    *x = *x * 2;            /* dereference pointer */
    printf("Inside function: *x = %d\n", *x);
}

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int num = 10;
    printf("Before: num = %d\n", num);
    modifyValue(&num);           /* pass address of num */
    printf("After : num = %d\n", num);  /* ផ្លាស់ប្ដូរ! 20 */

    int x = 5, y = 10;
    printf("\nBefore swap: x=%d, y=%d\n", x, y);
    swap(&x, &y);
    printf("After swap : x=%d, y=%d\n", x, y);
    return 0;
}
/* Output:
   Before: num = 10
   Inside function: *x = 20
   After : num = 20   ← ផ្លាស់ប្ដូរ!
   Before swap: x=5, y=10
   After swap : x=10, y=5 */

5.7 Recursive Functions (អនុគមន៍ Recursive)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Recursive function ជា function ដែលហៅខ្លួនឯង ។ ត្រូវតែមាន base case ដើម្បីបញ្ចប់ recursion ។

#include <stdio.h>

/* Factorial: n! = n * (n-1) * ... * 1 */
long long factorial(int n) {
    if (n == 0 || n == 1)   /* Base case */
        return 1;
    return n * factorial(n - 1);  /* Recursive case */
}

/* Fibonacci: fib(n) = fib(n-1) + fib(n-2) */
int fibonacci(int n) {
    if (n == 0) return 0;   /* Base case */
    if (n == 1) return 1;   /* Base case */
    return fibonacci(n-1) + fibonacci(n-2);  /* Recursive */
}

/* Sum: 1 + 2 + ... + n */
int sumN(int n) {
    if (n == 0) return 0;
    return n + sumN(n - 1);
}

int main() {
    int i;
    printf("Factorials:\n");
    for (i = 0; i <= 10; i++) {
        printf("%d! = %lld\n", i, factorial(i));
    }

    printf("\nFibonacci sequence (first 10):\n");
    for (i = 0; i < 10; i++) {
        printf("fib(%d) = %d\n", i, fibonacci(i));
    }

    printf("\nSum 1 to 10 = %d\n", sumN(10));
    return 0;
}

5.8 Static Variables in Functionsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

static variable ក្នុង function រក្សាតម្លៃ រហូតដល់ program បញ្ចប់ (មិនត្រូវ reset ពេល function ហៅឡើងវិញ):

#include <stdio.h>

void counter(void) {
    static int count = 0;  /* initialized once only */
    count++;
    printf("Function called %d time(s)\n", count);
}

int main() {
    counter();  /* 1 */
    counter();  /* 2 */
    counter();  /* 3 */
    return 0;
}

5.9 Function Scopeរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Scope កំណត់ថា variable visible/accessible ពីណា:

#include <stdio.h>

int globalVar = 100;    /* Global: accessible everywhere */

void showScope(void) {
    int localVar = 200;  /* Local: accessible only in this function */
    printf("Global: %d\n", globalVar);  /* OK */
    printf("Local : %d\n", localVar);   /* OK */
}

int main() {
    printf("Global: %d\n", globalVar);  /* OK */
    /* printf("%d", localVar); */        /* ERROR - not visible */
    showScope();
    return 0;
}

ឧទាហរណ៍ពេញលេញ - Student Grade System:

#include <stdio.h>

/* Prototypes */
char getGrade(float score);
int isPassed(float score);
void printHeader(void);
void displayStudent(char name[], int age, float score);

int main() {
    printHeader();
    displayStudent("Sokha", 20, 85.5);
    displayStudent("Dara", 21, 72.0);
    displayStudent("Bopha", 22, 55.0);
    return 0;
}

char getGrade(float score) {
    if (score >= 90) return 'A';
    else if (score >= 80) return 'B';
    else if (score >= 70) return 'C';
    else if (score >= 60) return 'D';
    return 'F';
}

int isPassed(float score) {
    return score >= 60;
}

void printHeader(void) {
    printf("========================================\n");
    printf("       Student Information System       \n");
    printf("========================================\n");
}

void displayStudent(char name[], int age, float score) {
    printf("Name : %s\n", name);
    printf("Age  : %d\n", age);
    printf("Score: %.2f\n", score);
    printf("Grade: %c\n", getGrade(score));
    printf("Status: %s\n", isPassed(score) ? "PASS" : "FAIL");
    printf("-------------------\n");
}

លំហាត់ប្រចាំមេរៀនទី 5 - Functions (prototypes, recursion, scope)

  1. បង្កើត Function greetUser() ដែលគ្មាន parameter និងគ្មាន return ដើម្បីបង្ហាញពាក្យ "Welcome!" រួចហៅវាប្រើក្នុង main()
  2. បង្កើត Function addNumbers(int a, int b) ដើម្បីបូកលេខពីរ រួច return លទ្ធផលទៅកាន់ main()
  3. បង្កើត Function គណនាផ្ទៃក្រឡារង្វង់ ដែលទទួលយកកាំ (radius) និង return លទ្ធផលជា float
  4. សរសេរកម្មវិធីដែលមាន Function Prototypes ប្រកាសនៅខាងលើ main() ហើយតួ Function ពេញលេញសរសេរនៅខាងក្រោម។
  5. សរសេរកម្មវិធីបង្ហាញពីភាពខុសគ្នារវាង Local Variable (ប្រកាសក្នុង function) និង Global Variable (ប្រកាសក្រៅ function ទាំងអស់)។
  6. បង្កើត Function មួយដើម្បីរកចំនួនតូចបំផុតក្នុងចំណោមពីរចំនួន ដោយប្រើប្រាស់អនុគមន៍បញ្ជូនតម្លៃ (Pass by value)។
  7. បង្កើត Recursive Function ដើម្បីគណនាហ្វាក់តូរីយ៉ែល (Factorial, n!) នៃចំនួនគត់ n។
  8. បង្កើត Recursive Function ដើម្បីរកតម្លៃនៃតួទី n របស់ស្វីត Fibonacci។
  9. បង្កើត Function សម្រាប់បំប្លែងសីតុណ្ហភាពពីអង្សាសេ ទៅអង្សាហ្វារិនហៃ។
  10. បង្កើត Function ដែលទទួលយកចំនួនគត់មួយ ហើយត្រឡប់តម្លៃ 1 បើវាជា Prime Number និង 0 បើមិនមែនជា Prime Number។

❖ 6. Arrays in C

6.1 Introduction to Arraysរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Array ជា collection នៃ elements ដែលមានប្រភេទដូចគ្នា រក្សាទុកក្នុង memory locations ជាប់គ្នា (contiguous)។

ហេតុអ្វីប្រើ Arrays:

6.2 Array Declarationរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Syntax:

dataType arrayName[size];
int numbers[5];       /* array of 5 integers */
double prices[10];    /* array of 10 doubles */
char letters[26];     /* array of 26 characters */
char name[50];        /* C-string: char array for names */
Array Index ចាប់ពី 0!
  • Element ទីមួយ: array[0]
  • Element ទីចុងក្រោយ: array[size-1]
  • C មិន check array bounds → access index ខុស = undefined behavior!

6.3 Array Initializationរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

#include <stdio.h>

int main() {
    /* 1. Initialize at declaration */
    int arr1[5] = {10, 20, 30, 40, 50};

    /* 2. Partial initialization - rest = 0 */
    int arr2[5] = {10, 20};   /* {10, 20, 0, 0, 0} */

    /* 3. All zeros */
    int arr3[5] = {0};        /* {0, 0, 0, 0, 0} */

    /* 4. Size auto-determined */
    int arr4[] = {100, 200, 300};  /* size = 3 */

    /* 5. Calculate size at runtime */
    int size = sizeof(arr4) / sizeof(arr4[0]);
    printf("arr4 size = %d\n", size);  /* 3 */

    /* Access and modify */
    arr1[0] = 99;
    printf("arr1[0] = %d\n", arr1[0]);

    return 0;
}

6.4 Array with Loopsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Input/Output Array:

#include <stdio.h>

int main() {
    int i;
    int numbers[5];
    int size = 5;

    /* Input */
    printf("Enter %d numbers:\n", size);
    for (i = 0; i < size; i++) {
        printf("Number[%d]: ", i);
        scanf("%d", &numbers[i]);
    }

    /* Output */
    printf("\nYou entered: ");
    for (i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    return 0;
}

Array Statistics:

#include <stdio.h>

int main() {
    int i;
    int numbers[] = {45, 12, 78, 23, 90, 34, 56};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int sum = 0, max, min;

    max = min = numbers[0];

    for (i = 0; i < size; i++) {
        sum += numbers[i];
        if (numbers[i] > max) max = numbers[i];
        if (numbers[i] < min) min = numbers[i];
    }

    printf("Array: ");
    for (i = 0; i < size; i++) printf("%d ", numbers[i]);
    printf("\n");
    printf("Sum     = %d\n", sum);
    printf("Average = %.2f\n", (double)sum / size);
    printf("Maximum = %d\n", max);
    printf("Minimum = %d\n", min);

    return 0;
}

6.5 Character Arrays (Strings in C)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង C គ្មាន string type ដូច C++ ទេ ។ Strings ត្រូវបានតំណាងដោយ char arrays ដែលបញ្ចប់ដោយ null character '\0'

Null Terminator '\0': រាល់ C string ត្រូវមាន '\0' នៅចុងបញ្ចប់ ។ ដូច្នេះ array size ត្រូវ = string length + 1 ។ ឧទាហរណ៍ "Sokha" (5 chars) ត្រូវការ char name[6] យ៉ាងតិច ។
#include <stdio.h>
#include <string.h>  /* for string functions */

int main() {
    /* Declaration and Initialization */
    char name1[20];                       /* ទុកទំហំ */
    char name2[] = "Sokha";              /* size = 6 (5+'\0') */
    char name3[20] = "Dara";
    char name4[] = {'B','o','p','h','a','\0'};  /* explicit '\0' */

    /* Print strings */
    printf("name2 = %s\n", name2);
    printf("name3 = %s\n", name3);
    printf("name4 = %s\n", name4);

    /* String length (not counting '\0') */
    printf("Length of name2 = %lu\n", strlen(name2));  /* 5 */

    /* Copy string */
    char dest[20];
    strcpy(dest, name2);
    printf("Copied: %s\n", dest);

    /* Concatenate */
    char full[50] = "Hello, ";
    strcat(full, name2);
    printf("Concat: %s\n", full);  /* Hello, Sokha */

    /* Compare */
    if (strcmp(name2, "Sokha") == 0)
        printf("name2 equals 'Sokha'\n");

    /* Compare n chars */
    if (strncmp(name2, "Sok", 3) == 0)
        printf("name2 starts with 'Sok'\n");

    return 0;
}

String Input/Output:

#include <stdio.h>

int main() {
    char word[50], sentence[200];

    /* scanf reads until whitespace */
    printf("Enter a word: ");
    scanf("%s", word);             /* no & needed for arrays */
    printf("Word: %s\n", word);

    /* fgets reads the entire line including spaces */
    printf("Enter a sentence: ");
    scanf(" ");                    /* clear buffer */
    fgets(sentence, sizeof(sentence), stdin);
    printf("Sentence: %s", sentence);

    /* gets() - avoid! unsafe (buffer overflow) */
    /* Use fgets() instead */

    return 0;
}

String Functions (string.h):

FunctionDescriptionExample
strlen(s)ប្រវែង stringstrlen("Hi") → 2
strcpy(dst, src)copy stringstrcpy(a, "Hi")
strncpy(dst, src, n)copy n chars (safe)strncpy(a, b, 10)
strcat(dst, src)concatenatestrcat(a, " World")
strncat(dst, src, n)concat n chars (safe)strncat(a, b, 5)
strcmp(s1, s2)compare (0=equal)strcmp("a","a") → 0
strncmp(s1, s2, n)compare n charsstrncmp(a, b, 3)
strchr(s, c)រក char ក្នុង stringstrchr("Hello", 'l')
strstr(s1, s2)រក substringstrstr("Hello","ll")
strupr/strlwrupper/lower caseplatform-specific
sprintf(buf,...)format to stringsprintf(s, "%d", 42)

ctype.h - Character Functions:

#include <stdio.h>
#include <ctype.h>

int main() {
    char c = 'A';

    printf("isalpha('%c') = %d\n", c, isalpha(c));   /* 1 */
    printf("isdigit('5')  = %d\n", isdigit('5'));     /* 1 */
    printf("islower('a')  = %d\n", islower('a'));     /* 1 */
    printf("isupper('A')  = %d\n", isupper('A'));     /* 1 */
    printf("isspace(' ')  = %d\n", isspace(' '));     /* 1 */
    printf("tolower('A')  = %c\n", tolower('A'));     /* a */
    printf("toupper('a')  = %c\n", toupper('a'));     /* A */

    return 0;
}

6.6 Multi-dimensional Arraysរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

C គាំទ្រ multi-dimensional arrays ។ 2D array ប្រើច្រើនបំផុត (matrix):

#include <stdio.h>

int main() {
    int i, j;

    /* 2D array declaration */
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    /* Print matrix */
    printf("Matrix:\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf("%3d", matrix[i][j]);
        }
        printf("\n");
    }

    /* Sum of diagonal */
    int diagSum = 0;
    for (i = 0; i < 3; i++) {
        diagSum += matrix[i][i];
    }
    printf("Diagonal sum = %d\n", diagSum);

    /* Matrix of strings */
    char students[3][20] = {"Sokha", "Dara", "Bopha"};
    printf("\nStudents:\n");
    for (i = 0; i < 3; i++) {
        printf("%d. %s\n", i+1, students[i]);
    }

    return 0;
}

ឧទាហរណ៍ - Sort and Search:

#include <stdio.h>

/* Bubble Sort */
void bubbleSort(int arr[], int size) {
    int i, j, temp;
    for (i = 0; i < size - 1; i++) {
        for (j = 0; j < size - i - 1; j++) {
            if (arr[j] > arr[j+1]) {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

/* Linear Search */
int linearSearch(int arr[], int size, int target) {
    int i;
    for (i = 0; i < size; i++) {
        if (arr[i] == target) return i;
    }
    return -1;
}

/* Display Array */
void displayArray(int arr[], int size) {
    int i;
    for (i = 0; i < size; i++) printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int numbers[] = {64, 34, 25, 12, 22, 11, 90};
    int size = 7;

    printf("Original: ");
    displayArray(numbers, size);

    int idx = linearSearch(numbers, size, 25);
    if (idx != -1)
        printf("Found 25 at index %d\n", idx);
    else
        printf("25 not found\n");

    bubbleSort(numbers, size);
    printf("Sorted  : ");
    displayArray(numbers, size);

    return 0;
}

ឧទាហរណ៍ - Student Grade Report:

#include <stdio.h>

#define MAX_STUDENTS 5

int main() {
    int i;
    char names[MAX_STUDENTS][30];
    float scores[MAX_STUDENTS];
    char grades[MAX_STUDENTS];

    /* Input */
    printf("===== Enter Student Info =====\n");
    for (i = 0; i < MAX_STUDENTS; i++) {
        printf("\nStudent %d:\n", i+1);
        printf("Name : "); scanf("%s", names[i]);
        printf("Score: "); scanf("%f", &scores[i]);

        if (scores[i] >= 90) grades[i] = 'A';
        else if (scores[i] >= 80) grades[i] = 'B';
        else if (scores[i] >= 70) grades[i] = 'C';
        else if (scores[i] >= 60) grades[i] = 'D';
        else grades[i] = 'F';
    }

    /* Statistics */
    float sum = 0, highest = scores[0], lowest = scores[0];
    int hiIdx = 0, loIdx = 0;

    for (i = 0; i < MAX_STUDENTS; i++) {
        sum += scores[i];
        if (scores[i] > highest) { highest = scores[i]; hiIdx = i; }
        if (scores[i] < lowest)  { lowest  = scores[i]; loIdx = i; }
    }

    /* Output Report */
    printf("\n===== Student Report =====\n");
    printf("%-15s %-8s %-6s\n", "Name", "Score", "Grade");
    printf("------------------------------\n");
    for (i = 0; i < MAX_STUDENTS; i++) {
        printf("%-15s %-8.2f %-6c\n", names[i], scores[i], grades[i]);
    }
    printf("\n===== Statistics =====\n");
    printf("Average : %.2f\n", sum / MAX_STUDENTS);
    printf("Highest : %.2f (%s)\n", highest, names[hiIdx]);
    printf("Lowest  : %.2f (%s)\n", lowest,  names[loIdx]);

    return 0;
}

លំហាត់ប្រចាំមេរៀនទី 6 - Arrays & Strings (char arrays, string.h)

  1. ប្រកាស Array មួយប្រភេទ int អាចផ្ទុកបាន ៥ធាតុ។ បញ្ចូលតម្លៃវាដោយប្រើ Loop ហើយបង្ហាញវាមកវិញ។
  2. សរសេរកម្មវិធីរកផលបូក និងមធ្យមភាគនៃគ្រប់ធាតុទាំងអស់ក្នុង Array ដែលមាន n ធាតុ។
  3. សរសេរកម្មវិធីរកតម្លៃធំបំផុត និងតូចបំផុតក្នុង Array នៃចំនួនគត់។
  4. សរសេរកម្មវិធីប្រើប្រាស់ 2D Array សម្រាប់បង្កើតម៉ាទ្រីស (Matrix) ទំហំ 3x3 រួចបង្ហាញវាតាមទម្រង់ជួរដេក និងជួរឈរ។
  5. សរសេរកម្មវិធីគណនាផលបូកនៃម៉ាទ្រីសពីរ (2D Arrays ទំហំ 2x2) រួចរក្សាទុកលទ្ធផលក្នុងម៉ាទ្រីសទី៣។
  6. ប្រកាស Char Array (String) ដើម្បីទទួលយកឈ្មោះពេញរបស់អ្នកប្រើប្រាស់ (ប្រើ gets()fgets()) ហើយបង្ហាញវាមកវិញ។
  7. សរសេរកម្មវិធីប្រើអនុគមន៍ strlen() ពីបណ្ណាល័យ <string.h> ដើម្បីរាប់ប្រវែង (ចំនួនតួអក្សរ) នៃ String មួយ។
  8. សរសេរកម្មវិធីប្រើ strcpy() ដើម្បីចម្លងទិន្នន័យពី String មួយទៅកាន់ String មួយទៀត។
  9. សរសេរកម្មវិធីប្រើ strcat() ដើម្បីតភ្ជាប់ String ពីរចូលគ្នាជា String តែមួយ។
  10. សរសេរកម្មវិធីប្រើ strcmp() ដើម្បីប្រៀបធៀប String ពីរ ថាដូចគ្នា ឬខុសគ្នា។

❖ 7. Pointers in C

7.1 Introduction to Pointersរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Pointer ជា variable ដែលរក្សាទុក memory address របស់ variable មួយទៀត ។ Pointers ជា feature ដ៏ powerful និងសំខាន់បំផុតក្នុង C ។

ហេតុអ្វីប្រើ Pointers:

7.2 Memory Conceptរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ស្មំថា variable int x = 10:

7.3 Pointer Declarationរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Syntax:

dataType *pointerName;
int *ptr;       /* pointer to int */
double *dptr;   /* pointer to double */
char *cptr;     /* pointer to char (C-string) */
void *vptr;     /* generic pointer */

7.4 Address Operator (&) and Dereference (*)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

OperatorNameDescriptionExample
&Address-ofទទួល address របស់ variableptr = &num;
*Declarationប្រកាស pointer variableint *ptr;
*Dereferenceaccess value នៅ addressvalue = *ptr;
#include <stdio.h>

int main() {
    int num = 42;
    int *ptr;

    ptr = #    /* ptr holds address of num */

    printf("Value of num      : %d\n", num);
    printf("Address of num    : %p\n", (void*)&num);
    printf("Value of ptr (addr): %p\n", (void*)ptr);
    printf("Value via ptr (*ptr): %d\n", *ptr);

    /* Modify via pointer */
    *ptr = 100;
    printf("\nAfter *ptr = 100:\n");
    printf("num  = %d\n", num);    /* 100 */
    printf("*ptr = %d\n", *ptr);   /* 100 */

    return 0;
}
/* Sample Output:
   Value of num       : 42
   Address of num     : 0x7ffd1234
   Value of ptr (addr): 0x7ffd1234
   Value via ptr (*ptr): 42
   After *ptr = 100:
   num  = 100
   *ptr = 100 */

7.5 NULL Pointerរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

NULL pointer ជា pointer ដែលមិនកំណត់ទៅ address ណាទេ ។ ប្រើ NULL ពី <stdio.h><stddef.h>:

#include <stdio.h>

int main() {
    int *ptr = NULL;  /* NULL pointer - safe initialization */

    /* Always check before dereferencing */
    if (ptr != NULL) {
        printf("Value: %d\n", *ptr);
    } else {
        printf("Pointer is NULL - cannot dereference!\n");
    }

    /* Never do this - undefined behavior! */
    /* *ptr = 10; */   /* CRASH! */

    return 0;
}

7.6 Pointer to Pointer (**)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Pointer to pointer រក្សាទុក address របស់ pointer មួយទៀត:

#include <stdio.h>

int main() {
    int num = 42;
    int *ptr = #     /* pointer to int */
    int **pptr = &ptr;   /* pointer to pointer to int */

    printf("num    = %d\n", num);
    printf("*ptr   = %d\n", *ptr);
    printf("**pptr = %d\n", **pptr);

    /* Modify via double pointer */
    **pptr = 999;
    printf("\nAfter **pptr = 999:\n");
    printf("num = %d\n", num);   /* 999 */

    return 0;
}

7.7 Pointer Arithmeticរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Pointer arithmetic អនុញ្ញាតឱ្យ move pointer ទៅ elements ជាប់គ្នា:

#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int *ptr = arr;   /* ptr points to arr[0] */
    int i;

    printf("Array via pointer arithmetic:\n");
    for (i = 0; i < 5; i++) {
        printf("ptr+%d: address=%p, value=%d\n",
               i, (void*)(ptr+i), *(ptr+i));
    }

    /* ptr++ moves to next element (not just +1 byte, but +sizeof(int)) */
    printf("\nUsing ptr++:\n");
    ptr = arr;
    for (i = 0; i < 5; i++) {
        printf("%d ", *ptr);
        ptr++;
    }
    printf("\n");

    /* Difference between pointers */
    int *start = arr;
    int *end = &arr[4];
    printf("\nElements between start and end: %ld\n", end - start);  /* 4 */

    return 0;
}

7.8 Pointers and Arraysរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង C, Array name ជា constant pointer ទៅ first element:

#include <stdio.h>

/* Array as function parameter (actually pointer) */
void displayArray(int *arr, int size) {
    int i;
    for (i = 0; i < size; i++) {
        printf("%d ", arr[i]);   /* same as *(arr+i) */
    }
    printf("\n");
}

void doubleAll(int *arr, int size) {
    int i;
    for (i = 0; i < size; i++) {
        *(arr + i) *= 2;   /* modifies original array */
    }
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = 5;

    printf("Original: ");
    displayArray(numbers, size);   /* numbers = &numbers[0] */

    doubleAll(numbers, size);
    printf("Doubled : ");
    displayArray(numbers, size);

    /* Equivalent notations */
    int arr[] = {10, 20, 30};
    int *p = arr;
    printf("\narr[1]    = %d\n", arr[1]);    /* 20 */
    printf("*(arr+1)  = %d\n", *(arr+1));  /* 20 */
    printf("p[1]      = %d\n", p[1]);      /* 20 */
    printf("*(p+1)    = %d\n", *(p+1));    /* 20 */

    return 0;
}

7.9 Pointers and Stringsរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

#include <stdio.h>
#include <string.h>

int main() {
    /* String literal (read-only) */
    char *str1 = "Hello";        /* pointer to string literal */
    /* str1[0] = 'h'; */         /* UNDEFINED - read-only! */

    /* Char array (modifiable) */
    char str2[] = "Hello";       /* modifiable copy */
    str2[0] = 'h';               /* OK */
    printf("str2 = %s\n", str2);  /* hello */

    /* Pointer to traverse string */
    char name[] = "Sokha";
    char *p = name;
    printf("Characters: ");
    while (*p != '\0') {
        printf("%c ", *p);
        p++;
    }
    printf("\n");

    /* String length using pointer */
    char s[] = "Programming";
    char *q = s;
    int len = 0;
    while (*q++) len++;
    printf("Length = %d\n", len);

    return 0;
}

7.10 Dynamic Memory Allocationរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Dynamic allocation ប្រើ malloc(), calloc(), realloc(), free() ពី <stdlib.h>:

FunctionDescription
malloc(size)Allocate size bytes, uninitialized
calloc(n, size)Allocate n×size bytes, initialized to 0
realloc(ptr, size)Resize allocated memory
free(ptr)Release allocated memory
#include <stdio.h>
#include <stdlib.h>

int main() {
    int n, i;

    printf("Enter number of students: ");
    scanf("%d", &n);

    /* Dynamic allocation */
    int *scores = (int*)malloc(n * sizeof(int));

    if (scores == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }

    /* Input */
    printf("Enter %d scores:\n", n);
    for (i = 0; i < n; i++) {
        printf("Score[%d]: ", i+1);
        scanf("%d", &scores[i]);
    }

    /* Process */
    int sum = 0;
    for (i = 0; i < n; i++) sum += scores[i];
    printf("Average = %.2f\n", (double)sum / n);

    /* Free memory - MUST! */
    free(scores);
    scores = NULL;   /* good practice */

    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int n = 5;

    /* calloc - allocate + initialize to 0 */
    int *arr = (int*)calloc(n, sizeof(int));
    printf("calloc initialized: ");
    int i;
    for (i = 0; i < n; i++) printf("%d ", arr[i]);  /* 0 0 0 0 0 */
    printf("\n");

    /* Fill array */
    for (i = 0; i < n; i++) arr[i] = (i+1) * 10;

    /* realloc - resize to 8 elements */
    arr = (int*)realloc(arr, 8 * sizeof(int));
    for (i = 5; i < 8; i++) arr[i] = 0;

    printf("After realloc(8): ");
    for (i = 0; i < 8; i++) printf("%d ", arr[i]);
    printf("\n");

    free(arr);
    arr = NULL;

    /* Dynamic string */
    char *name = (char*)malloc(50 * sizeof(char));
    strcpy(name, "Sokha Chan");
    printf("Name: %s\n", name);
    free(name);

    return 0;
}
Memory Management Rules (ច្បាប់ក្នុង C):
  • រាល់ malloc/calloc/realloc ត្រូវមាន free() ផ្គូ
  • Always check return value ≠ NULL មុន use
  • កុំ free() pointer ដែលគ្មាន allocated ឬ freed ហើយ
  • Set pointer = NULL ក្រោយ free()
  • Memory leak = allocate ប៉ុន្តែ forget free → program ប្រើ RAM ច្រើនខ្លាំង

7.11 Function Pointersរៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Function pointers រក្សាទុក address នៃ functions អាចប្រើ call functions dynamically:

#include <stdio.h>

double add(double a, double b) { return a + b; }
double sub(double a, double b) { return a - b; }
double mul(double a, double b) { return a * b; }
double dvd(double a, double b) {
    if (b == 0) { printf("Error!\n"); return 0; }
    return a / b;
}

/* Function pointer type */
typedef double (*Operation)(double, double);

double calculate(double a, double b, Operation op) {
    return op(a, b);
}

int main() {
    /* Declare function pointer */
    double (*fp)(double, double);

    fp = add;
    printf("10 + 5 = %.2f\n", fp(10, 5));

    fp = sub;
    printf("10 - 5 = %.2f\n", fp(10, 5));

    /* Array of function pointers */
    Operation ops[4] = {add, sub, mul, dvd};
    char *opNames[] = {"Add", "Sub", "Mul", "Div"};
    int i;

    printf("\nAll operations on 10, 5:\n");
    for (i = 0; i < 4; i++) {
        printf("%-4s: %.2f\n", opNames[i], calculate(10, 5, ops[i]));
    }

    return 0;
}

7.12 Pointers to Structs (Preview)រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Struct ជា user-defined type ដែលប្រមូល data fields ផ្សេងៗ:

#include <stdio.h>
#include <string.h>

/* Define struct */
struct Student {
    char name[50];
    int age;
    float gpa;
};

void displayStudent(struct Student *s) {
    printf("Name: %s, Age: %d, GPA: %.2f\n",
           s->name, s->age, s->gpa);
    /* s->name is same as (*s).name */
}

int main() {
    struct Student s1;
    struct Student *ptr = &s1;

    /* Access via pointer - use -> operator */
    strcpy(ptr->name, "Sokha");
    ptr->age = 20;
    ptr->gpa = 3.85;

    displayStudent(ptr);

    /* Array of structs */
    struct Student students[3];
    strcpy(students[0].name, "Dara");
    students[0].age = 21;
    students[0].gpa = 3.70;

    struct Student *p = students;
    printf("First: %s\n", p->name);

    return 0;
}

ឧទាហរណ៍ពេញលេញ - Dynamic Array of Students:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[50];
    int age;
    float score;
} Student;

void inputStudent(Student *s, int index) {
    printf("\nStudent %d:\n", index+1);
    printf("Name : "); scanf("%s", s->name);
    printf("Age  : "); scanf("%d", &s->age);
    printf("Score: "); scanf("%f", &s->score);
}

void displayAll(Student *arr, int n) {
    int i;
    printf("\n%-15s %-5s %-6s\n", "Name", "Age", "Score");
    printf("------------------------------\n");
    for (i = 0; i < n; i++) {
        printf("%-15s %-5d %-6.2f\n",
               arr[i].name, arr[i].age, arr[i].score);
    }
}

float average(Student *arr, int n) {
    float sum = 0;
    int i;
    for (i = 0; i < n; i++) sum += arr[i].score;
    return sum / n;
}

int main() {
    int n;
    printf("Number of students: ");
    scanf("%d", &n);

    /* Dynamic allocation */
    Student *students = (Student*)malloc(n * sizeof(Student));
    if (!students) { printf("Memory error!\n"); return 1; }

    int i;
    for (i = 0; i < n; i++) inputStudent(&students[i], i);

    displayAll(students, n);
    printf("\nClass average: %.2f\n", average(students, n));

    free(students);
    students = NULL;

    return 0;
}

លំហាត់ប្រចាំមេរៀនទី 7 - Pointers & Dynamic Memory (malloc, free)

  1. ប្រកាស Pointer (int *p) ចង្អុលទៅកាន់អថេរ int មួយ។ បង្ហាញតម្លៃនៃអថេរ និងអាសយដ្ឋាន (Memory Address) របស់វា។
  2. សរសេរកម្មវិធីផ្លាស់ប្តូរតម្លៃនៃអថេរដើមដោយប្រយោល (Indirectly) តាមរយៈការប្រើប្រាស់ Pointer។
  3. សរសេរកម្មវិធីបង្ហាញពី Pointer Arithmetic ដោយរុញ Pointer ទៅមុខដើម្បីអានធាតុបន្តបន្ទាប់នៅក្នុង Array (*(p+i))។
  4. បង្កើត Function swap(int *a, int *b) ដើម្បីផ្លាស់ប្តូរតម្លៃអថេរពីរ ដោយប្រើយន្តការឆ្លងកាត់អាសយដ្ឋាន (Call by Reference)។
  5. សរសេរកម្មវិធីរកប្រវែងនៃ String មួយ ដោយប្រើតែ Pointer ជំនួសឱ្យការប្រើ Index នៃ Array (អត់ប្រើ strlen)។
  6. សរសេរកម្មវិធីប្រើ malloc() ដើម្បីបម្រុងទុកអង្គចងចាំសម្រាប់ Array ដែលមាន n ធាតុ រួចបញ្ចូលទិន្នន័យ។
  7. សរសេរកម្មវិធីរកផលបូកនៃធាតុក្នុង Array ដែលត្រូវបានបម្រុងទុកដោយប្រើ malloc()
  8. សរសេរកម្មវិធីប្រើ calloc() ដើម្បីបម្រុងទុកអង្គចងចាំ និងកំណត់តម្លៃដើមនៃគ្រប់ប្លុកទៅជា 0 ដោយស្វ័យប្រវត្តិ។
  9. សរសេរកម្មវិធីប្រើ realloc() ដើម្បីពង្រីកទំហំ Dynamic Array បន្ថែមធាតុថ្មីដោយមិនបាត់បង់ទិន្នន័យចាស់។
  10. សរសេរកម្មវិធីដោយមានបញ្ចូលអនុគមន៍ free() នៅចុងបញ្ចប់ ដើម្បីលុប (Deallocate) អង្គចងចាំវិញ បន្ទាប់ពីប្រើប្រាស់ Dynamic Memory រួចរាល់ ដើម្បីជៀសវាង Memory Leak។