Manipulating Array Elements Inside a For Loop in C++


Suppose you have an array nums and your task is to increment every number in that array by one.

The first idea that might come to your mind is to write a for loop like this:

vector<int> nums = {1, 2, 3};

// Increment items:
for (int num : nums) {
  num++;
}

// Print the array after:
for (int num : nums) {
  cout << num << " ";
}

but when you run this code, you'll be surprised to see that the output is:

1 2 3

No element in nums changed its value. How is this possible since we clearly do num++ for every num in nums?


Let's talk about copies:

Take a look at this code:

int number = 100;

int number_copy = number;

number_copy++;

cout << number_copy << endl; // Output: 101
cout << number << endl; // Output: 100

Although we wrote int number_copy = number;, this doesn't mean that number and number_copy are one and the same.

number_copy is a completely different entitity (stored at a different memory address) than number.

What we did is initialize this new number_copy entity with the value of number. That's why we say the number_copy is a copy of number.

And so number_copy++ will only increment number_copy and won't have any effect on number.


The loop variable is just a copy:

This is what also happens with a for loop.

Whenever you write a for loop, the loop variable (in our case num) is just a copy of the current item of the array, not the item itself.

This code

vector<int> nums = {1, 2, 3};

for (int num : nums) {
  num++;
}

works exactly like this code:

vector<int> nums = {1, 2, 3};

int num = nums[0];
num++;

num = nums[1];
num++;

num = nums[2];
num++;

Notice that only the variable num is being manipulated, which has nothing to do with the actual entries of the array nums.

You'll see this better if we also print the value of num on each iteration.

vector<int> nums = {1, 2, 3};

for (int num : nums) {
  num++;
  cout << num << endl;
}

// Print the array after:
for (int num : nums) {
  cout << num << " ";
}

The output of this code is:

2
3
4
1 2 3

Looping over the indices:

In order to manipulate the entries of some array we have to loop over the items' indices:

vector<int> nums = {1, 2, 3};

for (int index = 0; index < nums.size(); index++) {
  nums[index]++;
}

This code works exactly like this one:

vector<int> nums = {1, 2, 3};

int index = 0;
nums[index]++;

index++;
nums[index]++;

index++;
nums[index]++;

In this way we directly manipulate the actual entries of the list (nums[0], nums[1], etc.)

Assignment:

Fix our code such that it correctly increments (adds one to) the even numbers of nums and decrements (subtracts one from) the odd ones.

Introduction

In this lesson, we will explore how to manipulate array elements inside a for loop in C++. This is a fundamental concept in programming that is essential for tasks such as data processing, algorithm implementation, and more. Understanding how to correctly modify array elements is crucial for writing efficient and bug-free code.

Understanding the Basics

When working with arrays in C++, it's important to understand that the loop variable in a range-based for loop is a copy of the array element, not a reference to it. This means that any modifications to the loop variable do not affect the original array. Let's illustrate this with a simple example:

vector<int> nums = {1, 2, 3};

for (int num : nums) {
  num++;
}

for (int num : nums) {
  cout << num << " ";
}

The output of this code is:

1 2 3

As you can see, the array elements remain unchanged because num is a copy of each element, not a reference to the original element.

Main Concepts

To modify the actual elements of the array, we need to use a traditional for loop that iterates over the indices of the array. This allows us to directly access and modify the elements. Here is how you can do it:

vector<int> nums = {1, 2, 3};

for (int index = 0; index < nums.size(); index++) {
  nums[index]++;
}

In this code, we use the index to access each element of the array and increment it by one. This directly modifies the elements of the array.

Examples and Use Cases

Let's look at a more complex example where we need to increment even numbers and decrement odd numbers in an array:

vector<int> nums = {1, 2, 3, 4, 5};

for (int index = 0; index < nums.size(); index++) {
  if (nums[index] % 2 == 0) {
    nums[index]++;
  } else {
    nums[index]--;
  }
}

for (int num : nums) {
  cout << num << " ";
}

The output of this code is:

0 3 2 5 4

In this example, we check if each element is even or odd and modify it accordingly.

Common Pitfalls and Best Practices

One common mistake is to use a range-based for loop when you need to modify the elements of an array. Always remember that the loop variable in a range-based for loop is a copy. To avoid this mistake, use a traditional for loop with indices when you need to modify the array elements.

Best practices include writing clear and maintainable code by using meaningful variable names and adding comments to explain the logic. Additionally, always test your code with different inputs to ensure it works correctly in all scenarios.

Advanced Techniques

For more advanced manipulation, you can use iterators or the std::transform function from the C++ Standard Library. Here is an example using std::transform:

#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

int main() {
  vector<int> nums = {1, 2, 3, 4, 5};

  transform(nums.begin(), nums.end(), nums.begin(), [](int num) {
    return (num % 2 == 0) ? num + 1 : num - 1;
  });

  for (int num : nums) {
    cout << num << " ";
  }

  return 0;
}

This code uses a lambda function to increment even numbers and decrement odd numbers in the array.

Code Implementation

Here is the complete code to solve the assignment:

#include <vector>
#include <iostream>

using namespace std;

int main() {
  vector<int> nums = {1, 2, 3, 4, 5};

  for (int index = 0; index < nums.size(); index++) {
    if (nums[index] % 2 == 0) {
      nums[index]++;
    } else {
      nums[index]--;
    }
  }

  for (int num : nums) {
    cout << num << " ";
  }

  return 0;
}

Debugging and Testing

When debugging code that manipulates arrays, it's helpful to print the array at various stages to understand how the elements are being modified. Use assertions to check if the array elements meet the expected conditions. Here is an example of a simple test case:

#include <cassert>

int main() {
  vector<int> nums = {1, 2, 3, 4, 5};

  for (int index = 0; index < nums.size(); index++) {
    if (nums[index] % 2 == 0) {
      nums[index]++;
    } else {
      nums[index]--;
    }
  }

  assert(nums[0] == 0);
  assert(nums[1] == 3);
  assert(nums[2] == 2);
  assert(nums[3] == 5);
  assert(nums[4] == 4);

  cout << "All tests passed!" << endl;

  return 0;
}

Thinking and Problem-Solving Tips

When approaching problems related to array manipulation, break down the problem into smaller steps. First, understand the requirements and constraints. Then, think about how you can use loops and conditionals to achieve the desired outcome. Practice with different problems to improve your problem-solving skills.

Conclusion

In this lesson, we covered how to manipulate array elements inside a for loop in C++. We discussed the importance of understanding that the loop variable in a range-based for loop is a copy and how to use a traditional for loop to modify array elements. We also explored advanced techniques and provided tips for debugging and testing. Mastering these concepts is essential for writing efficient and bug-free code.

Additional Resources

For further reading and practice problems, check out the following resources: