In C, how to initialise an array with a certain pattern? - c

I want to initialise an array in C following a pattern.
For example, here are two arrays with 10 elements. Each array have following elements: {0,0,2,3,0,7,0,1,9,0}
And here is my code: Note: example above and code below are not related, just to elaborate the definition of "pattern" in my case.
void CreateArray()
{
int i = ArraySize();
int j;
int k = Rand_Gen();
printf("%d\n",i);
int array[i];
for (j=0;j<i;j++)
{
if (k>0 && k<=30)
{
array[j]=4;
array[j+2]=23;
array[j+5]=900;
printf("%d",array[j]);
}
else if (k>30 && k<=60)
{
array[j]=2;
array[j+3]=54;
array[j+5]=870;
printf("%d",array[j]);
}
else
{
array[j]=0;
printf("%d",array[j]);
}
}
}
However, after running this program, I can only get an array with the same element. In this case, half of the time I get an array filled with 4 only, and half of the time I get 2.
I have done Googling but I could not find a possible solution to my problem. Or, maybe my method to print elements of the array is not correct?
Thanks first.
Follow up:
I have tried adding "int k = Rand_Gen()" within loop, but I still can only get one number. Here is the update segment of code:
void CreateArray()
{
int i = ArraySize();
int j;
printf("%d\n",i);
int array[i];
for (j=0;j<i;j++)
{
int k = Rand_Gen();
//some if statements here.
}
}

You use :
int k = Rand_Gen();
outside your for loop. This means that k will only be created once. Consequently, your for loop will be executed i times with the same value of k and therefore it will be entering the same part of your if-else statement. You need to generate k inside your loop.
Another issue is that your index 'j' gets out of your array bounds. In particular, your loop runs as following :
for (j=0;j<i;j++)
At some point, j will reach value i-1 (which will be the last iteration). At this point, your if and your else if parts try to access the positions array[j+2], array[j+3] and array[j+5].
However, you have declared array to be of size i so the statements :
array[j+2] = ... ;
array[j+3] = ... ;
array[j+5] = ... ;
with j being i-1 will be equivalent to :
array[i+1] = ... ;
array[i+2] = ... ;
array[i+4] = ... ;
which is definetely indexing out of bounds.

Move k = Rand_Gen(); inside for loop.
Currently you are generating 'k' value only once.
Also accessing j+2 index make out of bound access.

Related

C program to find the sum of all odd integers up to n using while-loop

My book says for programming using while-loop, we must first initialize with a number, provide the condition mentioning 'while', and then it's to be followed by the statement to partake in the loop until the condition is met as well as to increment value in the loop.
Example :
i = 1;
while(i<=10)
{
s = s + i;
p = p * i;
i++;
}
But, in case of summing of odd numbers program no such incrementing value has been shown.
And, strangely enough(for me), I get correct result w/o the use of i++. I absolutely cannot wrap my head around why that is the case. Is mentioning i++ or i+1 not really a rule within loops?
int s, i, n;
s = 0;
i = 1;
while (i <= n)
{
s = s + i;
i = i + 2;
}
This line is the incrementing value:
i = i + 2;
The first loop increments by 1 with i++. But since you only want the odd numbers, you need to increment by 2.
You can simplify this to:
i += 2;
There is no such rule that we must use i++ in every loop(and for that matter using i as a loop variable).
As #Barmar indicated, you are incrementing i using the line :
i = i + 2;
There are cases where we need to increment by 3, 10, √n, logn, etc.
There are even cases where we need to run a loop backwards hence, we decrement i.
The point is, the value of i must change at some point otherwise we'll end up in an infinite loop.

Understanding the following code

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.

What's the point of using linear search with sentinel?

My goal is to understand why adopting linear search with sentinel is preferred than using a standard linear search.
#include <stdio.h>
int linearSearch(int array[], int length) {
int elementToSearch;
printf("Insert the element to be searched: ");
scanf("%d", &elementToSearch);
for (int i = 0; i < length; i++) {
if (array[i] == elementToSearch) {
return i; // I found the position of the element requested
}
}
return -1; // The element to be searched is not in the array
}
int main() {
int myArray[] = {2, 4, 9, 2, 9, 10};
int myArrayLength = 6;
linearSearch(myArray, myArrayLength);
return 0;
}
Wikipedia mentions:
Another way to reduce the overhead is to eliminate all checking of the loop index. This can be done by inserting the desired item itself as a sentinel value at the far end of the list.
If I implement linear search with sentinel, I have to
array[length + 1] = elementToSearch;
Though, the loop stops checking the elements of the array once the element to be searched is found. What's the point of using linear search with sentinel?
A standard linear search would go through all the elements checking the array index every time to check when it has reached the last element. Like the way your code does.
for (int i = 0; i < length; i++) {
if (array[i] == elementToSearch) {
return i; // I found the position of the element requested
}
}
But, the idea is sentinel search is to keep the element to be searched in the end, and to skip the array index searching, this will reduce one comparison in each iteration.
while(a[i] != element)
i++;
First, lets turn your example into a solution that uses sentinels.
#include <stdio.h>
int linearSearch(int array[], int length, int elementToSearch) {
int i = 0;
array[length] = elementToSearch;
while (array[i] != elementToSearch) {
i++;
}
return i;
}
int main() {
int myArray[] = {2, 4, 9, 2, 9, 10, -1};
int myArrayLength = 6;
int mySearch = 9;
printf("result is %d\n", linearSearch(myArray, myArrayLength, mySearch));
return 0;
}
Notice that the array now has an extra slot at the end to hold the sentinel value. (If we don't do that, the behavior of writing to array[length] is undefined.)
The purpose of the sentinel approach is to reduce the number of tests performed for each loop iteration. Compare:
// Original
for (int i = 0; i < length; i++) {
if (array[i] == elementToSearch) {
return i;
}
}
return -1;
// New
while (array[i] != elementToSearch) {
i++;
}
return i;
In the first version, the code is testing both i and array[i] for each loop iteration. In the second version, i is not tested.
For a large array, the performance difference could be significant.
But what are the downsides?
The result when the value is not found is different; -1 versus length.
We have to make the array bigger to hold the sentinel value. (And if we don't get it right we risk clobbering something on the stack or heap. Ouch!)
The array cannot be read-only. We have to be able to update it.
This won't work if multiple threads are searching the same array for different elements.
Using the sentinel value allows to remove variable i and correspondingly its checking and increasing.
In your linear search the loop looks the following way
for (int i = 0; i < length; i++) {
if (array[i] == elementToSearch) {
return i; // I found the position of the element requested
}
}
So variable i is introduced, initialized, compared in each iteration of the loop, increased and used to calculate the next element in the array.
Also the function has in fact three parameters if to pass to the function the searched value
int linearSearch(int array[], int length, int value) {
//...
Using the sentinel value the function can be rewritten the following way
int * linearSearch( int array[], int value )
{
while ( *array != value ) ++array;
return array;
}
And inside the caller you can check whether the array has the value the following way
int *target = linearSearch( array, value );
int index = target == array + size - 1 ? -1 : target - array;
If you add the value to search for, you can reduce one comparison in every loop, so that the running time is reduced.
It may look like for(i = 0;;i++) if(array[i] == elementToSearch) return i;.
If you append the value to search for at the end of the array, when instead of using a for loop with initialization, condition and increment you can a simpler loop like
while (array[i++] != elementToSearch)
;
Then the loop condition is the check for the value you search for, which means less code to execute inside the loop.
The point is that you can convert the for loop into a while/repeat loop. Notice how you are checking i < length each time. If you covert it,
do {
} while (array[i++] != elementToSearch);
Then you don't have to do that extra checking. (in this case, array.length is now one bigger)
Although the sentinel approach seems to shave off a few cycles per iteration in the loop, this approach is not a good idea:
the array must be defined with an extra slot and passing its length as 1 less than the defined length is confusing and error prone;
the array must be modifiable;
if the search function modifies the array to set the sentinel value, this constitutes a side effect that can be confusing and unexpected;
the search function with a sentinel cannot be used for a portion of the array;
the sentinel approach is inherently not thread safe: seaching the same array for 2 different values in 2 different threads would not work whereas searching a constant read only array from multiple threads would be fine;
the benefits are small and only for large arrays. If this search becomes a performance bottleneck, you should probably not use linear scanning. You could sort the array and use a binary search or you could use a hash table.
optimizing compilers for modern CPUs can generate code where both comparisons will be performed in parallel, hence incur no overhead;
As a rule of thumb, a search function should not have side effects. A good example of the Principe of least surprise.

Returning to the start of a while loop mid-loop?

I'm doing a last assessment for the semester and interestingly enough, the code I have written seems to be devoid of errors other than a few simple ones I have just ironed out. However, I am stuck with one last error I cannot get my head around.
The program I am doing is a random numbers generator, using a while loop to generate the numbers and store them in the array, however, a second while loop has to be used to check to see if that number is already in the array, if that number is already in the array, this number has to be discarded and another value has to be obtained to put into the same index. After this the array is printed as a grid of 5x 10. However, upon using a continue command towards the end of the first loop, it comes up with the error:
Random50.java:52: error: continue outside of loop
continue;
^
As much as it seems obvious, I have no idea how to alter my code to make the program run, I was using the the continue command to return to the start of the first loop without incrementing a counter variable, so another value could be stored in the same index again.
import java.util.Random;
import java.util.Arrays;
public class Random50
{
public static void main(String[] args)
{
// Declare and initalise array
int[] random50 = new int[5];
// Declare and initalise counter variable
int i = 0;
// Declare and initalise repeater variable
int r = 0;
// Generator while loop
while (i < random50.length)
{
// Generate random number
int n = (int) (Math.random() * 999) + 1;
// Initalise variables for second while loop
int searchValue = i;
int position = 0;
boolean found = false;
// Duplicate while loop
while (position < random50.length && !found)
{
if (random50[position] == searchValue)
{
found = true;
}
else
{
position++;
}
}
// Return to first loop, determine if duplicate to return to the start of the loop early
if (found);
{
continue;
}
// Store value into array
random50[i] = n;
// Print value and add to counter variable
System.out.print(random50[i] + " ");
r++;
// reset counter variable to maintain grid
if (r == 5)
{
System.out.println("");
r = 0;
}
i++;
}
}
}
So, how can I get the continue to work or in other words, return to the start of the first loop mid loop?
The problem is your while() loop terminating instantly due to an obsolete ; probably placed by accident:
while (i < random50.length);
So your whole loop body will execute exactly once, no matter the condition (which will most likely be optimized out).
Once this is fixed, your use of continue; should work as expected.
Edit:
Same problem further down below:
if (found);
Due to this line you'll always execute the continue; following within these brackets, so the code below becomes unreachable.

Trying to find numbers repeated in two arrays

I am trying to find all of the numbers that are repeated across two arrays..
For example:
array1[2]: 1,2
array2[2]: 1,5
The number that repeats itself is 1 so we create a new array that will contain 1.
array3[2]: 1
My code is:
int func1(int *str, int *str2)
{
int i,j,temp,c[10];
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
if(*(str+i) == *(str+j))
{
temp = *(str+i);
*(str+i) = temp;
temp = *(c+i);
return c[i];
}
}
}
return 0;
}
What is the problem?(logically)
Thanks.
There are multiple problems:
The conditions in the two for loops are odd and probably wrong. They are equivalent to:
for (i = 0; i < str1[i]; i++)
for (j = 0; j < str2[j]; j++)
You should probably specify the sizes of the input arrays in the function interface.
In C, you must make sure you always know the sizes of the arrays.
You should probably specify the output array in the function interface.
Since you will need to know how many values were found in common, you'll need to return that number from the function.
Your choice of the names str1 and str2 is unusual. Not technically wrong, but probably not a good idea. Such names should be reserved for character strings, not arrays of integers.
Your local array c is barely used, and is not used safely.
Your code returns when it finds the first pair of numbers that match, not all possible matches.
The first two lines of the body of the if statement elaborately copies the value in str[i] back to itself via temp.
The third line of the body of the if statement copies an uninitialized value from array c into the variable temp.
The last line of the body of the if then returns that uninitialized value.
This adds up to changes such as:
int func1(int *arr1, int num1, int *arr2, int num2, int *arr3)
{
int k = 0;
for (int i = 0; i < num1; i++)
{
for (int j = 0; j < num2; j++)
{
if (arr1[i] == arr2[j])
arr3[k++] = arr1[i];
}
}
return k;
}
Note that this code assumes that the size of arr3 (the array, not the pointer itself) is as big as the product of num1 and num2. If both arrays contain a list of the same value, then there will be one row in the output array, arr3, for each pair so it could use num1 * num2 rows. This points out that the code does not deal with suppressing duplicates; if you need that (you likely do), then the body of the if statement needs to search through the current values in arr3 to check that the new value is not present. It would be wise to add another parameter, int siz3, to indicate the size of the third array; if you run out of space for values, you could then return -1 as an error indication.
The coded algorithm is quadratic (or, more accurately, proportional to the product num1 * num2). If you know the arrays are sorted on entry, you can reduce it to a linear algorithm (proportional to num1 + num2). With duplicate elimination, it is a little more expensive - it isn't quite as simple as 'cubic'. If you know the input arrays contain unique values (no duplicates), then duplicate elimination is obviously not necessary.
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
Are wrong. You are applying '<' condition on an integer to itself and hence loop condition breaks. So, the loop never runs.
And why are you using these redundant statements?
temp = *(str+i);
*(str+i) = temp;
Also, this is wrong
temp = *(c+i);
return c[i];
Try more to correct those statements.If you can't do again, I will provide you a solution

Resources