C++ pointer gets overwritten in for loops - c++

Could someone explain why pointers gets overwritten when variables are declared inside a loop?
For example, given the following snippet, and the user inputs 1 and 2. I would expect that the pNums array contain 2 pointers to 2 integers holding the value 1 and 2 respectively.
But instead, the console prints out 2 and 2;
#include <iostream>
using namespace std;
//Input "1 2"
int main() {
int* pNums[2];
for(int i = 0; i < 2; i++){
int num;
cin >> num;
pNums[i] = (&num);
}
cout << (*pNums[0]) << endl;
cout << (*pNums[1]) << endl;
}
Why is this the case? And how do I get around it? What if, for example, we don't know how many numbers the user will put in, and instead of a for loop, we have a while loop? Until some conditions are met, we want to keep creating new pointers and store them into a pNums vector?

There is only one num, and you are overwriting that. (And then causing Undefined Behavior, but never mind that.)
There are two simple ways to avoid this mistake.
1) Store objects, not pointers:
int nums[2];
for(int i = 0; i < 2; i++){
cin >> nums[i];
}
2) Use dynamic allocation:
int* pNums[2];
for(int i = 0; i < 2; i++){
int *p=new int;
cin >> *p;
pNums[i] = p;
}

The pointers that you are storing in pNums are to two instances of the variable num in the for block. There is one instance of the variable in each for loop iteration and these variables live only until the end of their respective iteration of the for loop body is reached.
Therefore your pointers will be invalid when the for loop exits and so trying to dereference them with e.g. *pNums[0] causes undefined behavior.
Don't store pointer, store values:
#include <iostream>
using namespace std;
//Input "1 2"
int main() {
int pNums[2];
for(int i = 0; i < 2; i++){
int num;
cin >> num;
pNums[i] = num;
}
cout << pNums[0] << endl;
cout << pNums[1] << endl;
}
and if you need a variable number of entries in the array, use std::vector.

for(int i = 0; i < 2; i++){
int num; //< this is num. It lives here.
cin >> num;
pNums[i] = (&num); //< you have taken the address of num (twice!)
}
// here is when 'num' is destroyed (no longer in scope)
// so this is now pointing at something that doesn't exist.
cout << (*pNums[0]) << endl;

Related

Why does my void function don't return the right value? (Newbie to c++) [duplicate]

This question already has answers here:
String 'G' is not showing
(2 answers)
Closed 2 years ago.
As you can see below, my function doesn't return the right value in int main() but it does in the function itself. I'm a newbie to c++, can anyone explain to me why or what's the problem? Thanks!
#include <iostream>
using namespace std;
int a[100],n;
void citire(int n)
{
int a[100];
for(int i = 0 ; i < n ; i ++) { // the for loop
cin >> a[i]; // entering the numbers for each
}
cout << a[5] << endl; // returns the right number
}
int main()
{
cout << "n= "; cin >> n; // how many numbers should the vector have.
citire(n); // me calling the function
cout << a[5]; // returns 0
}
Variable shadowing, where variables in different scopes have the same name. int a[100] inside the function citire is allocated on the stack will not persist when it falls out of scope at the end of the function, it's a different array to the global int a[100].
You have two different variables, a local variable and a global variable, but as you have given both of them the same name, you don't see that difference. Let me show you in a clearer way what you have programmed:
#include <iostream>
using namespace std;
int global_a[100],n;
void citire(int n)
{
int local_a[100];
for(int i = 0 ; i < n ; i ++) { // the for loop
cin >> local_a[i]; // entering the numbers for each
}
cout << local_a[5] << endl; // returns the right number
}
int main()
{
cout << "n= "; cin >> n; // how many numbers should the vector have.
citire(n); // me calling the function
cout << global_a[5]; // returns 0
}
Now, you tell me, where did you store any variable in the array global_a?
In order to avoid this, you might do the following:
#include <iostream>
using namespace std;
int global_a[100],n;
void citire(int n)
{
// int a[100]; don't declare a local variable, so while referring to "a",
// the global variable will be used:
for(int i = 0 ; i < n ; i ++) { // the for loop
cin >> global_a[i]; // entering the numbers for each
}
cout << global_a[5] << endl; // returns the right number
}
int main()
{
cout << "n= "; cin >> n; // how many numbers should the vector have.
citire(n); // me calling the function
cout << global_a[5]; // returns 0
}
For your information, the prefixes "local_" and "global_" are just there for clarification purposes. In the last example, you might just write "a" instead of "global_a", the result will be the same.

I'm having trouble in C++ geting input from a user in a function, adding to an array, and printing that array

