C++ Fundamentals: A Comprehensive Guide to Core Concepts
Data Types and Output Operations
Data serves as the carrier of information, and the primary purpose of programming is to process data effectively. C++ supports multiple data categories including numeric values, characters, and strings. Numeric values such as 100, 18.52, 0, and 9 can be written directly. Characters must be enclosed in single quotes and represent individual symbols like 'A', 'Z', '0', or '+', while Chinese characters and full-width punctuation do not qualify as characters. Strings use double quotes to contain multiple symbols such as "Hello World" or "100".
The std::cout object enables output of various data types, and the stream insertion operator ().
#include <iostream>
using namespace std;
int main()
{
string userName;
cout << "Please enter your name: ";
cin >> userName;
cout << "Entered name: " << userName << endl;
int userAge;
cout << "Please enter your age: ";
cin >> userAge;
cout << "Entered age: " << userAge << endl;
double userWeight;
cout << "Please enter your weight (kg): ";
cin >> userWeight;
cout << "Entered weight: " << userWeight << endl;
char userGender;
cout << "Please enter gender (F-female, M-male): ";
cin >> userGender;
cout << "Entered gender: " << userGender << endl;
bool userAttractive;
cout << "Please rate attractiveness (1-attractive, 0-not attractive): ";
cin >> userAttractive;
cout << "Entered rating: " << userAttractive << endl;
}
Arithmetic operators include addition (+), subtraction (-), multiplication (*), division (/), and modulus (%). Integer division discards the fractional part, while floating-point division preserves decimal precision. Division by zero causes program termination for integers or produces infinity (inf) for floating-point numbers.
Increment and decrement operators (++ and --) modify variable values. The prefix form (++variable) increments before expression evaluation, while the postfix form (variable++) increments after evaluation.
Control Flow Statements
The if statement evaluates conditions and executes code blocks based on boolean results. The basic structure includes an optional else branch for alternative execution paths. Expression evaluation must use parentheses, and assignment (=) should not be confused with equality comparison (==).
#include <iostream>
using namespace std;
int main()
{
bool isAttractive;
cout << "Please rate attractiveness (1-attractive, 0-not attractive): ";
cin >> isAttractive;
if (isAttractive == true)
{
cout << "You are beautiful!" << endl;
cout << "Congratulations, advancing to the next round!" << endl;
}
else
{
cout << "Sorry, you did not pass!" << endl;
cout << "Recommended beauty salon..." << endl;
}
}
Nested if statements enable multi-level condition checking up to 127 levels. The compiler associates else clauses with the nearest preceding if statement. Braces define explicit pairing for else clauses when needed.
#include <iostream>
using namespace std;
int main()
{
char gender;
bool isAttractive;
int bodyType;
cout << "Enter gender (F-female, M-male): ";
cin >> gender;
if (gender == 'F')
{
cout << "Enter attractiveness (1-attractive, 0-not attractive): ";
cin >> isAttractive;
if (isAttractive == true)
{
cout << "Enter body type (1-hot, 2-curvy, 3-slim): ";
cin >> bodyType;
if (bodyType == 1)
{
cout << "Advancing successfully!" << endl;
}
else
{
if (bodyType == 2)
{
cout << "Pending!" << endl;
}
}
}
}
}
The conditional (ternary) operator provides a concise alternative to simple if statements: expression1 ? expression2 : expression3.
Loop Constructs
Loop statements enable repeated execution of code blocks. The while loop evaluates conditions before each iteration, executing the statement block while the condition remains true.
#include <iostream>
using namespace std;
int main()
{
int itemNumber = 1;
while (itemNumber <= 10)
{
cout << "This is item number " << itemNumber++ << endl;
}
}
The for loop provides structured iteration with initialization, condition checking, and increment/decrement in a single statement. The loop executes initialization once, then evaluates the condition before each iteration.
#include <iostream>
using namespace std;
int main()
{
for (int itemNumber = 1; itemNumber <= 10; itemNumber++)
{
cout << "This is item number " << itemNumber << endl;
}
}
Nested loops enable multi-dimensional iteration patterns such as printing multiplication tables.
#include <iostream>
using namespace std;
int main()
{
for (int row = 1; row <= 9; row++)
{
for (int column = 1; column <= row; column++)
{
cout << row << "*" << column << "=" << row * column << " ";
}
cout << endl;
}
}
The break keyword exits the current loop, while continue returns to the loop's beginning. The do-while loop executes its body at least once before condition evaluation.
Functions and Modular Programming
Functions enable code organization by encapsulating specific tasks, improving readability and maintainability. Function declaration specifies the return type, name, and parameter types, while definition includes the implementation.
#include <iostream>
using namespace std;
int maximumValue(int first, int second);
void displayMessage(string messageContent);
void printMultiplicationTable();
int main()
{
cout << "maximumValue(5,8) = " << maximumValue(5, 8) << endl;
displayMessage("Hello, beautiful!");
printMultiplicationTable();
}
int maximumValue(int first, int second)
{
if (first > second)
return first;
return second;
}
void displayMessage(string messageContent)
{
cout << messageContent << endl;
return;
}
void printMultiplicationTable()
{
for (int row = 1; row <= 9; row++)
{
for (int column = 1; column <= row; column++)
{
cout << row << "*" << column << "=" << row * column << " ";
}
cout << endl;
}
return;
}
Function calls pass agruments to parameters. Variable scope determines accessibility: global variables are accessible throughout the program, while local variables exist only within their defininng function or block.
Parameter passing occurs through pass-by-value, pass-by-address (pointers), or pass-by-reference. References provide cleaner syntax compared to pointers for modifying arguments.
#include <iostream>
using namespace std;
void updateValues(int *numberValue, string *textValue)
{
cout << "Dear " << *numberValue << ": " << *textValue << endl;
*numberValue = 8;
*textValue = "I have a small bird.";
}
void findExtremes(int a, int b, int c, int *maximum, int *minimum)
{
*maximum = a > b ? a : b;
*minimum = a < b ? a : b;
*maximum = *maximum > c ? *maximum : c;
*minimum = *minimum < c ? *minimum : c;
}
int main()
{
int identifier = 3;
string greetingMessage = "I am a cheerful bird.";
updateValues(&identifier, &greetingMessage);
cout << "Dear " << identifier << ": " << greetingMessage << endl;
int valueA = 180, valueB = 170, valueC = 175, resultMax, resultMin;
findExtremes(valueA, valueB, valueC, &resultMax, &resultMin);
cout << "Max = " << resultMax << ", Min = " << resultMin << endl;
}
Pointers and Memory Management
Pointers store memory addresses, enabling direct memory manipulation. The address-of operator (&) retrieves variable addresses, while the dereference operator (*) accesses the value at a stored address.
#include <iostream>
using namespace std;
void printAddress(string variableName, void *memoryAddress)
{
cout << variableName << "'s address is: " << memoryAddress << endl;
cout << variableName << "'s value is: " << *(char *)memoryAddress << endl;
}
int main()
{
int alpha = 89;
char beta = 'X';
cout << "alpha's address: " << &alpha << endl;
cout << "beta's address: " << &beta << endl;
printAddress("alpha", &alpha);
printAddress("beta", &beta);
}
Dynamic memory allocation uses new to request memory and delete to release it. Dynamic arrays require delete[] for proper cleanup.
#include <iostream>
using namespace std;
int main()
{
int *numericArray = new int[8];
for (int index = 0; index < 8; index++)
{
numericArray[index] = 100 + index;
cout << "array[" << index << "] = " << *(numericArray + index) << endl;
}
delete[] numericArray;
}
Pointer categories include const pointers (pointer cannot change address), pointer constants (pointed value cannot change), and constant pointer constants (neither can change).
#include <iostream>
using namespace std;
void processData(const int *numberValue, const string *textValue)
{
cout << "Dear " << *numberValue << ": " << *textValue << endl;
}
int main()
{
int alpha = 3, beta = 8;
const int *pointerA = α
alpha = 13;
cout << "alpha = " << alpha << ", *pointerA = " << *pointerA << endl;
pointerA = β
int *const pointerB = α
*pointerB = 13;
cout << "alpha = " << alpha << ", *pointerB = " << *pointerB << endl;
processData(&alpha, &beta);
}
Memory regions include the stack (local variables and function parameters), heap (dynamic allocation), data segment (global and static variables), and code segment (executable code and constants).
Null pointers (nullptr in C++11) indicate no valid address. Wild pointers contain arbitrary uninitialized values and should be avoided by initializing pointers to nullptr when no valid address is available.
Arrays and Strings
Arrays store sequences of elements of the same type. Array length must be specified using constant or variable expressions. Elements are accessed via zero-based indices.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int itemCodes[] = {3, 6, 1, 6, 7, 4, 3, 5, 6, 7, 8, 322, 2, 3, 9};
string names[3];
for (int index = 0; index < sizeof(itemCodes) / sizeof(int); index++)
{
cout << "codes[" << index << "] = " << itemCodes[index] << endl;
}
int copiedArray[sizeof(itemCodes) / sizeof(int)];
memcpy(copiedArray, itemCodes, sizeof(itemCodes));
for (int index = 0; index < sizeof(copiedArray) / sizeof(int); index++)
{
cout << "copiedArray[" << index << "] = " << copiedArray[index] << endl;
}
}
Array names decay to pointers in most contexts, enabling pointer arithmetic. The expression array[index] is equivalent to *(array + index).
#include <iostream>
using namespace std;
int main()
{
int dataSet[5] = {3, 6, 5, 8, 9};
cout << "dataSet[0] = " << dataSet[0] << endl;
cout << "dataSet[1] = " << dataSet[1] << endl;
int *dataPointer = dataSet;
cout << "*(pointer + 0) = " << *(dataPointer + 0) << endl;
cout << "*(pointer + 1) = " << *(dataPointer + 1) << endl;
}
C-style strings are character arrays terminated with null characters ('\0'). String functions include strcpy(), strncpy(), strlen(), strcat(), strncmp(), strchr(), and strstr().
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char messageBuffer[11];
memset(messageBuffer, 0, sizeof(messageBuffer));
strncpy(messageBuffer, "greetings", 3);
cout << "message = " << messageBuffer << endl;
cout << "message[0] = " << (int)messageBuffer[0] << endl;
cout << "message[1] = " << (int)messageBuffer[1] << endl;
cout << "message[2] = " << (int)messageBuffer[2] << endl;
}
Advanced Data Structures
Structures combine multiple data types into a single entity. Members are accessed using the dot operator (.) for variables or arrow operator (->) for pointers.
#include <iostream>
using namespace std;
#pragma pack(8)
struct ParticipantProfile
{
char fullName[21];
int age;
double weight;
char gender;
bool isAttractive;
};
int main()
{
ParticipantProfile profile{"Catherine", 26, 33.8, 'F', true};
cout << "sizeof(ParticipantProfile) = " << sizeof(ParticipantProfile) << endl;
memset(&profile, 0, sizeof(profile));
cout << "Name: " << profile.fullName << ", Age: " << profile.age
<< ", Weight: " << profile.weight << ", Gender: " << profile.gender
<< ", Attractive: " << profile.isAttractive << endl;
}
Unions store different data types in the same memory location, with size equal to the largest member. Enumerations create symbolic constants with integer values starting from zero by default.
#include <iostream>
using namespace std;
enum ColorOptions { RED = 0, YELLOW = 1, BLUE = 2, OTHER = 3 };
int main()
{
ColorOptions selectedColor = YELLOW;
cout << "RED = " << RED << ", YELLOW = " << YELLOW
<< ", BLUE = " << BLUE << ", OTHER = " << OTHER << endl;
switch (selectedColor)
{
case RED: cout << "Red.\n"; break;
case YELLOW: cout << "Yellow.\n"; break;
case BLUE: cout << "Blue.\n"; break;
default: cout << "Unknown.\n";
}
}
References and Advanced Functions
References serve as aliases for variables, declared using the ampersand (&) operator. References must be initialized and cannot be reassigned to refer to different variables.
#include <iostream>
using namespace std;
int main()
{
int originalValue = 3;
int &referenceValue = originalValue;
cout << "originalValue address: " << &originalValue
<< ", value: " << originalValue << endl;
cout << "referenceValue address: " << &referenceValue
<< ", value: " << referenceValue << endl;
referenceValue = 5;
cout << "originalValue address: " << &originalValue
<< ", value: " << originalValue << endl;
cout << "referenceValue address: " << &referenceValue
<< ", value: " << referenceValue << endl;
}
References passed as function parameters avoid pointer syntax while enabling modification of argument values. The compiler implements references as pointers with syntactic sugar.
#include <iostream>
using namespace std;
void modifyValues(int &numberValue, string &textValue)
{
numberValue = 8;
textValue = "I have a small bird.";
cout << "Dear " << numberValue << ": " << textValue << endl;
}
int main()
{
int identifier = 3;
string messageContent = "I am a cheerful bird.";
modifyValues(identifier, messageContent);
cout << "Dear " << identifier << ": " << messageContent << endl;
}
Default function parameters provide default values when arguments are omitted. Function overloading enables multiple functions with the same name but different parameter lists. Inline functions request the compiler to insert function body directly at call sites for performance optimization.
#include <iostream>
using namespace std;
inline void displayGreeting(const short identifier, const string messageContent)
{
cout << "Dear " << identifier << ": " << messageContent << endl;
}
void exchangeValues(int &firstValue, int &secondValue)
{
int temporary = firstValue;
firstValue = secondValue;
secondValue = temporary;
}
void exchangeValues(string &firstValue, string &secondValue)
{
string temporary = firstValue;
firstValue = secondValue;
secondValue = temporary;
}
void sendGreeting(int participantId, const string &name = "Default",
const string &message = "I like you.")
{
cout << "Dear " << name << " (" << participantId << "): " << message << endl;
}
int main()
{
displayGreeting(3, "I am a cheerful bird.");
int alpha = 3, beta = 5;
exchangeValues(alpha, beta);
cout << "alpha = " << alpha << ", beta = " << beta << endl;
string personOne = "Catherine", personTwo = "Jennifer";
exchangeValues(personOne, personTwo);
cout << "personOne = " << personOne << ", personTwo = " << personTwo << endl;
sendGreeting(3, "Jennifer", "I am a cheerful bird.");
sendGreeting(5);
}
Object-Oriented Basics
Classes encapsulate data and behavior into a single unit. Members marked as public are accessible from outside the class, while the class itself serves as a blueprint for creating objects.
#include <iostream>
using namespace std;
class BeautyParticipant
{
public:
string fullName;
int age;
void setDetails(string nameInput, int ageInput)
{
fullName = nameInput;
age = ageInput;
}
void introduce()
{
cout << "Name: " << fullName << ", Age: " << age << endl;
}
};
int main()
{
BeautyParticipant participant;
participant.setDetails("Catherine", 26);
participant.introduce();
}
This foundational understanding of C++ syntax, data structures, and programming concepts provides a solid basis for developing more sophisticated applications and exploring advanced features of the language.