Bachelors Program in Computer Applications
Fundamentals of Programming (C/C++)
•
Bachelor
Computing and Programming Foundations
Introduction
Programming is the disciplined activity of expressing a solution to a problem in a form that a computer can execute. Although modern computers are powerful, they do not understand human intentions directly. They process encoded instructions, manipulate data according to precise rules, and communicate results through hardware and software interfaces. A programmer therefore needs more than knowledge of a programming language: the programmer must understand how computer systems are organized, how programs are translated and executed, and how large problems can be decomposed into manageable parts.
This chapter establishes the conceptual foundation for later study of C and C++. It introduces computer organization, software classifications, programming paradigms, computational thinking, source-code translation, and the historical importance of C and C++. The emphasis is on principles that remain useful even as particular tools and languages change.
Learning Objectives
After studying this chapter, you should be able to:
Describe the major components of a computer system and their relationships.
Distinguish system software, application software, utilities, firmware, and middleware.
Explain imperative, procedural, object-oriented, functional, and event-driven programming paradigms.
Apply decomposition, abstraction, pattern recognition, and algorithmic thinking to simple problems.
Explain the roles of source code, preprocessors, compilers, assemblers, linkers, loaders, and interpreters.
Describe the historical roles and continuing relevance of C and C++.
Identify professional, ethical, and practical considerations in developing reliable programs.
1. The Computer as a Programmable System
A computer is an electronic, programmable system that accepts input, stores and processes data, and produces output. The word programmable is central: the same physical machine can perform many different tasks when supplied with different instructions.
A useful abstract model consists of four activities:
Input: receiving data or commands from users, sensors, networks, or other systems.
Processing: applying instructions to data.
Storage: retaining instructions and data temporarily or permanently.
Output: presenting results to users or transmitting them to another system.
This model is not a complete description of modern computing, but it provides a reliable starting point. A web browser, payroll system, embedded controller, and scientific application all use these activities, although their hardware and software arrangements differ.
Data and information
Data consists of represented facts, symbols, measurements, or observations. Information is data interpreted in a meaningful context. For example, the sequence 37 is data; interpreted as a temperature in degrees Celsius, it becomes information. Programming involves representing data, transforming it, and preserving its meaning.
Computers represent all data internally as bits. A bit has one of two values, conventionally written 0 or 1. A group of eight bits is a byte. A byte can represent 2⁸ = 256 distinct patterns, although the interpretation may be a character, part of a number, or part of an instruction. The meaning of a bit pattern depends on its encoding and context.
2. Basic Computer Organization
Most general-purpose computers can be understood through the interaction of a processor, memory, storage, input/output devices, and communication pathways.
The central processing unit
The central processing unit (CPU) executes instructions. Its principal conceptual components are:
Arithmetic and logic unit (ALU): performs arithmetic operations and logical comparisons.
Control unit: coordinates instruction fetching, decoding, and execution.
Registers: very small, fast storage locations inside the processor.
Cache: high-speed memory that keeps frequently used instructions and data close to the CPU.
The CPU repeatedly performs an instruction cycle:
Fetch: obtain the next instruction from memory.
Decode: determine what operation the instruction specifies.
Execute: perform the operation.
Store or write back: preserve the result when required.
Modern processors use pipelines, multiple cores, speculative execution, and other techniques, so actual execution is more complex than this simplified cycle. Nevertheless, the cycle is valuable for understanding the relationship between programs and hardware.
Memory and storage
Main memory, commonly called random-access memory (RAM), holds programs and data currently in use. RAM is generally volatile: its contents are lost when power is removed. Secondary storage, such as solid-state drives and hard disks, retains data without continuous power but is usually slower than RAM.
A memory address identifies a location in memory. A variable in a high-level program may correspond, directly or indirectly, to one or more memory locations. The programming language hides much of this detail, but understanding it becomes important when studying pointers, arrays, performance, and resource management in C and C++.
Input, output, and buses
Input/output (I/O) devices allow a computer to communicate with its environment. Examples include keyboards, displays, cameras, printers, sensors, and network interfaces. A bus or communication interconnect carries data, addresses, and control signals among components. Contemporary systems may use sophisticated interconnects rather than one physical shared bus, but the logical idea remains useful.
Conceptual organization of a computer system
Figure: Conceptual organization of a computer system
Figure: A simplified conceptual organization of a computer system.
3. Software and Its Types
Hardware is the physical equipment of a computing system. Software is a collection of programs, data, and related instructions that directs hardware to perform tasks.
System software
System software manages computer resources and provides a platform for other programs. The operating system is the most important example. It manages processes, memory, files, devices, security, and user interaction. Device drivers allow the operating system to communicate with particular hardware devices.
Firmware is software stored in persistent memory and closely associated with hardware. It may initialize a device, control a network appliance, or operate an embedded system. Firmware lies between hardware and general-purpose software, and updating it can involve significant safety and security considerations.
Application software
Application software performs tasks for users or organizations. Word processors, accounting systems, games, geographic information systems, browsers, and medical-record systems are applications. An application may rely on operating-system services, libraries, databases, and network services.
Utilities, libraries, middleware, and services
Utilities perform focused maintenance or support tasks, such as backup, compression, diagnostics, and security scanning. A library is reusable code that provides functions or classes to other programs. Middleware connects otherwise separate applications or systems; examples include message brokers, database connectors, and web-service frameworks. Cloud services may provide computation, storage, identity, or specialized APIs over a network.
The boundaries between these categories are not absolute. A database engine, for example, may be viewed as system support software, middleware, or an application platform depending on its role.
4. Programming Paradigms
A programming paradigm is a style or model for organizing computation. Languages often support several paradigms, so paradigms should not be confused with language names.
Imperative and procedural programming
Imperative programming describes computation as a sequence of commands that change program state. Procedural programming organizes these commands into procedures or functions. A procedure may accept inputs, perform operations, and return a result or modify state.
C is primarily an imperative and procedural language. This approach is effective for operating systems, embedded software, numerical routines, and many performance-sensitive programs because it gives programmers substantial control over data representation and execution.
Object-oriented programming
Object-oriented programming organizes software around objects that combine state and operations. Important concepts include encapsulation, abstraction, inheritance, and polymorphism. C++ supports object-oriented programming while also retaining procedural and low-level capabilities.
Object orientation can improve organization in large systems, but it is not automatically superior. Poorly designed class hierarchies can create complexity. The appropriate design depends on the problem, constraints, team, and maintenance requirements.
Functional programming
Functional programming treats computation largely as the evaluation and composition of functions. It emphasizes immutability, expressions, and avoidance of unintended side effects. C and C++ are not primarily functional languages, but modern C++ supports lambdas, higher-order algorithms, and some functional techniques.
Event-driven and concurrent programming
Event-driven programs respond to events such as user actions, network messages, timers, or sensor readings. Concurrent programs manage multiple activities that may overlap in time. These approaches are essential in graphical applications, servers, mobile systems, and embedded controllers. They also introduce challenges involving synchronization, race conditions, deadlock, and nondeterministic behavior.
5. Computational Thinking and Problem Decomposition
Computational thinking is a set of reasoning practices for formulating problems so that people or computers can solve them effectively. It does not mean thinking like a machine; it means identifying structure, rules, and procedures.
Decomposition
Decomposition breaks a complex problem into smaller problems. A student-record system, for example, may be divided into modules for registration, assessment entry, grade calculation, reporting, and authentication. Each module can be designed and tested separately.
Good decomposition aims for high cohesion and low coupling. A cohesive component performs closely related tasks. Low coupling means that components depend on one another as little as practical. These properties improve testing, reuse, and maintenance.
Abstraction
Abstraction focuses attention on essential characteristics while hiding unnecessary detail. A function named calculateAverage expresses an operation without requiring every caller to know how values are stored or summed. Abstraction reduces cognitive load, but an abstraction must have a clear contract: its inputs, outputs, assumptions, and possible errors.
Pattern recognition and generalization
Pattern recognition identifies similarities among problems. If several tasks require searching a collection for a matching value, a general search procedure may be preferable to separate ad hoc solutions. Generalization turns a repeated pattern into a reusable algorithm or component.
Algorithms and representations
An algorithm is a finite, ordered, and unambiguous procedure for solving a problem. Before coding, a programmer should clarify the inputs, outputs, constraints, exceptional cases, and success criteria. A representation may be expressed as structured English, pseudocode, a flowchart, or a mathematical model.
For example, to determine the larger of two values:
Read values a and b.
If a is greater than b, report a.
Otherwise, report b.
This algorithm assumes that the values are comparable. If equal values require a special message, that requirement must be stated explicitly. Programming begins with such precise decisions, not with typing syntax immediately.
Correctness, efficiency, and maintainability
A program is correct when it satisfies its specified requirements for all relevant inputs. Efficiency concerns resources such as execution time and memory. Maintainability concerns how easily the program can be understood, tested, repaired, and extended. These goals can conflict. A highly optimized implementation may be difficult to maintain, while a very general design may use more resources. Professional programming balances these concerns according to context.
6. From Source Code to Execution
A high-level language allows programmers to express ideas using readable constructs such as variables, functions, conditions, and loops. Hardware, however, executes machine instructions. Translation tools bridge this gap.
Source code and object code
Source code is the human-readable program written in a language such as C or C++. Object code is a machine-oriented translation, often stored in an object file. Object code may still contain unresolved references to functions or data supplied by other files or libraries.
The exact stages vary by toolchain. Some compilers combine stages, and some systems use just-in-time compilation or virtual machines.
Preprocessor
The C and C++ preprocessing stage handles directives such as file inclusion and conditional compilation. A directive such as #include incorporates declarations from another file before ordinary compilation. Preprocessing is textual and does not provide the full semantic safety of language-level modules. Excessive or poorly controlled inclusion can increase build time and create name conflicts.
Compiler
A compiler translates source code into another form, commonly assembly language or machine-oriented object code. It performs lexical analysis, parsing, semantic checks, optimization, and code generation. A compiler can diagnose syntax errors, incompatible types, undeclared names, and some suspicious constructs.
Compilation is not proof that a program is correct. A program may compile successfully and still calculate the wrong result, mishandle input, leak resources, or contain security vulnerabilities.
Assembler
An assembler translates assembly language into machine code. Assembly provides a symbolic representation of processor instructions and registers. Most application developers do not write assembly routinely, but it remains relevant for embedded systems, operating-system components, performance analysis, and hardware-specific work.
Linker
A linker combines object files and libraries into a program image. It resolves references such as a function called in one source file but defined in another. Static linking copies required library code into the executable. Dynamic linking allows shared libraries to be loaded separately and reused by multiple programs. Linking errors often involve missing definitions, incompatible libraries, or duplicate symbols.
Loader
The loader is part of the operating-system environment that prepares an executable for execution. It places program segments into memory, performs required relocation, establishes the initial execution environment, and may load shared libraries. After loading, control is transferred to the program’s entry point, which eventually invokes the programmer’s main function in a conventional hosted C or C++ environment.
Interpreter
An interpreter executes a program through a runtime system rather than producing a complete native executable in one prior step. Some interpreters translate and execute one statement or construct at a time; others execute an intermediate representation. Interpreted execution can support portability, interactive development, and dynamic behavior, although performance depends on implementation.
The distinction between compiled and interpreted languages is not absolute. Many modern environments combine ahead-of-time compilation, bytecode, just-in-time compilation, caching, and interpretation. The important question is which translation and execution stages a particular toolchain performs.
Errors at different stages
Stage
Typical error
Example consequence
Preprocessing
Missing included file
Header cannot be found
Compilation
Syntax or type error
Invalid expression rejected
Linking
Unresolved symbol
Function declaration has no linked definition
Loading
Missing shared library
Program cannot start
Execution
Logic or runtime error
Incorrect output or invalid memory access
7. C and C++: Historical Roles and Continuing Relevance
C was developed in the early 1970s at Bell Labs and became strongly associated with the development and portability of the UNIX operating system. It provided structured programming constructs while permitting close control over memory and hardware representation. The language influenced operating systems, compilers, networking software, embedded systems, and many later languages.
C’s strengths include a relatively small core language, efficient compiled implementations, portability across processors, and direct access to memory through pointers. Its risks include manual resource management, weak protection against certain memory errors, undefined behavior in some situations, and the possibility of confusing low-level details with application requirements.
C++ began as an extension of C and was initially associated with “C with Classes.” It developed into a multi-paradigm language supporting procedural programming, object-oriented programming, generic programming, and modern abstractions. C++ is widely used in games, high-performance systems, finance, browsers, scientific computing, embedded systems, and large infrastructure projects.
Modern C++ encourages resource-management techniques such as RAII, standard containers, algorithms, smart pointers, and type-safe abstractions. Nevertheless, C++ remains complex because it supports low-level operations, multiple programming styles, extensive backward compatibility, and demanding performance requirements.
C and C++ are not simply older versions of one another. They share historical roots and some syntax, but their standard libraries, type systems, idioms, and design practices differ. Code that is valid in both languages may still have different recommended interpretations and maintenance implications.
8. A Worked Design Example: Library Fine Calculation
Consider a library that charges a daily fine for overdue items. The problem statement is:
Given the number of overdue days and a daily fine rate, calculate the total fine. If the item is returned on time, the fine is zero. Negative days are invalid input.
Decomposition
The problem can be divided into:
Validate the number of overdue days.
Determine whether the item is overdue.
Multiply overdue days by the daily rate.
Report the result or an input error.
The calculation is:
F = d × r, d > 0
where F is the total fine in currency units, d is the number of overdue days, and r is the daily rate in currency units per day. The formula applies only when d is positive and the rate is defined. For d = 0, F = 0. Negative d is rejected rather than interpreted mathematically.
If d = 6 days and r = 2.50 currency units per day, then:
F = 6 × 2.50 = 15.00
A robust implementation must also decide how to represent currency, how to handle fractional rates, and how to report invalid input. In financial software, binary floating-point values can introduce representation issues; integer minor units, such as cents, or a suitable decimal type may be preferable.
Pseudocode
read overdueDays
read dailyRate
if overdueDays < 0 or dailyRate < 0
report invalid input
else if overdueDays = 0
report 0
else
fine ← overdueDays × dailyRate
report fine
This example illustrates that programming is not merely translating a formula. Requirements, validation, data representation, and communication of errors are equally important.
9. Case Study: An Illustrative Campus Attendance System
Background
A university wants to replace paper attendance registers with a small system used by instructors and administrative staff. The system must record attendance, produce reports, and protect student information.
Problem analysis
The initial request, “Create an attendance application,” is too vague to implement safely. Decomposition reveals several functions: authenticate users, identify a course and session, retrieve enrolled students, record attendance, validate changes, generate reports, and maintain an audit trail.
The system also has constraints. An instructor should edit only authorized courses. A student should not be able to alter attendance. Network failures should not silently discard records. Reports should distinguish absent, present, excused, and unrecorded states.
Approach and solution
A suitable design separates concerns:
A user-interface component collects actions.
An application layer applies attendance rules.
A data-access layer communicates with storage.
An authentication and authorization service controls access.
Reporting functions transform stored records into summaries.
A C or C++ implementation might use structures or classes to represent students, courses, sessions, and attendance records. Functions should have clear contracts, and input should be validated before it reaches storage. Tests should include empty classes, duplicate submissions, invalid course identifiers, network interruption, and unauthorized access.
Outcome
The design reduces the risk of a single large function containing interface, database, and policy logic. It also makes later changes—such as adding mobile access or new attendance statuses—more manageable. The example demonstrates why decomposition and abstraction are engineering practices rather than merely academic techniques.
Learning points
Requirements must be clarified before implementation.
Security and privacy are system requirements, not optional additions.
Modular design supports testing and maintenance.
Error handling must consider real operating conditions.
Correct output is not sufficient if authorization and data protection are inadequate.
10. Professional, Ethical, and Contemporary Considerations
Programming decisions can affect safety, privacy, employment, access to services, and public trust. Developers should collect only necessary data, restrict access, protect credentials, validate external input, and avoid exposing confidential information through logs or error messages.
Memory safety is especially important in C and C++. Buffer overflows, use-after-free errors, invalid pointer access, and data races can cause crashes or security vulnerabilities. Defensive programming, compiler warnings, sanitizers, static analysis, code review, automated testing, and safe library facilities reduce risk. No single tool guarantees security.
Contemporary development increasingly uses integrated development environments, automated builds, version control, continuous integration, package managers, and AI-assisted coding tools. AI-generated code can accelerate exploration, but it may contain incorrect assumptions, insecure practices, licensing concerns, or fabricated APIs. Developers remain responsible for reviewing, testing, documenting, and governing code.
Best practices for beginning programmers include:
define the problem and expected behavior before coding;
use meaningful names and small, cohesive functions;
compile with warnings enabled;
test normal, boundary, invalid, and unexpected inputs;
use version control and make small, explainable changes;
document assumptions and interfaces;
avoid premature optimization;
treat compiler success as one checkpoint, not evidence of complete correctness.
Chapter Summary
Computer systems combine processors, memory, storage, input/output devices, and software. The CPU fetches, decodes, and executes instructions, while operating systems and other system software manage resources and provide services to applications. Software may be classified as system software, application software, firmware, utilities, libraries, middleware, or services, although categories can overlap.
Programming paradigms provide different ways to organize computation. C emphasizes imperative and procedural programming with considerable control over hardware. C++ extends this foundation with object-oriented, generic, and other multi-paradigm techniques. Computational thinking involves decomposition, abstraction, pattern recognition, algorithm design, and careful choice of representations.
A native C or C++ program commonly passes through preprocessing, compilation, assembly, linking, loading, and execution. Interpreters and modern hybrid runtimes use different combinations of translation and execution. Each stage can produce distinct errors. Reliable professional programming requires more than syntactically valid code: it requires clear requirements, validation, testing, security, maintainability, and ethical responsibility.
Key Terms
Computer: A programmable electronic system that processes data according to instructions.
Bit: The smallest conventional unit of digital information, with a value of 0 or 1.
CPU: The processor that executes program instructions.
ALU: The processor component that performs arithmetic and logical operations.
Register: Small, fast storage within a processor.
RAM: Volatile main memory used for active programs and data.
Firmware: Persistent software closely associated with hardware.
Operating system: System software that manages resources and provides services.
Application software: Software designed to perform tasks for users or organizations.
Library: Reusable code made available to other programs.
Programming paradigm: A model or style for organizing computation.
Algorithm: A finite, ordered, and unambiguous procedure for solving a problem.
Abstraction: Representation that emphasizes essential features while hiding detail.
Source code: Human-readable program text written in a programming language.
Compiler: A translator that converts source code into another representation, often machine-oriented code.
Interpreter: A runtime system that executes program constructs through interpretation or related mechanisms.
Linker: A tool that combines object files and resolves external references.
Loader: Software that prepares an executable for execution in memory.
Procedural programming: Organization of computation around procedures or functions.
Object-oriented programming: Organization of software around objects that combine state and behavior.
Review Questions
Short Answer Questions
What are the four broad activities represented by the input–processing–storage–output model?
What is the difference between RAM and secondary storage?
Define source code and object code.
What is the role of a linker?
Name two benefits of problem decomposition.
Long Answer Questions
Explain the instruction cycle and discuss why it is a useful abstraction even for modern processors.
Compare system software, application software, firmware, utilities, libraries, and middleware.
Compare procedural, object-oriented, functional, and event-driven programming paradigms.
Describe the typical stages through which a C or C++ program passes before execution.
Discuss the historical importance, strengths, and risks of C and C++.
Analytical / Application Questions
Decompose a hospital appointment system into cohesive components and identify at least three security or privacy requirements.
Design an algorithm for calculating a student’s final result from several assessment scores. State assumptions, validation rules, inputs, outputs, and boundary cases.
A program compiles successfully but fails when started because a shared library cannot be found. Identify the likely stage of failure and explain how it differs from a compilation or linking error.
Multiple Choice Questions with Answers
Question 1
Which component primarily performs arithmetic and logical operations?
A. Control unit
B. Arithmetic and logic unit
C. Loader
D. Secondary storage
Correct Answer: B. Arithmetic and logic unit
Question 2
What is the main purpose of an operating system?
A. To replace all application software
B. To manage hardware resources and provide system services
C. To translate every program directly into source code
D. To store only permanent user documents
Correct Answer: B. To manage hardware resources and provide system services
Question 3
Which paradigm organizes computation mainly as changes to program state through commands?
A. Imperative programming
B. Declarative database design
C. Markup processing
D. Pure data storage
Correct Answer: A. Imperative programming
Question 4
Which tool resolves references among object files and libraries?
A. Interpreter
B. Preprocessor
C. Linker
D. Text editor
Correct Answer: C. Linker
Question 5
What normally happens during preprocessing in C or C++?
A. The CPU executes the program
B. Include and conditional-compilation directives are handled
C. The operating system loads shared libraries
D. User input is validated at runtime
Correct Answer: B. Include and conditional-compilation directives are handled
Question 6
Which statement best describes an interpreter?
A. It always produces a permanent native executable before any execution
B. It executes program constructs through a runtime translation mechanism
C. It manages physical memory independently of an operating system
D. It combines object files into one executable
Correct Answer: B. It executes program constructs through a runtime translation mechanism
Question 7
If an item is six days overdue and the daily fine is 2.50 currency units, what is the fine?
A. 8.50 currency units
B. 12.50 currency units
C. 15.00 currency units
D. 20.00 currency units
Correct Answer: C. 15.00 currency units
Question 8
Which computational-thinking practice breaks a large problem into smaller manageable problems?
A. Decomposition
B. Encryption
C. Compilation
D. Rendering
Correct Answer: A. Decomposition
Question 9
What was a major historical role of C?
A. It was designed exclusively for spreadsheet formatting
B. It supported operating-system and systems programming with relatively direct hardware control
C. It eliminated the need for compilers
D. It was created as a database query language
Correct Answer: B. It supported operating-system and systems programming with relatively direct hardware control
Question 10
Which statement about successful compilation is correct?
A. It proves that the program meets all requirements
B. It proves that the program contains no security vulnerabilities
C. It indicates that certain translation checks succeeded, but logic and runtime errors may remain
D. It means the linker and loader can never fail
Correct Answer: C. It indicates that certain translation checks succeeded, but logic and runtime errors may remain
Fundamentals of Programming (C/C++)
Chapter 1
of 15