Examining multidimensional array passed to a function in gdb - c
I have written code for dynamic programming, matrix chain multiplication algorithm. For this question, I am not concerned with the implementation details of algorithm.
I am trying to debug it using gdb. However, I am having a hard time examining cost_table 2-D array inside matrix_chain_order function.
Inside matrix_chain_order function, I set a breakpoint and examine the cost_table 2-D array. I have also used printf statements there.
The printf statements print the correct value of a cell in cost_table.
I found some revelant information in this SO QA: how to print 2d arry values in gdb.
I did not understand what the answer really explained. But it gave me a direction, so I tried printing cost_table and its cell values in gdb. (Session below)
Code:
/* MATRIX-CHAIN-MULTIPLICATION - CLRS 3rd Edition, Chapter 15 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define array_length(arr) (sizeof(arr) == 0 ? 0 : sizeof(arr) / sizeof((arr)[0]));
/* define input sequence to matrix_chain_order function */
const int INPUT_SEQUENCE[] = {4, 10, 3, 12, 20};
/* DEFINE m[i, j]:
* Let m[i, j] be the minimum number of scalar multiplications needed to compute
* matrix A_suffix_i..j; for the full problem, the lowest cost way to compute A_suffix_1..n
* would thus be m[1, n].
*/
/* The function computes the rows from bottom to top and from left to right within
* each row.
* It computes each entry m[i, j] using products p_suffix_i-1 * p_suffix_k * p_suffix_j
* for k = i, i + 1, ...., j - 1 and all entries southwest and southeast from m[i, j].
*
* This prodedure assumes that matrix A_suffix_i has dimensions p_suffix_i-1 * p_suffix_i
* for i = 1, 2, ...., n.
* Its input is a sequence p = <p_suffix_0, p_suffix_1, ...., p_suffix_n>, where
* p.length = n + 1.
*
* The procedure uses an auxiliary table m[1 ..n, 1 ..n] for storing the m[i, j] costs,
* and another auxiliary table s[1 ..n - 1, 2 ..] that records which index of k achieved
* the optimal cost in computing m[i, j].
*/
void matrix_chain_order (int ct_rows, int ct_cols, int cost_table[ct_rows][ct_cols], int kit_rows, int kit_cols, int k_idx_table[kit_rows][kit_cols]);
int main ()
{
int sequence_len = array_length(INPUT_SEQUENCE);
/* initialize table (2-D array), m[1 ..n, 1..n] */
int m = 0, n = 0;
int cost_table[sequence_len][sequence_len];
for (m = 0; m < sequence_len; m++) {
for (n = 0; n < sequence_len; n++) {
/* m[i, i] = 0, for i = 1, 2, ...., n (the minimum costs for chains of length 1) */
if (n == m) {
cost_table[m][n] = 0;
} else {
cost_table[m][n] = INT_MAX;
}
}
}
/* initialize table (2-D array), s[1 ..n - 1, 2..n] */
int o = 0, p = 0;
int k_idx_table[sequence_len - 1][sequence_len - 1];
for (o = 0; o < sequence_len - 1; o++) {
for (p = 0; p < sequence_len - 1; p++) {
k_idx_table[o][p] = -1;
}
}
matrix_chain_order(sequence_len, sequence_len, cost_table, sequence_len, sequence_len - 1, k_idx_table);
return 0;
}
/* NOTE on array passed to the function. */
/* When you pass an array to a function, it decays into a pointer to the first element,
* at which point knowledge of its size is lost. You need to work it out before decay
* and pass that information with the array.
*/
void matrix_chain_order(int ct_rows, int ct_cols, int cost_table[ct_rows][ct_cols], int kit_rows, int kit_cols, int k_idx_table[kit_rows][kit_cols])
{
int sequence_len = array_length(INPUT_SEQUENCE);
/* use recurrence,
*
* min[i, j] = 0 , if i = j
* min[i, j] = min {m[i, k] + m[k + 1, j] + p_suffix_i-1 * p_suffix_k * p_suffix_j , if i < j
*
* to compute m[i, i + 1] for i = 1, 2, ...., n - 1 (the minimum costs of chains of length l = 2)
* during the first execution of the for loop.
* The second time through the loop, it computes m[i, i + 2] for i = 1, 2, ...., n - 2
* (the minimum costs for chains of length l = 3), and so forth.
*/
int chain_len = 0, i = 1, j = 0, k = 0, cost = INT_MAX;
for (chain_len = 2; chain_len <= sequence_len; chain_len++) {
for (i = 1; i <= sequence_len - chain_len + 1; i++) {
j = i + chain_len - 1;
for (k = i; k <= j - 1; k++) {
/* at each step, the m[i, j] cost computed depends only on table entries m[i, k] and m[k + 1, j]
* already computed
*/
printf("Printed cost_table[%d][%d] : %d\n", i, k, cost_table[i][k]);
printf("Printed cost_table[%d][%d] : %d\n", (k+1), j, cost_table[k+1][j]);
cost = cost_table[i][k] + cost_table[k + 1][j] + INPUT_SEQUENCE[i - 1] * INPUT_SEQUENCE[k] * INPUT_SEQUENCE[j];
if (cost < cost_table[i][j]) {
cost_table[i][j] = cost;
k_idx_table[i][j] = k;
}
}
}
}
}
gdb session:
(gdb) p ((int (*) [5][5]) cost_table)[1][1]
$3 = {0, 0, 65280, 0, -8944}
(gdb) p (int [][5]) *cost_table
$4 = 0x7fffffffdca0
(gdb) p (int [5][5]) *cost_table
Invalid cast.
(gdb) p (int [][5]) **cost_table
warning: array element type size does not divide object size in cast
$5 = 0x7fffffffdca0
(gdb) p (int [][5]) *cost_table
$6 = 0x7fffffffdca0
(gdb) p (int [][5]) cost_table
warning: array element type size does not divide object size in cast
$7 = 0x7fffffffdbe0
(gdb) p cost_table#5#5
$16 = {{0x7fffffffdca0, 0x500000005, 0x26, 0x100000002, 0x500000001}, {0x7fffffff00000002, 0x4, 0x3, 0x1f7ffe728, 0x7fffffffdca0}, {0x0, 0x5, 0x7fffffffddf0, 0x400952 <main+892>, 0xffffffffffffffff}, {
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x7fffffffde10, 0x7fffffff00000000}}
(gdb) p *cost_table#5#5
$17 = {{{0, 2147483647, 2147483647, 2147483647, 2147483647}, {2147483647, 0, 2147483647, 2147483647, 2147483647}, {2147483647, 2147483647, 0, 2147483647, 2147483647}, {2147483647, 2147483647,
2147483647, 0, 2147483647}, {2147483647, 2147483647, 2147483647, 2147483647, 0}}, {{0, -140389360, 32767, 4, 0}, {0, 0, 65280, 0, -8944}, {32767, 4, 0, 0, 0}, {4, 0, 0, 0, 4}, {0, 0, 0, 4, 0}}, {{
0, 0, 0, 5, 5}, {4, 4, 5, 4, 0}, {4, 0, -9056, 32767, 3}, {0, 3, 0, -9136, 32767}, {1781326592, 1051810453, 0, 0, 0}}, {{0, 4195552, 0, -8496, 32767}, {0, 0, 0, 0, 4197632}, {0, -140322768, 32767,
0, 0}, {-8488, 32767, 0, 1, 4195798}, {0, 0, 0, 1661416990, 1731120}}, {{4195552, 0, -8496, 32767, 0}, {0, 0, 0, -989383138, -1731249}, {-690538978, -1735179, 0, 0, 0}, {0, 0, 0, 1, 0}, {4195798,
0, 4197744, 0, 0}}}
(gdb) p **cost_table#5#5
$18 = {{0, 2147483647, 2147483647, 2147483647, 2147483647}, {2147483647, 0, 2147483647, 2147483647, 2147483647}, {2147483647, 2147483647, 0, 2147483647, 2147483647}, {2147483647, 2147483647, 2147483647,
0, 2147483647}, {2147483647, 2147483647, 2147483647, 2147483647, 0}}
(gdb) p cost_table[i][k]
Cannot perform pointer math on incomplete types, try casting to a known type, or void *.
I don't get how the commands that I have used in gdb session result in their respective outputs.
Why am I unable to use p cost_table[i][k] directly in gdb,
whereas the printf statements print the result in execution of
code?
p ((int (*) [5][5]) cost_table)[1][1]: What happens if I change
value of numbers in this command or if I do something like
p ((int(*) [][5]) cost_table)[1][1]?
Why is the output of p *cost_table#5#5 and p **cost_table#5#5 so
different?
My requirement is to be able to examine the cost_table and its cells in gdb.
Any other suggestions is welcomed.
Just ask gbd for it :)
Breakpoint 2, matrix_chain_order (ct_rows=5, ct_cols=5, cost_table=0x7fffffffdac0, kit_rows=5, kit_cols=4, k_idx_table=0x7fffffffda80) at delme.c:96
96 printf("Printed cost_table[%d][%d] : %d\n", (k+1), j, cost_table[k+1][j]);
(gdb) ptype cost_table
type = int (*)[5]
(gdb) p ((int (*) [5])cost_table)[i][j]
$12 = 2147483647
You may also go up one frame ('up' in gdb) and print directly cost_table[idx1][idx2] but it is probably less user friendly to debug in the loop...
the type gdb gives (int(*)[5]) stand for pointer to array 5 of int (see
https://cdecl.org/?q=int+%28*t%29%5B5%5D if you want to experience the syntax.)
The array type decays that's why only a pointer remains; you may have a look to Manipulate multidimensional array in a function for more explanation in C.
Related
Why am I getting: Floating point exception (core dumped)
#include <cs50.h> #include <stdio.h> #include <string.h> // Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together. // Add the sum to the sum of the digits that weren’t multiplied by 2. // If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid! // 4003600000000014 - VISA TEST // 123456789 int length(long n); int main(void) { long ccnumber = get_long_long("Number: "); long x = 10; //Gets the 2nd digit. long y = 1; //gets the first. long sum1 = 0; //Holds the doubled sum. long sum2 = 0; //Holds the undoubled sum. int n = 8; while (n > 0) { long cc1 = ccnumber / y; cc1 = cc1 % 10; long cc2 = ccnumber / x; cc2 = cc2 % 10; y = y * 100; x = x * 100; // Times CC2 by 2. cc2 = cc2 * 2; // Check if double digit then mine by 9, as to add the two digits together. if (cc2 / 10 != 0) { cc2 = cc2 - 9; } sum1 = sum1 + cc2; sum2 = sum2 + cc1; } } I have tried checking if it is 0 before dividing by 10. I have tried some other checks with the cc1 and cc2 but cant work it out. I am doing the CS50 course and tring to do the Credit problem set, This is the best I have done so far but it is suddenly throwing this error since trying to do the next step of checking if the total %10 == 0.
The problem is really the infinite loop. But that, by itself, doesn't result in the core dump. What happens is best illustrated by adding a print statement at the bottom of the loop to display the values of a few variables: #include <cs50.h> #include <stdio.h> #include <string.h> // Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together. // Add the sum to the sum of the digits that weren’t multiplied by 2. // If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid! // 4003600000000014 - VISA TEST // 123456789 int length(long n); int main(void) { long ccnumber = get_long_long("Number: "); long x = 10; //Gets the 2nd digit. long y = 1; //gets the first. long sum1 = 0; //Holds the doubled sum. long sum2 = 0; //Holds the undoubled sum. int n = 8; while (n > 0) { long cc1 = ccnumber / y; cc1 = cc1 % 10; long cc2 = ccnumber / x; cc2 = cc2 % 10; y = y * 100; x = x * 100; // Times CC2 by 2. cc2 = cc2 * 2; // Check if double digit then mine by 9, as to add the two digits together. if (cc2 / 10 != 0) { cc2 = cc2 - 9; } sum1 = sum1 + cc2; sum2 = sum2 + cc1; printf("%d, %ld, %ld, %ld, %ld\n",n,cc2,cc1,x,y); } } What you'll see is that x and y are eventually overloaded and reset to 0, which will cause division by 0 with associated fp error and core dump. $ ./a.out Number: 5 8, 0, 5, 1000, 100 8, 0, 0, 100000, 10000 8, 0, 0, 10000000, 1000000 8, 0, 0, 1000000000, 100000000 8, 0, 0, 100000000000, 10000000000 8, 0, 0, 10000000000000, 1000000000000 8, 0, 0, 1000000000000000, 100000000000000 8, 0, 0, 100000000000000000, 10000000000000000 8, 0, 0, -8446744073709551616, 1000000000000000000 8, 0, 0, 3875820019684212736, 7766279631452241920 8, 0, 0, 200376420520689664, 1864712049423024128 8, 0, 0, 1590897978359414784, 2003764205206896640 8, 0, 0, -6930898827444486144, -2537764290115403776 8, 0, 0, 7886392056514347008, 4477988020393345024 8, 0, 0, -4570789518076018688, 5076944270305263616 8, 0, 0, 4089650035136921600, -8814407033341083648 8, 0, 0, 3136633892082024448, 4003012203950112768 8, 0, 0, 68739955140067328, -5527149226598858752 8, 0, 0, 6873995514006732800, 687399551400673280 8, 0, 0, 4870020673419870208, -5047021154770878464 8, 0, 0, 7386721425538678784, -6640025486929952768 8, 0, 0, 802379605485813760, 80237960548581376 8, 0, 0, 6450984253743169536, 8023796054858137600 8, 0, 0, -537617205517352960, 9169610316303040512 8, 0, 0, 1578511669393358848, -5376172055173529600 8, 0, 0, -8169529724050079744, -2661627379775963136 8, 0, 0, -5296233161787703296, -7908320945662590976 8, 0, 0, 5332261958806667264, 2377900603251621888 8, 0, 0, -1729382256910270464, -2017612633061982208 8, 0, 0, -6917529027641081856, 1152921504606846976 8, 0, 0, -9223372036854775808, 4611686018427387904 8, 0, 0, 0, 0 Floating point exception (core dumped)
checking array for values and then passing to new array. c
So given an array of: input[3] = {0, 0, 0} this outputs : output[3] = {3, 0 ,0} code: void create_hist(double input[], int num_of_inputs, int output[]) { int num_to_check = input[0]; int counter = 0; for (int i = 0; i < num_of_inputs; i++) { int j = output[i]; if ((int)input[i] == num_to_check) { counter++; /* it was found */ } output[j] = counter; } return; } but if I have a floating point array input[5] = {0.0000, 1.0000, 2.0000, 3.0000, 4.000} and I want to truncate the values to int, and count how many times each integer in the range 0 - 10 appears in the input array then output it to: output[5] = {1, 1, 1, 1, 1} output[0] = {1} //indicates how many times 0 appeared in the array or input[10] = {1.000, 4.000, 5.0000, 2.000, 4.000, 7.000, 9.000, 6.000, 0.000, 0.000} and output output[10] = {2, 1, 1, 0, 2, 1, 1, 1, 0, 1} output[0] = {2} // this indicates how many times 0 appeared in the first array Can anyone tell me how to do this?
You shouldn't use output[i] as an array index. It's a counter, not the value whose count you want. You should use (int)input[i] as the index. You first need to initialize all elements of output to 0, then you increment the elements corresponding to the integer part of each input. memset(output, 0, sizeof(output[0]) * MAX_INPUT_VALUE); for (int i = 0; i < num_of_inputs; i++) { output[(int)input[i]]++; }
2D rotation of rectangular array in C
I was experimenting around with 2d array manipulation in c. in-place rotation of a 2d shape in particular, so i did my research and came up with : #include <stdio.h> #include <stdlib.h> #include <math.h> #define RAD(x) ((x) * 3.14 / 180) char shape[3][3] = {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}; char nf[5][5]= {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; char expa[5][5]= {{0, 0, 1, 0, 0}, {0, 1, 0, 1, 0}, {1, 0, 0, 0, 1}, {0, 1, 0, 1, 0}, {0, 0, 1, 0, 0}}; void print(int row, int col, char shapein[][col]) { for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { printf("%c", ((shapein[i][j]) == 1) ? '#' : ' '); } printf("\n"); } } void main() { int nw = 5; int nh = 5; int xf = nw / 2; int yf = nh / 2; float angle = RAD(90); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { int nx = ((i - xf) * cos(angle) - (j - yf) * sin(angle)) + xf; int ny = ((i - xf) * sin(angle) + (j - yf) * cos(angle)) + yf; nf[nx][ny] = shape[i][j]; } } print(5, 5, nf); } i was expecting to get output like this : however what i get is : i did what i understood from my research: - rotations do happen at origin (assuming top left corner) - moved coords so that it is in origin scale. - used output array's dimension as space when rotating. I am stumped, i need a little help. while at it, as you can see from my code, i hard coded the new rotated dimensions, however, it would be nice if somebody could guide me how to calculate new rotated dimensions dynamically,without using the "maximum of corners" method.
The expected result you show looks like shape rotated by 45º, but you set the angle to 90º. You are working with integer coordinates but using floating-point functions. The sin and cos routines necessarily return approximations, and, when floating-point values are converted to integers, they are truncated. You may prefer rounding, perhaps using the round function. xf and yf appear to be set to the center of the image using nw / 2 and nh / 2, but they are integers, so the result, 2 in each case, is a considerable distance from the actual center, 2.5. There are likely additional errors, but you should fix those and continue working. Also, take steps to debug your code. Inside the loop, print each value of xf, yf, nx, and ny so you can see the inputs and outputs of the calculations. Check them manually to see if they are right or not. If they are not right, examine the individual calculations to see what they are doing.
Moving average in static array in C
I have an array of 10 elements, and I need to make that array into its moving average equivalent. Using 3 elements each time (eg average of elements at indices 0-2, then 1-3 and so on up to indices from 10 then back to 0 and 1 to make the new array have exactly 10 elements as well). What is the best approach to this without using pointers to wrap the array around (ring buffer).
Just do some bounds checking and wrap the index in code. The example code below can be made more efficient, but it's written like this for clarity (sort of). Also there may be some minor mistake since I'm typing into StackOverflow rather than compiling it. int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int averages[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; for (int i = 0; i < 10; i++) { int a = i; int b = i + 1 > 9 ? i - 10 + 1; int c = i + 2 > 9 ? i - 10 + 2; int count = array[a] + array[b] + array[c]; int average = count / 3; // note this will truncate any decimal part averages[i] = average; }
C check all neighbors of a element in a 2d array
I've been thinking if there is any smarter solution if I want to check all eight neighbors of an arbitrary element in a binary number only 2D array in C What I do is: Psudo Code: //return how many neighbor of an element at x,y equals 1. int neighbor(int** array, int x, int y) if x>WIDTH error if y>HIEGHT error if x==0 ignore west, nw, sw, and calculate the rest..... etc.. this is pretty dull, is there any smarter solution?
I used a similar approach to get Adjacent Mines for a particular cell in the Minesweeper Game. What I did, is I used an Array like this (MAX_NUMBER_OF_CELLS = 8) : int offset[MAX_NUMBER_OF_CELLS][2] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} }; Considering we are talking about the CELL at location 0, 0 in a matrix. We will simply add these offset values, to the CELL to check, if the adjacent CELL is a valid CELL (i.e. it falls within the matrix). If it is VALID, then we will see if it contains 1, if yes than increment sum by 1 else not. //rest of the values represent x and y that we are calculating (-1, -1) (-1, 0) (-1, 1) ------------------------- (0, -1) |(0, 0(This is i and j))| (0, 1) ------------------------- (1, -1) (1, 0) (1, 1) sum = 0; for (k = 0; k < MAX_NUMBER_OF_CELLS; k++) { indexX = i + offset[k][0]; indexY = j + offset[k][1]; if (isValidCell(indexX, indexY, model)) // Here check if new CELL is VALID // whether indexX >= 0 && indexX < rows // and indexY >= 0 && indexY < columns { flag = 1; if (arr[indexX][indexY] == 1)) sum += 1; } } EDIT 1 : Here is one working example (C is not my language, though still tried my hands on it to give you one idea :-)) : #include <stdio.h> #include <stdlib.h> int findAdjacent(int [4][4], int, int, int, int); int main(void) { int arr[4][4] = { {0, 1, 0, 0}, {1, 0, 1, 1}, {0, 1, 0, 0}, {0, 0, 0, 0} }; int i = 2, j = 2; int sum = findAdjacent(arr, i, j, 4, 4); printf("Adjacent cells from (%d, %d) with value 1 : %d\n", i, j, sum); return EXIT_SUCCESS; } int findAdjacent(int arr[4][4], int i, int j, int rows, int columns) { int sum = 0, k = 0; int x = -1, y = -1; // Location of the new CELL, which // we will find after adding offsets // to the present value of i and j int offset[8][2] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} }; for (k = 0; k < 8; k++) { x = i + offset[k][0]; y = j + offset[k][1]; if (isValidCell(x, y, rows, columns)) { if (arr[x][y] == 1) sum += 1; } } return sum; } int isValidCell(int x, int y, int rows, int columns) { if ((x >= 0 && x < rows) && (y >= 0 && y < columns)) return 1; return 0; }
One possible optimization, if you want to know the number of neighbors of cells a lot more than you want to change the cells, is to preprocess the number of neighbors for each cell and save the results in an another array. int** actualArray; // fill in with 0s and 1s int** numberOfNeighbors; // write a function to calculate the number of neighbors for cell x,y in actualArray and // store the result in numberOfNeighbors[x][y] preprocess(actualArray, numberOfNeighbors); // call this whenever actualArray changes // now you can get the number of neighbors of a cell in constant time // from numberOfNeighbors[x][y]
Are you trying to find the current position of the element in the array? If so, you can define a macro like: #define OFFSET(x,y) ((GridWidth*y)+x) Or, if you're trying to find which surrounding 'boxes' could contain an element (i.e which neighbors are 'in bounds')... for k = 0 while k < GridWidth for m = 0 while m < GridWidth if k < GridWidth toRight = true if m < GridWidth toDown = true if k > 1 toLeft = true if m > 1 toUp = true From there, combine the directions to get diagonals - if toRight && toUp, then toUpRight=true etc EDIT - I forgot to mention, this is if the grid is stored in a 1d array. For 2d, m would be for GridHeight