I'm trying to write a program that reads values from cin using a pointer, and then outputs the values alongside their position in the array. I can't figure out why printNumbers1 works but printNumbers2 doesn't. Here is the program (relevant code near the bottom):
#include <iostream>
using namespace std;
int *readNumbers(int);
void printNumbers1(int*);
void printNumbers2(int*);
int main()
{
int *numbers = readNumbers(5);
printNumbers1(numbers);
printNumbers2(numbers);
return 0;
}
int *readNumbers(int n)
{
int a[n];
int *numbers;
numbers = &a[0];
for (int i=0; i<n; i++)
{
cin >> *(numbers+i);
}
return numbers;
}
void printNumbers1(int *numbers)
{
cout << 0 << ' ' << *(numbers) << endl
<< 1 << ' ' << *(numbers+1) << endl
<< 2 << ' ' << *(numbers+2) << endl
<< 3 << ' ' << *(numbers+3) << endl
<< 4 << ' ' << *(numbers+4) << endl;
}
void printNumbers2(int *numbers)
{
for (int i=0; i<5; i++)
{
cout << i << ' ' << *(numbers+i) << endl;
}
}
When I run the program, it works as intended for printNumbers1 but outputs a combination of seemingly random numbers and 0s for printNumbers2. I feel like the two printNumbers functions should should function identically, but they don't. What am I missing?
This happens because of a combination of two things:
C++ does not allow variable-length arrays - this is a popular extension, but the declaration int a[n] is not standard.
You cannot return a pointer to local variable from a function - pointer numbers inside readNumbers points to a, a local variable. You can use this pointer inside the function, but outside of the function it becomes invalid, because a goes out of scope.
Using an out-of-scope variable causes undefined behavior. This Q&A provides a very good explanation of what is happening, and why it may look like the program is working fine.
If you want to use built-in pointers, remove int a[n], and change the declaration of numbers as follows:
int *numbers = new int[n];
You also need to add
delete[] numbers;
before return 0 line to avoid memory leaks.
I am assuming that you wrote this code as part of a learning exercise. In general, though, a better approach in C++ is to use std::vector<int>, which hides pointer operations from your code, and deals with resource management for you.
readNumbers returns a pointer to a variable with automatic storage duration.
The behaviour on dereferencing that pointer is undefined.
Use a std::vector instead. Rely on return value optimisation to obviate any superfluous value copies being taken.
Here you have created the array a[n] inside the function, so it is a local variable, Hence this array may or may not be deleted after the scope of the function ends.Never use the address of a local variable outside the funcrtion. This code is working:
#include <iostream>
using namespace std;
int *readNumbers(int);
void printNumbers1(int*);
void printNumbers2(int*);
int main()
{
int *numbers = readNumbers(5);
printNumbers1(numbers);
printNumbers2(numbers);
return 0;
}
int *numbers;
int *readNumbers(int n)
{
numbers = new int[n];
for (int i=0; i<n; i++)
{
cin >> *(numbers+i);
}
return numbers;
}
void printNumbers1(int *numbers)
{
cout << 0 << ' ' << *(numbers) << endl
<< 1 << ' ' << *(numbers+1) << endl
<< 2 << ' ' << *(numbers+2) << endl
<< 3 << ' ' << *(numbers+3) << endl
<< 4 << ' ' << *(numbers+4) << endl;
}
void printNumbers2(int *numbers)
{
for (int i=0; i<5; i++)
{
cout << i << ' ' << *(numbers+i) << endl;
}
}
Related
I want to increase the size of the array of string after declaring it once, how can it be done. I need to increase the size in the following code..
#include<iostream>
using namespace std;
#include<string>
int main()
{
int n;
string A[] =
{ "vaibhav", "vinayak", "alok", "aman" };
int a = sizeof(A) / sizeof(A[0]);
cout << "The size is " << a << endl;
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
cout << "Enter the number of elements you want to add to the string"
<< endl;
cin >> n;
cout << "ok now enter the strings" << endl;
for (int i = a; i < n + a; i++)
{
cin >> A[i];
}
a = a + n;
A.resize(a); // THIS KIND OF THING
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
return 0;
}
Plain and simple: you cannot.
You can get a larger array, copy all your stuff over and use that instead. But why do all that, when there is a perfectly good class already there, doing it all for you: std::vector.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
// want to enter more?
sd::string more;
std::cin >> more;
A.push_back(more);
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
return 0;
}
Convert your code over to use std::vector and this problem becomes much easier to solve.
#include<iostream>
#include<string>
#include<vector>
int main(){
int n;
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
int a = A.size();
std::cout << "The size is " << a << std::endl;
//Prefer Range-For when just iterating over all elements
for(std::string const& str : A){
std::cout << str << std::endl;
}
std::cout << "Enter the number of elements you want to add to the string" << std::endl;
std::cin >> n;
std::cout << "ok now enter the strings" << std::endl;
for(int i = 0; i < n; i++ ) {
//emplace_back automatically resizes the container when called.
A.emplace_back();
std::cin >> A.back();
//If you're using C++17, you can replace those two lines with just this:
//std::cin >> A.emplace_back();
}
for(std::string const& str : A){
std::cout << str << std::endl;
}
return 0;
}
Also, don't use using namespace std;, since it leads to expensive to fix bugs and makes your code harder to read for other C++ programmers.
I want to increase the size of the array of string after declaring it
once, how can it be done.
It cannot be done. Use std::vector if the element count isn't known at compile time or can change dynamically. It even has a resize member function named exactly like the one in your code.
You cannot increase the size of a Raw Array, you could use an std::vecto<std::string> as this type of array can grow at runtime.
However, you could also create a class that will store an array of string and create your own implementation to resize the raw array. Which would be creating a bigger array and copying all the other values over, then setting the class array to the new array (or just return it)
Here's the code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
The only reason I gave values to keyArray was that I read in answer to a similar question that you have to initialize an array with data before you use it. But it made no difference. The output is just junk symbols whether you initialize or not.
The compiler is Visual Studio Community 2017. Thanks for any help.
The error is not in your logic but rather in your debugging output. Since the other answers focus on how to fix it, I'll rather explain what happens instead. There seems to be a misunderstanding about the way strings work in C++.
The failure is in this operation:
keyArray[0] + "\n"
Internally, string literals are arrays of characters, in this case const char[2], consisting of the newline and a terminating '\0' null terminator. When you then try to add the integer and this array together, the array will be represented by a pointer to its first element, i.e. it will decay to const char* in order to be used as the second argument to the plus operator used in your code.
So for the compiler, this line will need operator+(int, const char*). But the result of that will be const char*, the input pointer offset by the integer, as that is the operation that happens when adding integers to pointers.
So instead of printing the number and then the string, it will try to access a string that does not exist as the pointer now pointer behind the string "\n" and thus into some arbitrary memory.
Instead of doing
cout << keyArray[0] + "\n"
do:
cout << keyArray[0] << "\n"
or
cout << keyArray[0] << endl
You can't concatanate an integer with a string. That's why you got garbage output
Try this first:
cout << keyArray[0] << "\n";
If you are using compilers that support C++ 11 then try using std::to_string(...) to make a string from an integer before doing the addition:
cout << (std::to_string(keyArray[0]) + "\n");
you cannot concatenate int with string.
change
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
to
cout << keyArray[0] << "\n"
<< keyArray[1] << "\n"
<< keyArray[2] << "\n"
<< keyArray[3] << "\n"
<< keyArray[4] << "\n"
<< keyArray[5] << "\n"
<< keyArray[6] << endl;
You need to convert the integers into a string. Using a relatively recent version of C++:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << std::to_string(keyArray[0]) + "\n";
cout << std::to_string(keyArray[1]) + "\n";
cout << std::to_string(keyArray[2]) + "\n";
cout << std::to_string(keyArray[3]) + "\n";
cout << std::to_string(keyArray[4]) + "\n";
cout << std::to_string(keyArray[5]) + "\n";
cout << std::to_string(keyArray[6]) + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
I use pointers to print the contents of a string array for this program, I have trouble in printing out the item's names. Whatever I enter how many items, it prints out only one item. For example, when I entered pencil, pen, book, it only printed out the last item 3 times: book book book instead of printing: pencil pen book.
void getPrint(string *names, int num){
cout <<"Here is the items you entered: ";
for (int i=0; i<num; i++){
cout <<*names<<" ";
}
Maybe you want to treat the pointer to a single string as an array:
void getPrint(string * names, int num)
{
for (int i = 0; i < num; ++i)
{
cout << names[i] << " ";
}
cout << endl;
}
There are other possibilities:
cout << names++ << " ";
cout << *(names + i) << " ";
Look up pointer dereferencing in your favorite reference.
The preferred solution is to use std::vector<string> or std::array<string>.
void getPrint(const std::vector<std::string>& names)
{
const unsigned int quantity = names.size();
for (unsigned int i = 0; i < quantity; ++i)
{
std::cout << names[i] << " ";
}
std::cout << endl;
}
There are two possibilies:
Array syntax
Your treat your std::string as an array and increment over its indices. To be consistent you can pass the argument in array syntax as well.
void getPrint(const std::string names[], const int num){
std::cout <<"Here is the items you entered: " << std::endl;
for (int i=0; i<num; i++){
std::cout <<names[i]<<" " << std::endl;
}
}
Pointer syntax
You pass your std::string as a pointer (on the first element of you array). To reach all your elements you have to increment the pointer itself.
void getPrint(const std::string* names, const int num){
std::cout <<"Here is the items you entered: " << std::endl;
for (int i=0; i<num; i++){
std::cout <<*(names++)<<" " << std::endl; // increment pointer
}
}
Since incrementing your pointer does not need the index i anymore you can shorten the whole thing a bit (but may not declare const num anymore).
void getPrint(const std::string* names, int num){
std::cout <<"Here is the items you entered: " << std::endl;
while(num--){
std::cout <<*(names++)<<" " << std::endl;
}
}
Hope I could help you.
Edit
As mentioned above any solution using the STL containers std::vector or std::array and passing them by reference are preferred. Since they provide .begin() and .end() methods one can use (C++11)
void getPrint(const std::vector<std::string>& names){
std::cout <<"Here is the items you entered: " << std::endl;
for (auto name: names){
std::cout << name << " " << std::endl;
}
}
This question already has answers here:
Two different values at the same memory address
(7 answers)
Closed 5 years ago.
New to C++ and learning the const_cast — get really confused by the code below:
int main(){
const int j = 1;
int * p = (int *)(&j);
cout << j << ' ' << *p << endl;
cout << &j << ' ' << p << endl;
*p = 2;
cout << j << ' ' << *p << endl;
cout << &j << ' ' << p << endl;
const int k = 1;
int * q = const_cast<int*>(&k);
cout << k << ' ' << *q << endl;
cout << &k << ' ' << q << endl;
*q = 2;
cout << k << ' ' << *q << endl;
cout << &k << ' ' << q << endl;
return 0;
}
The outputs are
1 1
00A2FD9C 00A2FD9C
1 2
00A2FD9C 00A2FD9C
1 1
00A2FD84 00A2FD84
1 2
00A2FD84 00A2FD84
Could anyone tell me why the addresses (&i and p, or &j and q) are the same, but there values (i and *p, or j and *q) are different? I am using Visual Studio 2013RC.
That happens because the compiler can assume a const variable won't change, and hence when your code refers to it, the compiler assumes that using the variable value, or the original value at initialization won't matter, it shoudn't change behavior, so it compiles to what is faster to execute, just using constant 1 without referring to memory locations.
Using const_cast<T*>(obj) to cast away constness and modifying the object is undefined behavior if obj started its life as a constant. In your example you tell the compiler that j isn't going to change and the compiler just replaces all uses of j to become uses of 1, instead. You then break the promise and the code the compiler generated won't pay any attention to you anymore and, instead, does what it pleases.
I want to return an array created in a local function through pointers to the main function. My code is below. The array is returned and I am able to access each element by element once only. The next time it is giving garbage values. What is Wrong?
void DoWork(int** ppOut , int& nSize)
{
int m[5];
for(int i = 0 ; i < 5 ; i++)
{
m[i] = i;
}
nSize = 5;
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;
cout << m[4] << endl;
*ppOut = &m[0];
//delete [] m;
}
void main()
{
int nSize = -1;
int i;
int* f = NULL;
DoWork(&f , nSize);
cout << f[3] << endl;
cout << f[0] << endl;
cout << f[2] << endl;
cout << f[3] << endl;
cout << f[4] << endl;
_getch();
}
Output is:-- 0 1 2 3 4 from local function.
But in main 3 and rest are grabage values
The Problem:
The array m is a local array which does not exist beyond the lifetime of the function DoWork(). When you do so what you end up with is Undefined Behavior, which basically means that you can see any observable behavior because the program ceases to be a C++ standard approved program and so it can show(literally) any behavior.
The Solution:
You will need to extend the lifetime of m so that it is still valid even after the function returns. There are number of ways to do this:
Create an array before the function & pass a pointer to it to the function.
Create a static array inside the function.
Use dynamic memory for the array in function (do remember to release it after usage)
Use global array which can be poulapted inside the function.
Each has own pros and cons and its more of horses for courses.
On a side note, void main() is not the standard specified prototype for main() it should return an int:
int main()
The main function in a C++ program should be int main
Returning a pointer to a local variable exhibits undefined behavior.