So the question is originated from Leetcode:
In a n * m two-dimensional array, each row is sorted in increasing order from left to right, and each column is sorted in increasing order from top to bottom. Please complete a function, input such a two-dimensional array and an integer, and determine whether the array contains the integer.
And my C solution is:
1 bool findNumberIn2DArray(int** matrix, int matrixSize, int* matrixColSize, int target){
2 //return matrixSize==5;
3 for(int i = 0; i < matrixSize; i++)
4 {
5 for (int j = 0; j < *matrixColSize; j++)
6 {
7 int num = matrix[i][j];
8 if (num == target) {return true;}
9 if (num > target) {break;}
10 }
11 }
12 return false;
13}
In row 5, It has to be *matrixColSize. If I remove the asterisk, the memory will overflow. From my perspective, the matrixColSize is an INT. Why can't I use the INT directly but have to use a pointer?
Maybe I didn't make my question clear. I know it's a pointer, and I know a pointer is totally different from an INT. My question is, why is this question using a pointer here to define the matrixColSize but not just using and INT? From my perspective, an INT is enough here to represent the size.
Can anybody tell me why please?
Because you define as a function parameter int* matrixColSize if you delete * in 5. line, you basically say that increase j till address of matrixColSize.
And it is very large number because an address like 0x88644278. So thats why I guess your memory overflows. If you want to just int you must change your function parameters to bool findNumberIn2DArray(int** matrix, int matrixSize, int matrixColSize, int target) and in 5. line you can write without an asterisk.
Related
I'm writing this code in C for some offline games but when I run this code, it says "runtime failure #2" and "stack around the variable has corrupted". I searched the internet and saw some answers but I think there's nothing wrong with this.
#include <stdio.h>
int main(void) {
int a[16];
int player = 32;
for (int i = 0; i < sizeof(a); i++) {
if (player+1 == i) {
a[i] = 254;
}
else {
a[i] = 32;
}
}
printf("%d", a[15]);
return 0;
}
Your loop runs from 0 to sizeof(a), and sizeof(a) is the size in bytes of your array.
Each int is (typically) 4-bytes, and the total size of the array is 64-bytes. So variable i goes from 0 to 63.
But the valid indices of the array are only 0-15, because the array was declared [16].
The standard way to iterate over an array like this is:
#define count_of_array(x) (sizeof(x) / sizeof(*x))
for (int i = 0; i < count_of_array(a); i++) { ... }
The count_of_array macro calculates the number of elements in the array by taking the total size of the array, and dividing by the size of one element.
In your example, it would be (64 / 4) == 16.
sizeof(a) is not the size of a, but rather how many bytes a consumes.
a has 16 ints. The size of int depends on the implementation. A lot of C implementations make int has 4 bytes, but some implementations make int has 2 bytes. So sizeof(a) == 64 or sizeof(a) == 32. Either way, that's not what you want.
You define int a[16];, so the size of a is 16.
So, change your for loop into:
for (int i = 0; i < 16; i++)
You're indexing too far off the size of the array, trying to touch parts of memory that doesn't belong to your program. sizeof(a) returns 64 (depending on C implementation, actually), which is the total amount of bytes your int array is taking up.
There are good reasons for trying not to statically declare the number of iterations in a loop when iterating over an array.
For example, you might realloc memory (if you've declared the array using malloc) in order to grow or shrink the array, thus making it harder to keep track of the size of the array at any given point. Or maybe the size of the array depends on user input. Or something else altogether.
There's no good reason to avoid saying for (int i = 0; i < 16; i++) in this particular case, though. What I would do is declare const int foo = 16; and then use foo instead of any number, both in the array declaration and the for loop, so that if you ever need to change it, you only need to change it in one place. Else, if you really want to use sizeof() (maybe because one of the reasons above) you should divide the return value of sizeof(array) by the return value of sizeof(type of array). For example:
#include <stdio.h>
const int ARRAY_SIZE = 30;
int main(void)
{
int a[ARRAY_SIZE];
for(int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = 100;
// I'd use for(int i = 0; i < ARRAY_SIZE; i++) though
}
int squaring_function (int *array, int i);
int main()
{
int array[5];
int i;
for(i=0; (i <= 5) ; i++)
{
array[i] = i;
printf("\nArray value %d is %d",i,array[i]);
}
for(i=0; (i <= 5) ; i++)
{
array[i] = (squaring_function(array, i));
printf("\nSquared array value %d is %d",i,array[i]);
}
return 0;
}
int squaring_function (int *array, int i)
{
return pow((array[i]),2);
}
I'm trying to use this squaring_function to square each value in turn in my array (containing integers 0 to 5). It seems to work however the last value (which should be 5)^2 is not coming up as 25. cmd window
I have tried reducing the array size to 5 (so the last value is 4) however this prints an incorrect number also.
I'm quite new to C and don't understand why this last value is failing.
I'm aware I could do this without a separate function however I'd quite like to learn why this isn't working.
Any help would be much appreciated.
Thanks,
Dan.
There are 2 bugs in your code. First is that you're accessing array out of bounds. The memory rule is that with n elements the indices must be smaller than n, hence < 5, not <= 5. And if you want to count up to 5, then you must declare
int array[6];
The other problem is that your code calculates pow(5, 2) as 24.99999999 which gets truncated to 24. The number 24 went to the memory location immediately after array overwriting i; which then lead to array[i] evaluating to array[24] which happened to be all zeroes.
Use array[i] * array[i] instead of pow to ensure that the calculation is done with integers.
The code
int array[5];
for(int i=0; (i <= 5) ; i++)
exceeds array bounds and introduces undefined behaviour. Note that 0..5 are actually 6 values, not 5. If you though see some "meaningful" output, well - good or bad luck - it's just the result of undefined behaviour, which can be everything (including sometimes meaningful values).
Your array isn't big enough to hold all the values.
An array of size 5 has indexes from 0 - 4. So array[5] is off the end of the array. Reading or writing past the end of an array invokes undefined behavior.
Increase the size of the array to 6 to fit the values you want.
int array[6];
The other answers show the flaws in the posted code.
If your goal is to square each element of an array, you can either write a function which square a value
void square(int *x)
{
*x *= *x;
}
and apply it to every element of an array or write a function which takes an entire array as an input and perform that transformation:
void square_array(int size, int arr[size])
{
for (int i = 0; i < size; ++i)
{
arr[i] *= arr[i];
}
}
// ... where given an array like
int nums[5] = {1, 2, 3, 4, 5};
// you can call it like this
square_array(5, nums); // -> {1, 4, 9, 16, 25}
Give this code:
int solution(int X, int A[], int N) {
int *jumps = calloc(X+1, sizeof(int));
int counter = 0;
int i;
for(i=0; i<N; i++) {
if(A[i]<=X && *(jumps+A[i])!=1) {
*(jumps+A[i])=1;
if(++counter==X) {
return i;
}
}
}
free(jumps);
return -1;
}
Here is what I think I know:
1) int *jumps = calloc(X+1, sizeof(int));
This is making an array storing X+1 elements of an int type. Since it's
calloc they are all initialized as 0.
2) if(A[i]<=X && *(jumps+A[i])!=1)
This if statement's condition is that the element of A at index i is less than or equal to X and the second part I am confused with. I am totally confused what *(jumps+A[i])!=1) means. I know that whatever *(jumps+A[i]) is cannot equal 1.
3) if(++counter==X)
This also confuses me. I'm not sure what ++ does in front of counter. I thought ++ was used as adding an increment of 1 to something. Also, how does counter change? If given the example (5,[1,3,1,4,2,3,5,4]) it changes to 5 but I don't understand why.
So here is what i understand :
every value in A that is superior to X are ignored. (A[i] <= X)
every duplicate value in A are ignored : this is the purpose of (jumps+A[i]) statements.
lastly it will return the index of the current loop if your A array contains at least X unique values inferior to X.
Conclusion : if X is 10. Then it will return the index of A when the function will have found every value from 0 to 9 once whatever their order is. If not found return -1. The ++counter make it so it will stop a 9 and not 10.
I'm going to write in pseudo code to make my question more clear. Please keep in mind this code will be done in C.
Imagine I have an array of any amount of numbers. The first number tells me how big of an array we're dealing with. For example, if my first number is 3, it means I have two 3x3 matrices. So I create two multidimensional arrays with:
matrix1[3][3]
matrix2[3][3]
What I'm having a hard time with is the arithmetic/coding to assign all the numbers to the matrices, I'm having a very hard time visualizing how it would be done.
Imagine a test array contains [2,1,2,3,4,5,6,7,8]
My program should now have two matrixes with:
1 2 5 6
3 4 7 8
Do I need several nested loops? Any help would be appreciated.
At the moment the only idea i get is using two for loops. Or you can make a function and call it every time you need (but don't forget to use k as second argument).
int i, j, k;
/* We start in the 2nd element of the array that's why k = 1. */
k = 1;
/* Now we fill the array1 copying 1 by 1 the elements of the "test array" until
we fill it. Then we do the same with the array2. */
for( i = 0; i < test[ 0 ]; i++ ){
for( j = 0; j < test[ 0 ]; j++ ){
array1[ i ][ j ] = test[ k ]
k++;
}
}
for( i = 0; i < test[ 0 ]; i++ ){
for( j = 0; j < test[ 0 ]; j++ ){
array2[ i ][ j ] = test[ k ]
k++;
}
}
Your data is presented in row-major order. After reading your integer array and validating the content (i.e. the dim=4 means 32 values follow, dim=2 means 8 values follow, etc.) I'm not sure why you want to allocate or loop anything.
I.e. You can use your physical test[] data as the matrices:
int dim = test[0];
int (*mat1)[dim] = (int (*)[dim])(test+1);
int (*mat2)[dim] = (int (*)[dim])(test+1 + dim*dim);
C99 supports variable array declarations at the implementation level (i.e. the compiler can support the feature as it is defined by the standard, but does not have to; see 6.7.6.2 of the C99 standard for more info). If your toolchain does NOT support it, then a predefined macro, __STDC_NO_VLA__ must be defined and can be tested at compile time (see section 6.10.8.3-1 of the C99 standard). That being said, every C99-compliant compiler I've ever used in the last decade-plus does support it, so if your's does not, tell us below in a comment.
If it does, then pay note to the use of 'dim' in the declarations of mat1 and mat2 above). It is one of the few features of C I like that C++ does not have. So dance with the one you brought.
Finally, assuming your compiler is C99 compliant and supports VLAs (__STDC_NO_VLA__ is NOT defined), as an extra super-special bonus it is all-but-guaranteed to be the fastest algorithm to get your two matrices, because there is no algorithm. You read one array element, then assign two pointers. O(3) is hard to beat.
Example
#include <stdlib.h>
#include <stdio.h>
// main loader.
int main(int argc, char *argv[])
{
int test[] = {2,1,2,3,4,5,6,7,8};
int dim = test[0];
int (*mat1)[dim] = (int (*)[dim])(test+1);
int (*mat2)[dim] = (int (*)[dim])(test+1 + dim*dim);
// proof stuff is where it should be.
int i=0,j=0;
for (i=0;i<dim;i++)
{
for (j=0;j<dim;printf("%d ", mat1[i][j++]));
printf (" ");
for (j=0;j<dim;printf("%d ", mat2[i][j++]));
printf("\n");
}
return EXIT_SUCCESS;
}
Output
1 2 5 6
3 4 7 8
A similar test with a 3x3 data set:
int test[] = {3,1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1};
Output
1 2 3 9 8 7
4 5 6 6 5 4
7 8 9 3 2 1
And finally, a 4x4 data set:
int test[] = {4,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1};
Output
1 2 3 4 8 7 6 5
5 6 7 8 4 3 2 1
1 2 3 4 8 7 6 5
5 6 7 8 4 3 2 1
The problem with multidimensional arrays in C is that you need to know in advance (at compile time) n-1 of the dimension sizes, they are also a drag when used as function parameters.
There are a couple of alternate approaches:
Creating an array of arrays. i.e. allocating an array of array pointers and then allocating arrays to those pointers.
type **array = malloc(sizeof(type * ) * < firstnumread > );
array[0] = malloc(sizeof(type) * < firstnumread > );
...
Allocating a single dimension array with the size of all the multiplied dimensions. i.e.
type *array = malloc(sizeof(type) * < firstnumread > * < firstnumread >);
In your case, the second is probably more appropiate. Something like:
matrix1 = malloc(sizeof(type)*<firstnumread>*<firstnumread>);
matrix2 = malloc(sizeof(type)*<firstnumread>*<firstnumread>);
Then you can assign values like this:
matrix1[column*<firstnumread> + row] = <value>;
Yes, with 2 for loops.
2D arrays are stored in continuous series of lines from the matrix. So you doesn't even need to allocate new memory you can use your original array. Anyway you can create 2 new standalone array too.
You can crate a function like this, to get the correct number of the matrix.
int getNumber(int array[], int arraynumber, int index_x, int index_y)
{
return array[(((array[0]*index_x)+index_y)+1)+((array[0]*array[0])*arraynumber)];
}
The arraynumber variable is 0 for the first and 1 for the second matrix. This funciton works only if all parameters are correct, so ther is no error detection.
With this function you can easily loop through and create 2 new arrays:
int i,k;
for (i=0; i<array[0]; i++)
{
for (k=0; k<array[0]; k++)
{
newarray1[i][k] = getNumber(array, 0, i,k);
newarray2[i][k] = getNumber(array, 1, i,k);
}
}
Here is something that works in a single loop; no nests and no repeats. I don't know if it'll outperform other answers, but I just felt like giving you a different answer ^_^
I have not tested this code, but it looks like the logic of the algorithm works - that's the point, right? Let me know if it has any errors....
int c=0, x=0, y=0, size=test[0], length=sizeof(test);
for(i=1; i<length; i++) {
if((c-size)<0) {
matrix1[x][y] = test[i];
} else {
matrix2[x][y] = test[i];
}
++y;
if(y%size == 0) {
++c;
y = 0;
x = (c-size)<0 ? ++x : 0;
}
}
I ran the following:
#include <stdio.h>
typedef unsigned short boolean;
#define false 0
#define true (!false)
int main()
{
int STATUS = 0;
int i = 0;
boolean ret = true;
for(i = 0; i < 99999; i++)
{
ret = ret && printf("Hello, World.");
}
if(!ret)
{
STATUS = -1;
}
return STATUS;
}
It completes in just under a second. Typically 0.9 - 0.92.
Then I changed int i = 0; to int *i = 0; and now I am getting execution times under 0.2 seconds. Why the speed change?
Your runtime is dominated by the time required to print to the console. i++ on an int* will increment the pointer by the size of a pointer. That will be either 4 or 8 depending on your computer and compiler settings. Based on the numbers you report, presumably it would be 4. So printf is executed only a quarter as many times.
Typically, printing to a console will be several orders of magnitude larger than any gain with micro optimization you could do to such a loop.
Are you really sure your second version prints hello world 99999 times as well ?
When you're doing for(int *i = 0; i++ ; i < 99999 ) , you're cheking if the pointer value(an address) is less than 99999, which doesn't normally make a lot of sense. Incrementing a pointer means you step it up to point at the next element, and since you have an int*, you'll increment the pointer by sizeof(int) bytes.
You're just iterating 99999/sizeof(int) times.
Your comment on nos's answer confirmed my suspicion: it's pointer arithmetic. When you increment an int pointer using ++, it doesn't just add one to the number, but it actually jumps up by the size of an integer, which is usually 4 (bytes). So i++ is actually adding 4 to the numeric value of i.
Similarly, if you use += on a pointer, like i += 5, it won't just add 5 (or whatever) to the numeric value of i, it'll advance i by the size of that many integers, so 5*4 = 20 bytes in that case.
The reasoning behind this is that if you have a chunk of memory that you're treating as an array,
int array[100]; // for example
you can iterate over the elements in the array by incrementing a pointer.
int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }
and you won't have to rewrite the loop if you use a data type of a different size.
The reason is because the increment operates differently on pointers.
On ints, i++ increments i by 1.
For pointers, i++ increments by the size of the pointed-to object, which will be 4 or 8 depending on your architecture.
So your loop runs for only 1/4 or 1/8 of the iteration count when i is a pointer vs when i is an int.
The correct way to do this test with a pointer would be something like:
int i;
int *i_ptr = &i;
for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
...