I'm learning c++ and I'm trying to ask the user to input 4 numbers in a function, and then simply print the array.
int getFourNums();
int main(int argc, char** argv){
int getNums;
getNums = getFourNums();
cout << "The array is: " getNums << endl;
}
int getFourNums(){
int i;
int myArray[4];
cout << "Enter 4 nums: ";
for(i = 0; i < 4; i++){
cin >> myArray[i];
}
return myArray[i];
As of now, it's letting me get the four numbers, but the result that's printing is "The array is: 0." I'm not quite sure why the array is seemingly not populating.
Your fundamental problem is that int getFourNums() can only return a single integer, not an array of them. The next problem is that functions cannot return raw arrays for historical reasons. Your choices are to return a std::array, a struct containing the array, pass the array by reference into the function, or return a std::vector. My preference for this application is a std::vector - it is flexible, and although not quite as efficient as std::array, you should probably default to std::vector unless you have a good reason otherwise. Your getNums code would then look like:
std::vector<int> getFourNums() {
std::vector<int> result;
cout << "Enter 4 nums: ";
for(int i = 0; i < 4; i++){
int v;
cin >> v;
result.push_back(v);
}
return result;
}
To print the vector, see this question. My personal preference would be a range-based for loop over the vector; your tastes may vary.
One issue in your code is that a loop like
for(i = 0; i < 4; i++){
cin >> myArray[i];
}
will end up with i==4. Hence, return myArray[i] will exceed array bounds and/or access an uninitialised value then and yield undefined behaviour.
The main issue, however, is that in C++ you'll follow a very different approach and use collection types like std::vector instead of plain arrays. See the following code illustrating this. Hope it helps.
#include <vector>
#include <iostream>
std::vector<int> getFourNums(){
int val;
std::vector<int> result;
cout << "Enter 4 nums: ";
for(int i = 0; i < 4; i++){
cin >> val;
result.push_back(val);
}
return result;
}
int main(int argc, char** argv){
std::vector<int> fourNums = getFourNums();
for (auto i : fourNums) {
cout << i << endl;
}
}
int getFourNums() will only let you return one int, not the whole array and return myArray[i]; is out of bounds since i == 4. You can only use the range [0,3] as indices for your array. Here's a reworked version with comments in the code.
#include <iostream>
#include <vector>
// don't do "using namespace std;" since it includes
// a lot of stuff you don't need.
// Here's a function that will return a vector of int's
// It'll behave much like a C style array
// but can have variable length and you can use
// a lot of standard functions on it.
std::vector<int> getNums(size_t count) {
// The "array" we'll return with "count" number of
// default constructed int:s (they will all be 0):
std::vector<int> myArray(count);
std::cout << "Enter " << count << " nums: ";
// A range based for loop that will go through
// all int:s in "myArray". "num" will be
// a reference to each int in the vector which
// means that if you change the value of "num",
// you'll actually change the value in the vector.
for(int& num : myArray) {
// read values into the int currently
// referenced by num
std::cin >> num;
}
// return the vector by value
return myArray;
}
// Put main() last so you don't have to forward declare the functions
// it uses
int main() {
// call getNums with the value 4 to read 4 int:s
std::vector<int> Nums = getNums(4);
std::cout << "The array is:";
// print each int in the vector. There's no need to use
// a reference to the int:s here since we won't be changing
// the value in the vector and copying an int is cheap.
for(int num : Nums) {
std::cout << " " << num;
}
// std::endl is rarely good when you only want to output a newline.
// It'll flush the buffer with is costly.
// Make a habit of using "\n" in most cases.
std::cout << "\n";
}
I see that you want to return entire array but just look at your return type:
int getFourNums()
You're returning an integer right? In this situation the returned integer is always myArray[4]. Be aware that it's an integer value, you're returning something that doesn't belong to you actually!
So what to do? I suggest you to pass your array to function like this:
void getFourNums(int myArray[]){
int i;
cout << "Enter 4 nums: ";
for(i = 0; i < SIZE; i++){
cin >> myArray[i];
}
}
Now you filled your array. How to print your array then? We can't simply give our array name and tell cout to print it like you did (you couldn't actually!). Nothing magical here. We're going to print your array's element one by one:
void printFourNumbers(int array[])
{
for(int i = 0 ; i < SIZE ; ++i)
{
cout << array[i] << endl;
}
}
Finally whole code looks like this:
#include <iostream>
using namespace std;
const int SIZE = 4;
void getFourNums(int myArray[]);
void printFourNumbers(int array[]);
int main(int argc, char** argv){
int myArray[SIZE];
getFourNums(myArray);
printFourNumbers(myArray);
}
void getFourNums(int myArray[]){
int i;
cout << "Enter 4 nums: ";
for(i = 0; i < SIZE; i++){
cin >> myArray[i];
}
}
void printFourNumbers(int array[])
{
for(int i = 0 ; i < SIZE ; ++i)
{
cout << array[i] << endl;
}
}

