0% found this document useful (0 votes)
11 views12 pages

CSC 205

Uploaded by

tonyimoh9
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views12 pages

CSC 205

Uploaded by

tonyimoh9
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Introduction to Debugging and Testing

Debugging is the process of identifying and removing errors from computer software or
hardware. It is essential for ensuring that programs run correctly and efficiently.
Testing involves executing a program with the intent of finding errors. It is crucial for verifying
that the software meets the requirements and is free of bugs.
Importance of debugging and testing
• They enhance software reliability and performance
• They prevent future issues
• They maintain code quality
Types of Errors
Errors in programming can be categorized into three main types:
• Syntax errors: Syntax errors are mistakes in the code structure, such as missing semicolons
or incorrect indentation, and are detected by the compiler or interpreter
• Runtime errors: Runtime errors occur during program execution, such as division by zero or
null pointer dereferences, and can cause the program to crash or produce incorrect results
• Logical errors: Logical errors are mistakes in the program's logic that produce incorrect
results. The program runs without crashing, but the output is not as expected.
Debugging Techniques
Various debugging techniques can be employed to identify and fix errors in the code.
• Using print statements is a simple but effective method: where print statements are inserted in
the code to output variable values and program flow.
• Debugging tools, such as IDEs with built-in debuggers (like Visual Studio, Code Blocks, and
Eclipse), provide more advanced debugging capabilities.
• Setting breakpoints allows the program to pause execution at specific points, enabling step-by-
step inspection of variable values and program flow.
• Analyzing error messages and stack traces helps identify the source of the problem by tracing
the sequence of function calls that led to the error.
Common Debugging Strategies
Effective debugging strategies involve;
• Understanding the problem: entails reproducing the error and gathering information
about the conditions under which it occurs.
• Reproducing the error: involves creating a test case that consistently triggers the error.
• Isolating the problem: Isolating the problem can be done using a binary search method
to narrow down the code section causing the error, or by commenting out code sections
and re-enabling them gradually to pinpoint the issue.
• Fixing the bug: once the problem is isolated, the code can be modified to correct the
error.
• Testing the fix: running tests ensures that the error is resolved and that the fix works
under various conditions.
Types of Testing
Testing is an essential aspect of software development, with various types including
• Unit testing: involves testing individual components or functions of the code.
• Integration testing: checks how different components work together
• System testing: verifies the complete system to ensure it meets the requirements.
Testing can be performed manually or automatically.
• Manual testing is done by human testers and is suitable for exploratory testing. In manual
software testing, a tester tests the software by following a set of predefined test cases. In this
testing, testers make test cases for the codes, test the software, and give the final report about
that software. Manual testing is time-consuming because it is done by humans, and there is
a chance of human errors.
• Automated testing uses scripts and tools to automate test execution, making it suitable for
repetitive tests. It involves using special software for tasks that people usually do when
testing.
Comparison between Unit Testing, Integration Testing and System Testing
Aspect Unit Testing Integration Testing System Testing
Definition Testing individual Testing the interactions Testing the entire system
components or functions between integrated as a whole to ensure it
in isolation components meets requirements
Scope Narrow scope: single Medium scope: combined Broad scope: the
function or module units or modules of the complete application or
application system
Purpose Ensure that each Ensure that combined Ensure that the entire
component works components function system works as
correctly on its own together correctly intended
Performed by Developers Developers or testers Testers
Test Cases Focus on individual Focus on interaction Focus on end-to-end
functions and methods between integrated units scenarios and user
journeys
Complexity Low complexity Medium complexity High complexity
Example Testing a function to Testing how the grade Testing the whole
calculate a single calculation and student grading system,
assignment grade (e.g., 85 record modules work including inputting
-> B) together (e.g., combining scores, calculating final
assignment scores for a grades, and generating
final grade) report cards
Unit Tests
Unit tests check a small part of the code, such as a single function or method, and are beneficial
for detecting issues early in the development process, facilitating code changes and refactoring,
and improving code reliability and quality. A typical unit test follows a structure:

Setup Execution Verification Teardown


•preparing the •running the code •checking the output •cleaning up
environment and being tested against expected after the test
inputs results

Best Practices in Debugging and Testing


