Weird array behaviour in C - arrays

so I'm trying to write a simple function that fills a given area of the screen with 'X's. The Area to be filled is user defined.
As (later on) I want to be able to manipulate that display, the 'x's are written into an array. Then, I use this array for my printf().
This works perfectly fine most of the time, but there are two problems:
In some cases ( for Example with the values 5,10) one X is missing from the array! (In this case drawPic[8][0] ) It doesn't make any sense to me...
X X X X X
X X X X X
X X X X X
X X X X X
X X X X X
X X X X X
X X X X X
X X X X X
X X X X
X X X X X
Second, I sometimes get that nice segmentation fault: 11 error. I don't understand why this is the case, it seems quite random. (for example, values 5,12 will give error, values 10,12 will not)
/*
Testcase to fill a picture frame
*/
#include <stdio.h>
#define clrscr() printf("\e[1;1H\e[2J")
int main()
{
int sizeX, sizeY;
clrscr();
printf("\n\n\n\n\tEnter picture size (x,y):\t");
scanf("%d,%d", &sizeX, &sizeY);
char drawPic[sizeX-1][sizeY-1];
clrscr();
for(int i=0; i<sizeY; i++)
{
for(int j=0; j<sizeX; j++)
{
drawPic[i][j] = 'X';
if(j<sizeX-1)
printf("%c ", drawPic[i][j]);
else
printf("%c\n", drawPic[i][j]);
}
}
// printf("\n\n 9th line 1st char: %c\n\n", drawPic[8][0]);
}
/edit:
OKAY, first of all: thanks a lot. Array size was a typical noob mistake, i guess. Correct array size solved issue no.1, and the other problem was that i had i,j of drawPic the wrong way round.
Working code:
/*
Testcase to fill a picture frame
*/
#include <stdio.h>
#define clrscr() printf("\e[1;1H\e[2J")
int main()
{
int sizeX, sizeY;
clrscr();
printf("\n\n\n\n\tEnter picture size (x,y):\t");
scanf("%d,%d", &sizeX, &sizeY);
char drawPic[sizeX][sizeY];
clrscr();
for(int i=0; i<sizeY; i++)
{
for(int j=0; j<sizeX; j++)
{
drawPic[j][i] = 'X';
if(j<sizeX-1)
printf("%c ", drawPic[j][i]);
else
printf("%c\n", drawPic[j][i]);
}
}
}
You're a great community to help out beginners like me with their stupid mistakes which must seem so very obvious to you. Thanks a lot!