Issue with user-defined array in C++

I am trying to create an array using cin to define the size. While that seems to be working (based on what I currently have), none of the other stuff I want to do seems to be working.
For instance, I want to use a for loop to find the smallest int in the array since I will then need to compare it with all the other ints in the array, but no matter where I have the statement to return the smallest int, it does not do it.
What am I doing wrong?
#include <iostream>
using namespace std;
int main(){
int userSize;
cout << "Please define size of array: ";
cin >> userSize;
int *duckArray = new int[userSize];
for (int i = 0; i < userSize; i++) {
cout << "Please enter a number into the array: ";
cin >> duckArray[i];
}
int smallest = duckArray[0];
for (int i = 0; i < userSize; i++){
if (duckArray[i] < smallest){
smallest = duckArray[i];
cout << smallest << endl;
}
}
//cout << smallest << endl;
return 0;
}
Your code is working if you change this:
for (int i = 0; i < userSize; i++){
if (duckArray[i] < smallest){
smallest = duckArray[i];
}
}
cout << smallest << endl;
This will find and print the smallest number entered.
Arrays in C++ must have their size declared to the compiler at runtime. Other people are going to explain how you can buffer memory to simulate a dynamically allocating arrays. You can also have your Array at a given size and as the user adds and removes, you can reject inputs over the current size.
I highly recommend you look into Vectors. Vectors are much like ArrayLists in Java. They are a form of higher level collections that resize themselves as you add more elements to them.

Stumped on array creation program

For a program I must use an array and not vector. I have to take in user's input, and it's a indefinite amount of them. The user can type in 5 values, or 50. I am absolutely stumped as to how to go about doing this. Using a for loop for example:
Int a[10];
Int b;
For (int i=0; i<10; i++)
{
Cout<<"enter values:";
Cin>>b;
A[i]=b;
}
With this I can take an array of 10 of user defined variables but how would I go about making it a dynamic size? Thank you for the help!
The size of a static array must be known at compile time, otherwise you must use a dynamic array. For example
#include <iostream>
int main()
{
// Determine how many total entries are expected
int entries;
std::cout << "How many values do you want to enter?" << std::endl;
std::cin >> entries;
// Allocate a dynamic array of the requested size
int* a = new int[entries];
// Populate the array
for (int i = 0; i < entries; ++i)
{
std::cout << "enter a value: ";
std::cin >> a[i];
std::cout << std::endl;
}
// Clean up your allocated memory
delete[] a;
return 0;
}

Arranging elements from two vectors alphabetically into one vector

The two vectors the user enters will always be in alphabetical order, and the function merge_items places those values in one vector seeing which one comes before the other by using the < operator, the code initially gave a segmentation fault and at certain times, it doesn't show the last element.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void merge_items(vector<string>& a1,vector<string>& b1,vector<string>& merged);
int main(){
vector<string> v1,v2;
string a,b;
int n1,n2;
cout << "How many values for v1? " << endl;
cin >> n1;
for(int i = 0;i < n1;i++){
cin >> a;
v1.push_back(a);
}
cout << "How many values for v2? " << endl;
cin >> n2;
for(int i = 0;i < n2;i++){
cin >> b;
v2.push_back(b);
}
vector<string> merge;
merge_items(v1, v2, merge);
for(int i = 0;i < merge.size();i++){
cout << merge[i] << endl;
}
return 0;
}
void merge_items(vector<string>& a1,vector<string>& b1,vector<string>& merged){ int i1 = 0,i2 = 0;
string temp;
while(i1+i2 < (a1.size()-1+b1.size()-1)){
if(a1[i1] < b1[i2]){
temp = a1[i1];
merged.push_back(temp);
i1++;
}else{
temp = b1[i2];
merged.push_back(temp);
i2++;
}
}
}
This is the appropriate way to merge:
std::merge(a1.begin(), a1.end(),
b1.begin(), b1.end(),
std::back_inserter(merged));
As far as what's wrong with your solution. A couple things.
First, once you reach the end of one of the two vectors, you need to stop comparing against that vector and just copy whatever elements are left from the other vector. So you need to compare i1 against a1.size(), separately from your comparison of i2 against b1.size(). With what you're doing now, when you reach the end of one vector, you continue comparing against out of bounds elements from that vector, which is undefined behavior, and likely the cause of your segmentation faults.
Second, you don't need to be subtracting 1 from the size of the vectors. The way you're doing it will leave you with a merged vector which has 2 fewer elements than the combined sizes of the source vectors.