Wrong values in second array - pointers - c++

I've started learning C++ and I found some problem with pointers. I'm not sure what did I wrong
char *tablica = NULL;
char *ps;
char c;
int i;
cin >> c;
for (i = 0; c != '#'; cin >> c){
if (!(isdigit(c))){
ps = new char[i + 1];
tablica = ps;
tablica[i] = c;
cout << tablica[i] << " na i " << i << endl;
i++;
delete ps;
}
}
for (int n = 0; n < i; n++){
if (islower(tablica[n]))
cout << char(toupper(tablica[n])) << endl;
else if (isupper(tablica[n]))
cout << char(tolower(tablica[n])) << endl;
else
cout << tablica[n] << endl;
}
delete [] tablica;
It should ask the user to write a single char, and then check if it's not a number (first array) - works fine.
Then the second one should change lower case to upper case, but in here the values are incorrect. I wrote this code without pointers and it worked fine.
Can anyone help?

When you do ps = new char[i + 1] you make ps point to some memory you allocate.
When you do tablica = ps you make tablica point to the same memory. You don't copy the actual memory pointed to by ps, only the pointer ps is copied.
That means when you next iteration allocate memory again what you read and stored into the memory pointed to by tablica (and ps) is gone.
In the second loop the memory pointed to by tablica doesn't exist anymore, since last in your previous loop did delete ps (which is itself an error, as it should be delete [] ps). You attempt to dereference memory that no longer is owned by your program.
Unless your exercise is to learn pointers, then use std::vector instead.

You are deleting the memory object to which the tablica pointer is referring.
Instead of doing
tablica = ps;
Use
tablica = new char[i+1];
So that it could create another memory segment for the array to be used later.

Related

What is this pointer and memory code printing? I don't know if it's printing garbage or how to print the value that I need

This is a snippet of code that I took from a bigger one. I need to figure out whether or not what I'm printing is garbage and how to change it for it to print the value I need.
I need it to print the value of int id instead of whatever it's printing. The output was 10813776 in this run and it, of course, changes whenever I change some code or relaunch DevC++.
The code is:
#include <iostream>
#include <memory> //Memory allocation (malloc)
using namespace std;
int main(){
int id = 0;
int nMemory = 0;
int * pMemory;
pMemory = (int *) malloc(20 * sizeof(int));
while(id < 20){
if (pMemory != NULL){
cout << "Numbers in memory: " << endl;
pMemory = new int[id];
nMemory = *pMemory;
cout << nMemory << endl;
}
id++;
}
delete pMemory;
return 0;
}
pMemory = new int[id];
nMemory = *pMemory;
The first line replaces the array you've malloc-ed with a new uninitialized one, and then tries to read from the first slot of that new array. You shouldn't be assigning directly to pMemory; maybe to pMemory[someIndex], but not to pMemory itself.
Are you trying to read from the pMemory array and assign it to nMemory? If so, change the lines above to this:
nMemory = pMemory[id];
Your entire loop should look more like this:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
while(id < 20) {
nMemory = pMemory[id];
cout << nMemory << endl;
id++;
}
}
Or, with a more idiomatic for loop:
if (pMemory != NULL) {
cout << "Numbers in memory: " << endl;
for (int i = 0; i < 20; i++) {
cout << pMemory[i] << endl;
}
}
(You're also going to have to initialize the array somewhere above this loop. I presume you do that in your real code, but if not: the code you posted allocates an array with malloc() but does not set the items to useful values. Make sure to set them to something meaningful before you then try to read and print them.)
This code is leaking the memory blocks you allocate with malloc() and new[].
You malloc() a block of memory and assign its address to pMemory, then you change pMemory to point at different memory addresses that are allocated with new[]. So you lose the ability to free() the malloc()'ed memory (you are not even trying to call free()).
And, this code is not freeing the memory allocated with new[] correctly. Memory allocated with new[] must be freed with delete[], not with delete. Worse, you are calling new[] 20 times in a loop, but calling delete only once after the loop. So, you are leaking 19 blocks of new[]ed memory, and have undefined behavior freeing 1 block.
Now, to answer your actual question, the code is printing out garbage because the memory you are allocating with new[] is uninitialized, so the data you are trying to print from that memory contains indeterminate values.

Entering value to dynamically allocated memory at runtime

Following is the code I wrote for reading a value at run time to dynamically allocated memory:
void main()
{
clrscr();
int *p = new int[5];
int *a = new int();
cin >> *a; // **line 5**
cout << *a << "\n"; // **line 6**
cout << &p; // line 7
cout << *p; // line 8
cout << "\nEnter 5 no for array\n";
for (int i = 0; i <= 4; i++)
{
cout << &p[i] << " :- ";
cin >> p[i]; // LINE 12
}
for (i = 0; i <= 4; i++)
cout << "\n" << p[i]; // LINE 16
delete[] p;
delete a;
getch();
}
I would like to know that while entering data for user in integer, we have to use *a with cin and cout for entering data in line 5 & 6 but in case of array we just gave the pointer variable name in line 12 & 16. Can anyone please tell me why we are having this difference?
Moreover can anyone also please tell me the difference between output of line 7 & 8.
You don't "have to"; you could have written cin >> a[0].
For built-in types and pointers and such, a[b] is *(a+b) is *(b+a) is b[a] and you can interchange them all.
It's only convention that leads to a choice. Like generally if you'd allocated more than one int you'd use "array notation" (a[i]) and if you'd allocated only one int you'd use a straight-up dereference (*(a+0), or *a).
But the language doesn't really care how many elements you allocated because either way you just have a pointer to "one or more" consecutive elements.
tl;dr this is just how the syntax was designed.
As for your second question, &p and *p give different results because they mean different things, and I'll leave discerning that difference as an exercise to the reader.

c++ dynamic allocation of char *

I have a problem in the following piece of code, the problem simply is that values of the dynamically-allocated array of char* changes from line number 24 to line number 28 and I can't figure out why
Code:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <ctype.h>
#include <cstring>
using namespace std;
int main() {
string x = "5+90-88n";
unsigned int i =0, k=0, argc=0;
char** argv = new char*[x.length()];
while (i < x.length()) {
if (isdigit(x[i])) {
k=0;
while (isdigit(x[i+k])) {k++;}
argv[argc] = (char*)x.substr(i,k).c_str();
i+=k;
} else {
argv[argc] = (char*)x.substr(i,1).c_str();
i++;
}
cout << argc <<" "<< argv[argc] <<endl;
argc++;
}
cout << " ------ \n";
for (unsigned int kk =0; kk<argc; kk++) {
cout << kk << " " << argv[kk] << endl;
}
return 0;
}
Output :
0 5
1 +
2 90
3 -
4 88
5 n
------
0 n
1 n
2 n
3 n
4 n
5 n
I was expecting the upper and lower parts to be the same, being not the same means that even there is some mistake I did and didn't notice or there is something I don't know about using dynamic allocation.
The array pointed to by the pointer returned std::string::c_str is owned by the string. substr returns a temporary string object that goes out of scope at the end of the expression in which substr was called.
Taken together these two facts mean that the arrays pointed to by the pointers in argv get deleted immediately after you create them. By the time you get around to printing any of them they are long dead.
It seems a simple problem, but it doesn't actually, It took me hours to try to find the answer.
Let us see this code below:
int main()
{
const char* p;
const char* p1;
{
string x = "xt";
p = x.substr(0, 1).c_str();
cout << p << endl;
p1 = x.substr(1, 1).c_str();
cout << p1 << endl;
}
cout << p << endl;
cout << p1 << endl;
return 0;
}
Its output is:
x
t
t
t
When running in the {} scope, p and p1 are pointing to temporary variables, and now these variables are existing, so we can print p an p1 out. When the code running out of the {} scope, those temporary variable are inexistent, we just cannot refer to them again, but their memory and data are still existent. So we still can print the value of p and p1 out without a memory crash.
But why the value of p and p1 are the same?
Let us see this:
int main()
{
const char* p;
const char* p1;
{
string x = "xt";
string t1 = x.substr(0, 1);
p = t1.c_str();
cout << p << endl;
string t2 = x.substr(1, 1);
p1 = t2.c_str();
cout << p1 << endl;
}
cout << p << endl;
cout << p1 << endl;
return 0;
}
Its output is:
x
t
x
t
just as you expected.
Maybe there is something strange with substr. But I am not sure about it. I'll go on checking.
And, as the code shows above, p and p1 are pointing to different temporary variables, according to the different outputs, p and p1 may be pointing to the same temporary variable in the first example.
Let us back to your code, char** is pointers to pointers, It is wrong to frequently make a pointer point to a temporary variable.
My suggestion is that you might use a array of string instead of a array of pointer.
Hope that helps.
You are not allocating anything for the temporary sub-string string object created which creates a temporary pointer to an array.
Doing something like this should work but won't recommend as you can't free that memory anymore:
argv[argc] =(char*)((new string(x.substr(i,k)))->c_str());
You need the string object to survive as c_str returns a constant pointer to the string object's value. If string object doesn't exist, what will be that pointer pointing to? Read this: c_str cplusplus.com
It is recommended to store the sub-strings to some array/vector, and then do necessary work with pointers.
#Mohamed Ibrahim, I think I have gotten the real reason of this problem that the two output are different.
Let us consider one problem at first:
What is happening when a temporary variable has ended its lifetime?
Please see this code:
int a1 = 9;
int& a = a1;
{
int b = 10;
a = b;
cout << a << endl;
int c = 11;
count << a << endl;
}
cout << a << endl;
its output is:
10
11
11
But as we know, 'b' and 'c' has gone when we try to print 'a' out at the last time. Why does 'a' still hold a value?
The reason is the memory and data of 'b' and 'c' is still existing in spite of 'b' and 'c' have gone. 'a' is a reference, it refered to the memory of 'b' and 'c'.
Let us continue considering:
When will the memory and data of a temporary variable be swept?
Even a temporary lifetime has been ended, but its memory and data are still existing until another temporary variable is declared, and the value of the new varialbe covers the value the old variable in that memory, and then all of the pointers and the references who are refering to the old variable, their value has been changed, we can print their value out to prove.
So, in your code, a new temporary variable of string will be declared in each loop, despite you can print a correct value out, but the new variable has covered the old. After the while scope ended, only one variable's value is existing, it is the last variable you declared, all of the others have been covered. So, we just could see the same value in the last output.
The way to remain every value is to save it in a global variable:
int main()
{
string x = "5+90-88n";
unsigned int i =0,k=0,argc=0;
char** argv = new char*[x.length()];
while ( i< x.length())
{
if (isdigit(x[i])) { k=0;
while(isdigit(x[i+k])) {k++;}
char* temp = (char*)x.substr(i,k).c_str();
argv[argc] = new char[strlen(temp) + 1];
memset(argv[argc], 0, sizeof(argv[argc]));
strcpy(argv[argc], temp);
i+=k;
}
else {
char* temp = (char*)x.substr(i,1).c_str();
argv[argc] = new char[strlen(temp) + 1];
memset(argv[argc], 0, sizeof(argv[argc]));
strcpy(argv[argc], temp);
i++;
}
cout << argc <<" "<< argv[argc] <<endl;
argc++;
}
cout<<" ------ \n";
for( unsigned int kk =0;kk<argc;kk++) { cout <<kk <<" "<<argv[kk]<<endl; }
return 0;
}
the above code could work well, but it is unsafe, I don't like this way of coding.
My suggestion, as I have ever said, don't try to make a pointer point to a temporary variable, never do that. No offence, please correct your code.

A simple vector, how can I reassign the address for a new array correctly

I am trying to create a simple version of a vector. It seems to be working if I look only at what I am storing, but there is one thing that concerns me. Here is my code:
#include <iostream>
using namespace std;
int main(){
char* arr = new char[1];
int size = 1; // current size of the array
int num_chars = 0; // how many characters are stored so far
char c;
while (true)
{
cout << ">";
cin >> c;
if (c == '!') break;
if (num_chars == size)
{
size *= 2;
char* new_arr = new char[size];
cout << "Old array address: " << &arr << endl;
cout << "New array address: " << &new_arr << endl;
for (int i = 0; i < size/2; i++) // copy arr to new_arr
new_arr[i] = arr[i];
delete[] arr;
arr = new_arr;
}
arr[num_chars++] = c;
for (int i = 0; i < num_chars; i++)
cout << arr[i];
cout << endl;
cout << &arr << endl;
}
delete[] arr;
return 0;
}
the program accepts characters one at a time, and they are stored in an array which grows dynamically, finishing when you enter an exclamation mark. I added some cout statements to check my input and where the arrays are being stored.
When I allocate new_arr it gets a new address, then I copy over the memebers of arr to the new arr, delete arr, and assign arr to point to new_arr. The part that concerns me is that when I check the memory locations of arr after it gets reassigned, it's the same as it was before, so it looks like I'm just writing past the end of the original array. How can I correctly reassign the pointer to the new array?
Here is some sample output:
>a
a
0x7fff5fbff760
>b
Old array address: 0x7fff5fbff760
New array address: 0x7fff5fbff748
ab
0x7fff5fbff760
>c
Old array address: 0x7fff5fbff760
New array address: 0x7fff5fbff748
abc
0x7fff5fbff760
You are printing out addresses of pointers themselves, not addresses of the arrays (i.e. the contents of the pointers).
The location in memory where you store the address of the array (i.e. the address of variable arr) stays the same. It's not supposed to change. Thus, &arr is always the same. But the value stored in that location does change (as it would be expected).
Change the code to
cout << "Old array address: " << static_cast<void*>(arr) << endl;
and see the difference.
(static_cast<void*>(arr) casts type of arr from char* to void*. The reason to do this is that cout treats char* as a pointer to null-terminated string, and prints the contents of the string instead of the pointer's value. However, if we change the type of the pointer to something that cout does not interpret (e.g. void*), then cout will just print the address.)

C++ char pointer array - cannot access elements

I am having some trouble storing some char pointers in my array
The method should take a char* array and and int pointer which is the size of the array. Then I loop and ask the user to enter the names. Then I want to print them; however it seems like there's nothing in my array.
Note I cannot use array notation for this assignment, I must use pointer notation to access the elements of the array.
void sort_name(char* name[], int* items)
{
//store the names
cout << "In function items is " << *items << endl;
for(int i=0; i<*items; i++)
{
string str;
cout << "Enter name #" << (i+1) << ": ";
getline(cin, str);
char* current = new char[str.size() + 1];
*(name + i) = current;
}
for(int i=0; i<*items; i++)
{
cout << *(name + i) << endl;
}
}
char* current = new char[str.size() + 1];
*(name + i) = current;
You are correctly allocating new memory for each of the array elements, but you never assign any value to them. Since this is homework, I won't say more.
You forgot to copy the string entered by the user to the array. There is no copy from str to current.
You need to actually copy the string, rather than just allocate space for a copy. Try this:
int length=str.copy(current,str.size(),0);
current[length]='\0';
just after you allocate the string. I.e., put the above code right after this line in your code:
char* current = new char[str.size() + 1];
If you want to do this way you need to copy the actual entry.
check strcpy or memcpy.
add the second line : (and #include "stdio.h")
char* current = new char[str.size() + 1];
strcpy(current , str.c_str());
(name + i) = current;
it should work.
You use "int* items", its better to use "int items".
i would written "name[i]" instead of "*(name + i)".
and if you know the maximum size of strings you want to allow, if it's n, you can directly write :
for(int i=0; i<*items; i++)
{
cout << "Enter name #" << (i+1) << ": ";
name[i] = new char[n];
cin.getline( name[i] , n);
}