Your array is too small:
char drawPic[sizeX-1][sizeY-1];
This creates a 2D array with dimensions sizeX-1 and sizeY-1 which is one less than you requested. Because array indices in C start from 0, the valid indices for these dimensions are 0 to sizeX-2 and 0 to sizeY-2 respectively.
Your loops then use indices up to sizeX-1 and sizeY-1 which means you read and write outside the bounds of the array. This triggers undefined behavior which explains the occasional strange results you're seeing.
When declaring an array, the dimensions specify the total number of elements, not the index of the last element. So you instead should declare it as:
char drawPic[sizeX][sizeY];
You've also got your loop conditions mixed up:
for(int i=0; i<sizeY; i++)
{
for(int j=0; j<sizeX; j++)
{
i should have sizeX as its limit and j should have sizeY as its limit, not the other way around. This can also cause reading outside the array bounds when the two values are not the same. While it's probably not a problem in practice, there's no guarantee it won't be.

Related

Why am I getting this single output wrong?

I'm new to competitive programming and I participated in Codeforces #653 in which I spent the whole time solving this problem and did not submit any code because of exceeded time limits or wrong answer for test cases.
I wanted to solve this problem - https://codeforces.com/contest/1374/problem/A
You are given three integers x,y and n. Your task is to find the maximum integer k such that 0 ≤k≤ n that k mod x=y, where mod is modulo operation. Many programming languages use percent operator % to implement it.
In other words, with given x,y and n you need to find the maximum possible integer from 0 to n that has the remainder y modulo x
You have to answer t independent test cases. It is guaranteed that such k exists for each test case.
I wrote this following code:
#include <stdio.h>
int main(){
int i,t,j,k=0;
int x[60000],y[60000],n[60000],prev[60000];
scanf("%d",&t);
for(i=0; i<t; i++){
scanf("%d %d %d",&x[i],&y[i],&n[i]);
}
for(i=0; i<t; i++){
for(j=0, k=0; j<n[i]; j++ , k++){
if(j%x[i]==y[i]){
prev[i]=k;
}
}
}
for(i=0; i<t; i++){
printf("%d",prev[i]);
printf("\n");
}
return 0;
}
Everything was working fine but for some test cases I'm getting different answers.
This was the expected output
12339
0
15
54306
999999995
185
999999998
and my output was this:
12339
0
5
54306
999999995
185
999999998
I did not understand why I got 5 instead of 15 keeping all the other outputs correct and also could anyone please help me to optimize the code, its taking too long to compile for large inputs.
For the 1st part of your question, why the answer is wrong - has been answered nicely by others already. For the 2nd part about efficiency, the solution doesn't need any extra loop except the loop for iterating over the test case.
The solution could be as easy as this:
k = n - ((n - y) % x)
For example:x = 7, y = 5, n = 12345. Then,
k = 12345 - ((12345 - 5) % 7)
= 12339
This small piece of code could get you accepted:
#include <stdio.h>
int main()
{
int t, x, y, n;
scanf("%d", &t);
while (t > 0) {
scanf("%d %d %d", &x, &y, &n);
printf("%d\n", n - ((n - y) % x));
t--;
}
}
The reason you were getting TLE was because your code was taking too long. As I can see n could be upto 10^9 and so a O(N) solution would easily time-out at such constraints. Add to that, the fact that your code would be given upto 5*10^4 test cases. So, for your code to work, it should be much faster than O(N) time complexity. I have explained a better approach below which would satisfy the given constraints.
Optimised Approach :
For each test case, we are given x, y, n. And we have to find the largest number( let's say ans) between 0 to n such that ans%x = y.
Let's first find the remainder when we divide n by x. So, remainder = n%x. Now, if the remainder >= y, this means that we would have to reduce n such that it will leave a smaller remainder that is => a remainder equal to y. For this, we can simply reduce n by (remainder - y) amount.
Example :
For better understanding, lets see an example where
x = 10, y = 5, n = 16.
In this case remainder = n%x = 6. Now remainder > y, so we can just reduce our n by (remainder - y), that is n now becomes 15. We see that 15%x = y and so that's our answer.
The other case we might get is remainder < y. In this case, we have to increase the remainder. But we can't increase n (since it is the upper limit). So, what we can instead do is subtract x from n. The remainder will still be same. But now we are allowed to increase n by some amount which results in remainder to be y. For that we simply increase n by an amount y - remainder, so that new remainder will be equal to y.
Example :
Let's consider example where
x = 10, y = 5 and n = 24
Here, remainder = n%x = 4. So remainder < y. We subtract x from n, so n becomes 14 but still n%x = 4, so remainder remains same. But, we now have the advantage that we can increase x so that remainder would be equal to y. Since our remainder is 1 less than required (y), we increase n by 1 (or y - remainder = 1). Thus, we have the answer = 15.
This approach has time complexity of O(1) which is far better than O(N) approach. I hope that you got the idea of the approach I was trying to explain. Below is the pseudocode for same -
Pseudocode
remainder = n%x
if (remainder >= y) // Case 1
return n - ( remainder - y ) as the answer
else // Case 2
return ( n - x ) + ( y - remainder ) as the answer
Hope this helps !
The first part of this answer will explain what's wrong in your logic. The second part will contain a plot twist.
How to get the correct answer
As you have correctly been told in comments by #ErichKitzmueller your inner loop searches k values in the range [0-n[. In other words, if you are not familiar to my mathematical notation, you are not even considering the value n that is not included in your loop search, as you do for(j=0, k=0; j<n[i]; j++ , k++).
For the record, [0-n[ means "range from to 0 to n including 0 and not including n.
If you have to search the maximum value satisfying a given requirement... why starting counting from 0? You just need starting from the right limit of the range and loop backwards. The first k you will find satisfying the condition will be your output, so you'll just need to save it and exit the inner loop.
No need to find ALL the numbers satisfying the condition and overwrite them until the last is found (as you do).
The main loop of your solution would become something like that:
for(i=0; i<t; i++){
int found = 0;
for(k=n[i]; k>=0 && found==0; k--)
{
if( ( k % x[i] ) == y[i] )
{
prev[i] = k;
found = 1;
}
}
}
The plot twist (the REAL solution)
The previous solution will lead to correct answers... anyway it will be rejected as it exceeds the time limit.
Actually, all these competitive coding problems are all based on asking for a problem that in some way is simpler than it looks. In other words, it's always possible to find a way (usually after a mathematical analysis) that have a lower computational complexity than the one of the first solution that comes to your mind.
In this case we have to think:
What is the reminder of a division? y = k%x = k - x*int(k/x)
When has this expression its max? When k=n. So y = k - x*int(n/x)
So k = x*int(n/x) + y
Finally, we want make sure that this number is lower than n. If it is, we subtract x
The code becomes something like this:
#include <stdio.h>
int main(){
int i, t;
int x[60000],y[60000],n[60000],k[60000];
scanf("%d",&t);
for(i=0; i<t; i++){
scanf("%d %d %d",&x[i],&y[i],&n[i]);
}
for(i=0; i<t; i++){
int div = n[i] / x[i]; // Since div is an integer, only the integer part of the division is stored to div
k[i] = x[i] * div + y[i];
if( k[i] > n[i] )
k[i] -= x[i];
}
for(i=0; i<t; i++){
printf("%d", k[i]);
printf("\n");
}
return 0;
}
I've tested the solution on Codeforce, and it has been accepted.
the following proposed code:
cleanly compiles
performs the desired functionality
is very quick (could be made quicker via different I/O functions)
and now, the proposed code:
#include <stdio.h>
int main()
{
int x;
int y;
int n;
size_t t;
scanf("%zu",&t);
for( ; t; t-- )
{
scanf( "%d %d %d", &x, &y, &n );
printf( "%d\n", n - ((n - y) % x) );
}
return 0;
}

calculating x to power y using for loop

I've tried to use the for loop for calculating x to power y. The program is running but giving errors.
To my knowledge, the error must be in "z" statements but I cannot figure it out.
Help me if you encounter my mistakes.
#include<stdio.h>
#include<conio.h>
void main()
{
int x,y,i;
long int z=x;
printf("Enter the values of x and y: ");
scanf("%d %d",&x,&y);
for(i=2;i<=y;i++)
z*=x; ```
/*e.g- Let x=2, y=3, then as per intialization z=x=2
since,from the for condition, (i=2)<=3, which is true
z= z*x =>2*2 => 4 now z=4
now i++ => i=3
(i=3)<=3,which is true
z= z*x =>4*2 => 8
therefore, 2 to power 3 is 8 */
printf("%d to power %d is %ld",x,y,z);
getch();
}
You are assigning z to x before x is assigned a value. z then has an indeterminate value, which messes up calculation of the power.
You have to wait until x is assigned from user input before using its value to initialize z.
Also, when reading input from scanf, it's a best practice to check its return value to ensure that all intended values were read successfully:
if(scanf("%d %d", &x, &y) != 2)
{
// x and y were not properly read - handle error
}
z = x;
EDIT: #chux - Reinstate Monica pointed out in the comments that if y == 0 the code still has a problem. Anything to the power of zero (except zero itself, since xy is not continuous at the origin) is 1. You have to handle that special case as well.
You are initializing your z variable (to be equal to x) before you have assigned a value to x! To fix this, move the declaration/initialization of z to after your scanf call:
//..
int x,y,i;
// long int z=x; // Means nothing: as "x" is here undefined, so "z" will also be!
printf("Enter the values of x and y: ");
scanf("%d %d",&x,&y);
long int z = x; // Here, we have (probably) a value for "x" so we can copy it to "z"
//..
EDIT: Maybe I'm drifting a bit 'off-topic' here, but you may have a background in programming languages that use reference variables (C++ or C#)? In such languages, what you are trying to do may work! For example, in C++, you could have int& z = x; (where you have your current declaration), and that could work in some circumstances (although, in your code, it actually won't, as pointed out in the comments). However, in "plain old C," code is executed where you put it, and there's no such thing as a "reference variable."
First you might want to initialize those variables
long int x = 0, y = 0;
long int z = 0;
Here you should check if scanf was successful
printf("Enter the values of x and y: ");
scanf("%ld %ld",&x,&y);
About scanf return value. From cppreference
Return value 1-3) Number of receiving arguments successfully assigned
(which may be zero in case a matching failure occurred before the
first receiving argument was assigned), or EOF if input failure occurs
before the first receiving argument was assigned. 4-6) Same as (1-3),
except that EOF is also returned if there is a runtime constraint
violation.
Now the problem is you're assigning z the value of x before either is initialized properly. So that is an undefined behavior.
This is what you want
long int x = 0, y = 0;
long int z = 0;
printf("Enter the values of x and y: ");
scanf("%ld %ld",&x,&y);
z = x;
Also you can define a new int variable inside the loop. I personally find this method better.
for(int i = 2; i <= y; i++)
z *= x;
For the print statement, you might want to use %ld format for long int
printf("%ld to power %ld is %ld",x,y,z);

Trying to make a function which squares all values in an array. Getting strange number on the last value

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}

Solve segmentation fault error in C

I am trying to store the sum 1/k^2 in an array using this code:
int main()
{
int i,n, e;
double terms[n];
double x, y;
printf(" Introduce n\n");
scanf("%d", &n);
y=1;
i=0;
while(e<n)
{
x=1/((y)*(y));
printf("x is %.16lf\n",x);
terms[i]=x;
printf("terms is %.16lf\n", terms[i]);
y++;
i++;
e++;
}
}
And I get the "segmentation fault" error. Why is this happening? How can I avoid it?
I am programming in C
n is garbage in double terms[n]; that causes undefined behaviour. Enable compiler warning by compiling with gcc -Wall and observe. Never ignore warnings.
Initialize n before declaring terms[n] OR
printf(" Introduce n\n");
scanf("%d", &n);
double terms[n];
Also e is uninitialized, initialize it.
e = 0 ;
while (e < n){
/* code */
}
When declaring an array with n elements (double terms[n];), the allocation of said array is done in the compilation stage. Because you left your n variable un-initialized, it has indeterminate value (random from the user perspective), so you don't know what is the size of said array.
Scanning an int into n later, does not help at all as it is done in the run-time (and also, it is done AFTER the array declaration. It could have worked if you have used malloc for the allocation AFTER the scanf).
Anyway, you currently have an array with "random" size, and accessing it is Undefined Behavior -> segfault
The crash comes from undefined size of the terms[n] array. You are crossing array memory boundaries.
A few variables are not initialized:
double terms[n]; // n is not initialized
while (e<n){ // e is not initialized
You have many choices to properly build terms array (marked in the code as well):
1) Decide upfront on the specific size of the array. (This is not flexible approach!)
2) Allocate array dynamically when you read n.
3) Declare terms[n] after reading n.
Test program:
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
int n;
int e = 0;
// 1. One of the 3 choices - thus is a rigid one
// double terms[TERMS_SIZE]; // make TERMS_SIZE big enough, read n has to be less than TERMS_SIZE
double x, y;
printf(" Introduce n\n");
scanf("%d", &n);
// 2.
// double *terms = malloc ( n* sizeof sizeof(double));
// or
// 3.
double terms[n];
y=1;
i=0;
while (e<n){
x=1/((y)*(y));
printf("x is %.16lf\n",x);
terms[i]=x;
printf("terms is %.16lf\n",terms[i]);
y++;
i++;
e++;
}
// If 2. used free the memory
// free(terms);
return 0;
}
Output:
4
Introduce n
x is 1.0000000000000000
terms is 1.0000000000000000
x is 0.2500000000000000
terms is 0.2500000000000000
x is 0.1111111111111111
terms is 0.1111111111111111
x is 0.0625000000000000
terms is 0.0625000000000000

Changing array values in functions

Ok so I have a 10x10 array that I need to flip and print. I made this function to do just that
void flip(int d[][10], int rows)
{
int temp, x, y, cols;
cols=rows;
for(x=0; x<rows; x++)
{
for(y=0; y<cols; y++)
{
temp=d[x][y];
d[x][y]=d[y][x];
d[y][x]=temp
}
}
}
Now I know arrays are passed by reference but I also read somewhere that arrays itself act as pointers so you don't have to use pointer notation which seems right. My problem is that when I try to print after flipping it, it does not print the flipped array, but prints out the original one making me think that it isn't flipping the original array.
Here is the print function.
void printArray(int d[][10])
{
int rows, cols,x,y;
rows = sizeof(d[0])/sizeof(d[0][0]);
cols = rows;
for(x=0;x<rows; x++)
{
for(y=0;y<cols;y++)
printf("%2d ",d[x][y]);
printf("\n");
}
}
Odd thing is if I change temp into a "hard" value like the number 10, then it does print out a 10x10 array with half of them being 10s. I am at a loss here why the simple swapping isn't working :(
From what I can tell, by "flip" you mean "transpose"...
Also, if you work out the code by hand, your code works, but twice - aka, you get the original matrix. You can try changing the inner for loop to start at x, not zero.

Resources