Following best practices in debugging and testing enhances the efficiency and effectiveness of
these processes.
• Keeping tests small and focused ensures that each test checks only one aspect of the
code, making it easier to identify the source of errors.
• Writing clear and maintainable tests with descriptive names and comments helps in
understanding and maintaining the tests.
• Regularly running tests allows developers to catch errors early, and using continuous
integration tools to automate test execution ensures that tests are run consistently.
• Continuous integration and automated testing are key practices for maintaining code
quality and reliability in a collaborative development environment.
Common Tools for Debugging and Testing
Various tools are available to assist in debugging and testing. IDEs like Visual Studio,
PyCharm, and Eclipse come with built-in debugging tools that provide features like
breakpoints, step-by-step execution, and variable inspection.
Introduction to Strings in C++
What are Strings?
Strings are a fundamental data type used to represent sequences of characters. In C++, strings
can be managed in two main ways: using C-style strings and C++ string objects. C-style strings
are essentially arrays of characters terminated by a null character ('\0') (ASCII value of null
character is 0), while C++ provides the std::string class, which offers more functionality and
ease of use.
C-strings vs. C++ Strings
C-strings are basic character arrays where each character is stored in a contiguous memory
location. For example, char str[] = "Hello"; initializes a C-string with the characters 'H', 'e', 'l',
'l', 'o', followed by the null terminator. Although C-strings are simple, they require manual
handling for memory and operations such as length calculation.
C++ strings, represented by the std::string class, provide a more user-friendly interface. They
automatically manage memory and offer numerous methods for string manipulation, such as
concatenation, comparison, and substring extraction. For example, std::string str = "Hello";
initializes a string object with the same content as the C-string example but with additional
functionality.
Input and Output of Strings
For input and output operations, the std::cin and std::cout streams are commonly used. Input
can be read into a std::string using std::cin >> str;, which reads until the first whitespace
character. For output, std::cout << str; prints the string to the console.
String Class in C++
What is the std::string Class?
The std::string class is part of the C++ Standard Library and is designed to simplify string
handling. It abstracts away the complexity of manual memory management and provides a rich
set of member functions for common string operations. Using std::string, developers can easily
perform operations such as concatenation, comparison, and length calculation without dealing
with raw character arrays.
Basic Operations with Strings
• Length: To find the length of a string, use the length() method, which returns the
number of characters in the string. For instance, std::string str = "Hello"; std::cout <<
str.length(); prints 5, indicating that the string contains five characters.
• Concatenation: You can concatenate strings using the + operator. For example,
std::string str1 = "Hello, "; std::string str2 = "World!"; std::string result = str1 + str2;
produces "Hello, World!".
• Comparison: Strings can be compared using relational operators like ==, <, and >.
For example, std::string str1 = "Hello"; std::string str2 = "World"; std::cout << (str1
== str2); evaluates to 0 (false) because the strings are not equal.
Accessing Characters in a String
Characters in a std::string can be accessed using the index operator ([]) or the at() method. For
example, std::cout << str[0]; prints the first character of the string, and std::cout << str.at(0);
provides the same result but with bounds checking.
String Manipulation Functions
Adding and Removing Characters
• Insert: To insert characters into a string, use the insert() method. For example,
str.insert(5, ", World"); inserts the substring ", World" at position 5, resulting in
"Hello, World!".
• Delete: Characters can be removed using the erase() method. For example, str.erase(5,
7); removes 7 characters starting from position 5, changing "Hello, World!" to
"Hello!".
Extracting Substrings
The substr() method extracts a part of the string based on the starting position and length. For
instance, std::string sub = str.substr(7, 5); extracts "World" from the string "Hello, World!",
starting from position 7 and spanning 5 characters.
Finding and Replacing Substrings
• Find: The find() method locates the first occurrence of a substring. For example,
std::size_t pos = str.find("World"); finds "World" starting at position 7. If the substring
is not found, find() returns std::string::npos.
• Replace: The replace() method substitutes a part of the string with another substring.
For example, str.replace(7, 5, "there"); changes "Hello, World!" to "Hello, there!".
String Iteration and Traversal
Looping Through Strings
Strings can be traversed using loops to process each character individually. Using a for loop,
you can iterate through the string:
std::string str = "Hello";
for (int i = 0; i < str.length(); i++) {
std::cout << str[i] << " ";
}
This will output each character of the string with a space in between: H e l l o.
Similarly, a while loop can be used to achieve the same result:
int i = 0;
while (i < str.length()) {
std::cout << str[i] << " ";
i++;
}
Output: H e l l o
Using Iterators
Iterators provide a way to traverse strings in a more generic manner. For example:
std::string str = "Hello";
for (auto it = str.begin(); it != str.end(); ++it) {
std::cout << *it << " ";
}
Output: H e l l o
String Conversion Functions
Converting Between Strings and Other Data Types
• String to int: Convert a string to an integer using std::stoi(). For example, int num =
std::stoi("123"); converts the string "123" to the integer 123.
• String to float: Convert a string to a float using std::stof(). For instance, float num =
std::stof("123.45"); converts "123.45" to 123.45.
• Int to string: Use std::to_string() to convert an integer to a string. For example,
std::string str = std::to_string(123); results in the string "123".
Case Conversion
Converting a string to uppercase or lowercase can be done using a loop with the toupper() and
tolower() functions, respectively. For example, to convert "Hello" to uppercase:
std::string str = "Hello";
for (int i = 0; i < str.length(); i++) {
str[i] = toupper(str[i]);
}
std::cout << str;
Output: HELLO
Similarly, converting to lowercase:
std::string str = "Hello";
for (int i = 0; i < str.length(); i++) {
str[i] = tolower(str[i]);
}
std::cout << str;
Output: hello
String Streams
What is a String Stream?
std::stringstream is a class in the C++ Standard Library that allows strings to be used as input
and output streams. This is particularly useful for converting between strings and other data
types or for manipulating strings in a way similar to stream operations.
Using String Streams
Converting a number to a string:
std::stringstream ss;
int num = 123;
ss << num;
std::string str = ss.str();
std::cout << str;
Output: 123
Converting a string to a number:
std::string str = "123";
std::stringstream ss(str);
int num;
ss >> num;
std::cout << num + 1;
Output: 124
Advanced String Operations
Special Characters and Escape Sequences
Strings can include special characters and escape sequences. For example, \n represents a new
line, \t is a tab, and \\ is a backslash. These can be used to format output. For instance:
std::cout << "Hello\nWorld\t!";
Output:
Hello
World !
Comparing Strings Lexicographically
Strings can be compared lexicographically using relational operators. For example:
std::string str1 = "Apple";
std::string str2 = "Banana";
if (str1 < str2) {
std::cout << str1 << " comes before " << str2;
}
Output: Apple comes before Banana
Splitting and Joining Strings
Splitting strings is commonly done using delimiters. For instance:
std::string data = "apple,orange,banana";
std::stringstream ss(data);
std::string token;
while (std::getline(ss, token, ',')) {
std::cout << token << std::endl;
}
Output:
apple
orange
banana
Joining Strings
Joining strings often involves concatenating them with a separator. For example:
using namespace std;
// A vector of strings containing different fruits
vector<string> fruits = {"apple", "orange", "banana"};
string result;// An empty string to store the result of concatenation
for (const auto& fruit : fruits) { // Loop through each fruit in the vector
if (!result.empty()) { // If result is not empty, add a separator (", ")
result += ", ";
}
result += fruit; // Add the current fruit to the result string
}
cout << result; // Print the final concatenated string
Output: apple, orange, banana

Common Pitfalls and Best Practices


Common Errors
• Out-of-Range Indexing: Accessing characters outside the valid range can cause
undefined behavior. Always ensure indices are within the string’s bounds.
• Null Terminator in C-strings: Ensure that C-strings are properly terminated with a
'\0' to avoid incorrect behavior.
Best Practices
• Prefer using std::string over C-strings for ease and safety. std::string automatically
handles memory management and reduces the risk of common errors.
• Use str.at(i) instead of str[i] for safer access. str.at(i) throws an std::out_of_range
exception if the index is out of bounds.
Memory Management Considerations
• Be cautious with large strings in performance-critical applications. Excessive copying
or modifications can lead to inefficiencies.
• Where possible, use references or pointers to avoid unnecessary copying of strings.
Code Samples
Hello World

Declaring variables
int float

double char

bool string

if statement syntax
If…else statement syntax

Single Line Comment (//)

Multi-line Comment (/* */)


Using comments for Debugging

>>>

break and continue statement

You might also like