Array of Pointers getting garbage value in c++ - c++

I'm trying to create an array of pointers to a 2D (5 X 12) array in C++.
The ptr array has 5 elements. Each element should hold the address of the 1st element of the respective row of the 2D array. So 1st element should point to 1st element of 1st row, 2nd element should point to 1st element of 2nd row, and so on.
The 5th element of my array of pointers seems to point to a garbage value.
Code and output shown below. Can anyone please let me know why?
#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int main( )
{
int rainMatrix[5][12] = {{0}}; //declare and initialize rain matrix
int *matrix_ptr[5] = {NULL};//declare and initialize array of pointers
int **matrix_ptr_ptr = matrix_ptr;
for (int i = 0; i < 5; ++i)
matrix_ptr[i] = &rainMatrix[i][0];
rainGen(matrix_ptr_ptr, 5, 12); //generate a random matrix
//display the matrix
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 12; ++j) {
cout << setw(2) << rainMatrix[i][j] << " ";
}
cout << endl;
}
for (int i = 0; i < 5; ++i)
cout << setw(2) << *matrix_ptr[i] << " " << rainMatrix[i][0] << endl;
return 0;
}
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
**pptr = rv;
*pptr += 1;
}
pptr++;
}
}
OUTPUT
11 1
88 11
28 88
25 28
1477892712 25

You're manipulating the wrong pointer in the innermost loop. Consider the pointer arithmetic carefully:
pptr essentially points to matrix_ptr[0];
on the first iteration, the double indirection means **pptr will set what you want, but then
*pptr += 1 will modify the contents of matrix_ptr[0], which means it no longer points to the beginning of the matrix.
Subsequent passes through the loop compound the situation drastically.
Modifying pptr won't help because it actually points to the wrong thing: it points to matrix_ptr, so incrementing it merely once moves its address from that of matrix_ptr[0], which points to rainMatrix[0][0], to that of matrix_ptr[1], which points to rainMatrix[1][0]. That is the wrong address for the next entry of the matrix, which is rainMatrix[0][1]. In essence, you've moved to the next row, instead of to the next column.
Try this for the innermost loop instead:
for (int i = 0; i < row; ++i)
{
auto qptr = *pptr;
for (int j = 0; j < col; ++j)
{
rv = rand() % 100;
*qptr = rv;
qptr += 1;
}
pptr++;
}
}
In this case, qptr is given the address of the first entry in the matrix. *qptr = rv sets the value. qptr += 1 increments the position of qptr while leaving *pptr alone - and, by extension, it leaves matrix_ptr[0] alone.

John Perry correctly identified the problem, but you have several option to deal with it. You are incorrectly incrementing *pptr += 1 Beyond using auto, you can simply index the pointer with the offset of j, e.g.
*(*pptr + j) = rv;
or
(*pptr)[j] = rv;
Either will work. Putting it together in your rainGen function, you could do:
void rainGen (int **pptr, int row, int col)
{
unsigned int seed = 43;
unsigned int rv;
srand(seed);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
rv = rand() % 100;
// *(*pptr + j) = rv; /* or */
(*pptr)[j] = rv;
}
pptr++;
}
}
(note: seed and srand(seed) should be moved to main() if there is the potential that rainGen could be called more than once -- srand should only be called once)
Example Use/Output
Both will produce the desired output:
$ ./bin/raingen
72 71 65 94 0 13 49 17 36 49 67 51
87 68 45 15 91 72 16 80 77 35 9 81
11 88 73 59 24 22 37 48 45 54 94 45
19 44 62 56 45 81 59 32 49 4 99 92
28 16 24 5 3 34 38 14 22 12 26 98
72 72
87 87
11 11
19 19
28 28

You are modifying the pointers in the pointer-array matrix_ptr within your rainGen function, so that all of them point past the end and further accesses go to "random" memory locations, which is undefined behavior. Tools like valgrind can find such errors.

Related

How to do a specific double "for" loop to do a calcul

I would like to be able to do a loop that be able to make a count like this :
00 01 02 03 04
10 11 12 13 14
20 12 22 23 24
30 31 32 33 34
40 41 42 43 44
The way they are wrote is not important, I just want to be able do a count from 0 to 4 on the right number, then it do a + to the left number, and again 0 to 4
And here is what I've done
for (i; i <= TAILLE - 1; i++) {
for (int i2=0; i2 <= TAILLE - 1; i2++) {
//tableau[x][y] = false;
cout << x << y << endl;
y = i2;
}
x = i;
}
TAILLE = 5
x=0
y=0
i=0
i2=0
x is the left number
y the right number
This should do the trick:
for (int i = 0; i < TAILLE; i++) {
for (int j=0; j <TAILLE; j++) {
cout << i << j << ' ';
}
cout << endl;
}
some notes on this code:
1.- Instead of i<=TAILLE -1 use i<TAILLE it is shorter and easier to read. Also it is more computationally efficient since you avoid the subtraction, this is very subtle, but it's good to note this kind of detail, since in large datasets this could mean saving thousands or millions of calculations.
2.- Use i, j, k instead of i, i2, i3, this is not mandatory, but is kind of the standard and makes it easier to read as well.
3.- The variables x and y are not necessary, you can use directly i and j

Can't change a vector's element value at index i

In Stroustrup's Programming: Principles and Practice Using C++, chapter 4, exercise 13, I have to write a program to find all the prime numbers in a given range using the Sieve of Erathostenes.
So far, I have come up with this:
vector<int> values;
void initialize_values()
{
for (int i{0}; i < 100; ++i)
values.push_back(1);
}
void remove_composites(vector<int> values)
{
for(int i{2}; i * i < values.size(); ++i)
{
if (values[i] == 1)
{
for (int p{i + i}; p < values.size(); p += i)
values[p] = 0; //not working
}
}
}
int main()
{
initialize_values();
remove_composites(values);
for (int i{2}; i < values.size(); ++i)
{
if (values[i] == 1)
cout << i << " ";
}
cout << '\n';
return 0;
}
I create a vector with size 100 (in this first case) and initialize elements to 1. Then I check all indexes multiples of i while i * i < 100 and change the value at those indexes to 0 and finally print the indexes whose value is 1.
The problem is that values[p] = 0 is not assigning the value 0 to the element at index p and I don't really understad why.
EDIT So after reading comments and answers I decided to move all code under main(), because I don't know how to use references.
The goal of this exercises, according to the book, is to get used to processing user input, working with loops, iterations, etc. It's not intended to be professional nor expert at this point.
To all people with many years coding and answering questions here, remember you were once learners and beginners. Have some respect and don't turn this community into a toxic one.
Updated code:
int main()
{
vector<int> values;
for (int i{0}; i < 100; ++i)
values.push_back(1);
for(int i{2}; i * i < values.size(); ++i)
{
if (values[i] == 1)
{
for (int p{i + i}; p < values.size(); p += i)
{
//cout << p << " ";
values[p] = 0;
}
//cout << '\n';
}
}
for (int i{2}; i < values.size(); ++i)
{
if (values[i] == 1)
cout << i << " ";
}
cout << '\n';
return 0;
}
And works as expected:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Thanks everyone.
The problem is that values[p] = 0 is not assigning the value 0 to the element at index p
It is assigning it.
The problem is that you are operating on a copy of the original vector, and that copy is local to remove_composites, which is why the calling code doesn’t see the changes.
Change your function signature to use a reference type parameter: std::vector<int>&.
There are also some other issues with your code (using the wrong type, i.e. int instead of bool; inconsistent signatures; mutable global variables).

how to check a matrix for duplicate numbers C++

I'm trying to generate a 5x20 matrix filled with random numbers. How can I make sure none of the random numbers are duplicates? This is the code I have for filling the matrix with random numbers.
srand(time(0));
int matrix[5][20];
int i = 0;
int j = 0;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
the code works but there are sometimes duplicates. If this were an array I could make use of a simple for loop and compare all of the elements in the array. but I have no idea how to do so with a matrix. I have searched everywhere but cant seem to find a solution.
It's not quite fit your question title but I think you should take a look.
for (i = 0; i < 5; i++)
{
for (j = 0; j < 20; j++)
{
matrix[i][j] = 1 + (rand() % 100);
cout << matrix[i][j] <<"_";
}
cout << endl;
}
I don't know the 5x20 and 100 (in rand() % 100) is compulsory or just an example you want to give. So I suggest for all case I can consider:
Let call the number of matrix elements is a, the number of set (contains all possible generated number) is b. In your is example, a is 5x20=100 and b is 100 (from 1 to 100).
a > b: no valid matrix without duplicates since Dirichlet principle
a == b: take a look at http://en.cppreference.com/w/cpp/algorithm/random_shuffle. Just create an 1-dimension array containing consecutive number from 0 to b-1 (or from min and max of your range) and permute them. Then use it to fill in the matrix.
a < b: similar to case a==b, but you just take a part of the permutation.
Of course, when a =< b then you can use rand() but you have to check duplicate and retry rand(), which is quite complicated. You can create a mark array (which cost memory) or iterate through your matrix again (which cost time).
as a heads up, you shouldn't use rand() unless you've got explicit reasons to (such as a professor's requirements).
The following approach uses a GetIndex function to simulate an int[5][20] with an int[100]. See if you can figure out how to use the code I wrote to create an int[5][20].
Your code fills the matrix with random numbers between 1 and 100 (1 + (rand() % 100)) inclusively, but you do no work to ensure you don't get duplicates! So you won't be able to guarantee that you don't get duplicates (in fact, it's very unusual for you to get no duplicates).
If you first initialize all your values to 1,...,100 and then later shuffle them, you know you have no duplicates.
#include <iostream>
#include <iomanip>
#include <random>
#include <algorithm>
constexpr size_t kDefaultMatrixHeight = 20;
constexpr size_t kDefaultMatrixWidth = 5;
constexpr size_t GetIndex(size_t i, size_t j) {
return i * kDefaultMatrixWidth + j;
}
int main() {
int matrix[kDefaultMatrixWidth * kDefaultMatrixHeight];
for (size_t i = 0 ; i < kDefaultMatrixHeight * kDefaultMatrixWidth ; i++) {
matrix[i] = i + 1;
}
std::mt19937 rng(std::random_device{}());
std::shuffle(std::begin(matrix), std::end(matrix), rng);
for (size_t i = 0 ; i < kDefaultMatrixHeight ; i++) {
for (size_t j = 0; j < kDefaultMatrixWidth ; j++) {
std::cout << std::setw(4) << matrix[GetIndex(i,j)];
}
std::cout << '\n';
}
}
And for example output:
Test#Test:/tmp/example$ g++ example.cpp && ./a.out
93 28 70 14 39
83 3 80 95 58
42 69 71 16 49
75 63 41 82 46
26 50 81 33 97
65 10 77 68 12
8 19 30 86 37
57 24 78 31 88
2 90 4 13 56
36 15 35 32 85
29 76 99 45 18
54 11 44 62 98
9 96 79 34 27
40 21 52 22 55
72 1 47 92 59
94 7 64 91 53
74 5 61 100 89
48 23 66 67 51
38 6 87 17 20
60 25 84 43 73
not exactly answer your question but for your purpose you can try something like this:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
srand(time(0));
int matrix[5][20];
int *pmatrix = &matrix[0][0];
int i = 0;
for (i = 0; i < 100; i++)
{
pmatrix[i] = i+1;
}
std::random_shuffle(pmatrix, pmatrix+100);
for (i = 0; i < 100; i++)
{
std::cout<<pmatrix[i]<<",";
}
}
cpp.sh/5bnyt
Update fixed memory out of bounds problem.

Modifing Arrays without using <algorithm> functions in C++? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So first, we start with an array of 50. The range of the values within the array can be 1-100, not repeating. Then we display the highest value of that random array. Then we display the lowest value in the array. Then comes the sorting, which would be easy using the standard library functions in the <algorithm> header, but since it's not allowed, we need to find another way around it. Then sort from high to low.
So, to display this easily... First we start with an array[50] with random numbers between 1-100
72 29 11 41 31 27 21 46 43 40 17 45 30 32 25 15 19 88 22 24 51 34 99 23 26 37 1 4 2 9 33 44 12 39 38 3 47 48 5 42 49 18 54 55 87 16 28 20 50 9
Now we display the highest number
99
Then the lowest
1
The we sort them
1 2 3 4 5 9 9 11 12 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 54 55 72 87 88 99
Then reverse sort them
99 88 87 72 55 54 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 12 11 9 9 5 4 3 2 1
So.. how would I go about doing this without algorithms?
The usual way to do this is by using loops.
For example, to traverse an array, printing every element, we could use a loop like:
for (int i=0; i<50; i++) {
std::cout << array[i] << std::endl;
}
All of the problems you mention, except sorting, can be done using a simple loop like the one above. You'll have to do your own bookkeeping in order to solve the problems, but it shouldn't be too difficult.
As for sorting, that's a more challenging problem. You might start with the wikipedia article to see how that is handled. You probably want to try implementing selection sort.
You can use bitset sort since the range of values of the array is limited to 1-100, and there is no repetition you can have a bitset array of 100 ints where each index specifies can be a 0 (that number isn't in the array) or a 1 (the number is in the array). For example the array [1, 5, 3] can be represented by the bitset array [1, 0, 1, 0, 1].
pseudo code:
MAX_SIZE = 100
bitset = new int[MAX_SIZE]
smallest = biggest = -1
for each value in array {
smallest = value if value < smallest
biggest = value if value > biggest
bitset[value-1] = 1
}
sorted = (i for i in 0..bitset.length - 1 if bitset[i] == 1)
reverse_sorted = (sorted[i] for i in sorted.length-1..0)
Not very professional but works
int array[50], used[50], sortedArray[50], buildSort = 1, genNum, max = 0, min = 101;
bool x;
srand(time(0));
//Array Generator
for(int i = 0; i < 50; i++){
do{
genNum = (1+rand()%100);
x = false;
for(int j =0; j < 50; j++){
if(genNum == used[j]){
x = true;
}
}
}while(x == true);
used[i] = genNum;
array[i] = genNum;
}
cout << "Numbers: ";
for(int d = 0; d < 50; d++){
cout << array[d] << " ";
}
cout << endl << endl;
//Max and Min finder
for(int m = 0; m < 50; m++){
if(array[m] > max){
max = array[m];
}
if(array[m] < min){
min = array[m];
}
}
cout << "Max is: " << max << endl;
cout << "Min is: " << min << endl << endl;
//Sorting
sortedArray[0] = min;
for(int v = min+1; v <= max; v++){
for(int r = 0; r < 50; r++){
if(array[r] == v){
sortedArray[buildSort] = array[r];
buildSort++;
}
}
}
cout << "Sorted: ";
for(int k = 0; k < 50; k++){
cout << sortedArray[k] << " ";
}
cout << endl << endl;
cout << "Reverse sorting: ";
for(int l = 49; l >=0; l--){
cout << sortedArray[l] << " ";
}
Well, I have not checked this code and I'm sure it has some errors in it, but hopefully this will at least give you some ideas and a good base to go off of:
/******************
*
* Your array should have 51 spots.
* The last element should be 0.
*
******************/
uint8_t findMax(uint8_t *arrayToSearch){
// Your array should end in a sentinel value of 0
uint8_t highest = 0;
for(; *arrayToSearch; arrayToSearch++){
highest = (*arrayToSearch > highest) ? *arrayToSearch : highest;
}
return highest;
}
uint8_t findMin(uint8_t *arrayToSearch){
// Your array should end in a sentinel value of 0
uint8_t lowest = 101;
for(; *arrayToSearch; arrayToSearch++){
lowest = (*arrayToSearch < lowest) ? *arrayToSearch : lowest;
}
return lowest;
}
void sortAscending(uint8_t *arrayToSearch){
// sort from low to high
// get count of array (According to your question, it should be 50, but we'll verify)
unsigned short count = 0;
uint8_t *countingPoint;
countingPoint = arrayToSeach; // make countingPoint point to the first element
while(*countingPoint){
count++;
countingPoint++;
}
// now we'll create a second array
uint8_t sortedArray[count];
// now let's begin sorting.
unsigned long int totalIterations = 0;
while(totalIterations < count){
uint8_t currentSmallest = 101; // value which will not ever exist.
signed long int smallestIndex = -1;
unsigned short offset = 0;
uint8_t *startOfArray;
startOfArray = arrayToSearch;
for(; *startOfArray; *startOfArray++, offset++){
if(currentSmallest > *startOfArray){
smallestIndex = offset;
currentSmallest = *startOfArray;
}
} /* end for */
sortedArray[totalIterations] = currentSmallest;
*(smallestIndex + arrayToSearch) = 101; /* set the value above 100 so it will be
skipped in the next for loop */
totalIterations++;
} /* end while */
/* now we'll the sorted values to the array to search */
int i;
for(i=0; i < count; i++){
*(i+arrayToSearch) = sortedArray[i];
}
// and we're done.
}
/*
* We can actually write sortDescending the same way and just modify
* the last loop to put them in reverse order
*/
void sortDescending(uint8_t *arrayToSearch){
// sort from low to high and then order as high to low
// get count of array (According to your question, it should be 50, but we'll verify)
unsigned short count = 0;
uint8_t *countingPoint;
countingPoint = arrayToSeach; // make countingPoint point to the first element
while(*countingPoint){
count++;
countingPoint++;
}
// now we'll create a second array
uint8_t sortedArray[count];
// now let's begin sorting.
unsigned long int totalIterations = 0;
while(totalIterations < count){
uint8_t currentSmallest = 101; // value which will not ever exist.
signed long int smallestIndex = -1;
unsigned short offset = 0;
uint8_t *startOfArray;
startOfArray = arrayToSearch;
for(; *startOfArray; *startOfArray++, offset++){
if(currentSmallest > *startOfArray){
smallestIndex = offset;
currentSmallest = *startOfArray;
}
} /* end for */
sortedArray[totalIterations] = currentSmallest;
*(smallestIndex + arrayToSearch) = 101; /* set the value above 100 so it will be
skipped in the next for loop */
totalIterations++;
} /* end while */
/* now we'll copy the values to the arrayToSearch in reverse order */
int i;
for(i=(count-1); i >= 0; i--){
*(i+arrayToSearch) = sortedArray[i];
}
// and we're done.
}
/* calling these */
int main(){
uint8_t yourArray[51];
// ... your code to populate this array
yourArray[50] = 0; // set the last spot to 0.
uint8_t highest = findMax(yourArray);
uint8_t lowest = findMin(yourArray);
// now make yourArray sorted by lowest to highest
sortAscending(yourArray);
// ... Whatever you need to do with it in ascending order.
// now make it sorted by highest to lowest
sortDescending(yourArray);
// ... Whatever you need to do with it in descending order.
return 0;
}
I'm a C-programmer so this is a rather C-style answer.
Some additional information that might be helpful can be found at:
http://www.sanfoundry.com/c-program-sort-array-ascending-order/
http://www.programmingsimplified.com/c/source-code/c-program-bubble-sort
http://en.wikipedia.org/wiki/Sorting_algorithm
The Wikipedia page (last link) might seem a little overwhelming, but there is a lot of great content on it.
I hope this will be of some help to you. Again, I'm not sure if the code I included will work properly. It's merely meant to convey the general idea.

C++ - Accessing values in dynamic arrays

I have an assignment that requires the following:
-Take command line input for rows and columns and dynamically create a 2-D array filled with random numbers
-Create a function called find_greatest_product to find the largest product of four adjacent
numbers in the array. The four adjacent numbers can be any configuration of the shapes
found in the game Tetris in the array. Your function needs to return the max product, starting
position, shape, and direction of the four numbers using a struct.
Yes, it's a totally useless program purely to practice 2-D arrays.
I've got my array set up so I started with the easiest shape: the box. However, when I try to access the array full of random numbers, the product and factors all seem to be 0. Any hints as to why I'm unable to access the ints within the array of random numbers to find the product? The relevant bits of code are below. You can assume all functions not copied here work fine.
struct shape {
int highest;
int factors[4];
int startRow;
int startColumn;
} tShape, sShape, iShape, boxShape;
int main(int argc, char* argv[]) {
if(argc == 5) {
for(int i = 1; i < argc; i++) {
rows = getArg(argc, argv, i, compare1);
}
for(int i = 1; i < argc; i++) {
columns = getArg(argc, argv, i, compare2);
}
}
int ** array = new int*[rows];
int i, j;
for (i = 0; i < rows; i++) {
array[i] = new int[columns];
}
create_array(array, rows, columns);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
cout << array[i][j];
cout << " ";
}
cout << endl;
}
boxProduct(array, rows, columns, boxShape);
cout << boxShape.highest << endl;
for (int i = 0; i < 4; i++) {
cout << boxShape.factors[i];
cout << " ";
}
cout << endl;
return 0;
}
void boxProduct(int *array[], int rows, int columns, shape boxShape) {
int highest = 0;
int product = 0;
for (int i = 0; i < rows - 1; i++) {
for (int j = 0; j < columns - 1; j++) {
product = (array[i][j]*array[i][j+1]*array[i+1][j]*array[i+1][j+1]);
if (product > highest) {
boxShape.highest = product;
boxShape.factors[0] = array[i][j];
boxShape.factors[1] = array[i][j+1];
boxShape.factors[2] = array[i+1][j];
boxShape.factors[3] = array[i+1][j+1];
}
}
}
}
Here is a sample output with a matrix 10 rows x 5 columns:
27 86 4 41 44
17 6 5 40 32
42 58 14 95 53
8 28 95 27 91
63 22 27 49 2
38 37 39 37 76
9 17 14 13 10
10 30 16 67 22
49 10 33 63 5
86 71 86 34 50
0 <- product
0 0 0 0 <- the four factors
C and C++ functions are call by value by default, not call by reference. That is, the compiler makes copies of the arguments to give to functions, and if the function modifies its arguments, it modifies a copy.
Consider this example:
void foo( int x )
{
x++; // increments foo's own local copy of 'x'
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(i);
cout << i << endl; // ALSO prints 42!
return 0;
}
This will print 42 twice, because foo modifies a copy.
If you modify the code slightly, you tell the C++ compiler to pass the argument by reference. (Note: This is a C++ only feature; it does not work in C.) Now, any modification to the argument inside the function will modify the value the caller sees also:
void foo( int& x ) // The & means "pass this parameter by reference"
{
x++;
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(i);
cout << i << endl; // prints 43
return 0;
}
An alternate way to modify a value held by the caller is to pass a pointer to that value, rather than the value itself. This is still call by value, but in this case the value you pass the function is a pointer. Example:
void foo( int* x ) // x is now a pointer to integer
{
(*x)++; // The (*x) dereferences the pointer. What happens if you leave off the parens?
}
int main()
{
i = 42;
cout << i << endl; // prints 42
foo(&i); // the & there takes the address of 'i' and passes that to foo()
cout << i << endl; // prints 43
return 0;
}
Because C does not support call-by-reference arguments, it requires this last scheme. Some C++ code also uses pointers in this way. Modern C++ style tends to avoid bare pointers wherever possible, but you'll still see pointers from time to time.
Punchline: You'll want to apply this knowledge to your shape boxShape structure above. You either want to pass shape boxShape by reference, or pass a pointer to shape boxShape. Both are valid approaches, although C++ tends to prefer passing a reference.