I made an int array in C and initialised it with 0 as follows -
int f[10000] = {0};
My program demanded me to reinitialise this array in the end of the loop. So, I performed this step -
f[10000] = 0;
But this didn't worked. I even tried
f[10000] = {0};
but got error in it too. Ultimately, I had to use memset. Can anyone help as in where is the error occurring and why?
EXTRA INFO - I USED ideone.com FOR CODING PURPOSE
For the reference, here is the complete code -
#include <stdio.h>
int main(void) {
int t, n, k, f[10000] = {0}, c[10000] = {0}, i, v, count = 0;
scanf("%d", &t);
while (t--) {
scanf("%d %d", &n, &k);
for (i = 1; i <= n; i++) {
scanf("%d", &v);
if (v == i) {
f[i] = 1;
}
c[v]++;
}
for (i = 1; i <= n; i++) {
if (!f[i] && c[i] >= k) {
count++;
}
}
printf("%d\n", count);
count = 0;
memset(f, 0, 10000);
memset(c, 0, 10000);
//f[10000] = 0; this didn't worked
//c[10000] = 0; this didn't worked
}
return 0;
}
In C, initialization is not the same as assignment, although both use =.
int foo[3] = { 0 };
means "make foo an array of three integers, all initialized to zero", but foo[3] = 0; means "set the fourth element of foo to zero". Clearly different.
And since memset() works in bytes, this:
memset(f, 0, 10000);
is wrong, it should be:
memset(f, 0, sizeof f);
as long as f is a proper array as in your code.
Also beware that very large arrays as automatic variables might not be very portable.
If you did like this
int f[10000] = {0};
then
f[10000] = 0;
is wrong since index starts at 0 in C so you are writing outside the array bounds.
As previously mentioned, you cannot assign to an array. However, you can assign to a struct.
struct foo { int f[1000]; } f = {};
Then,
f = (struct foo){};
Related
some time ago I tried to program a Mergesort. In some point I got an error that I was able to solve, but still saved the code because have something strange that i don't understand. The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int elem;
void mergesort(elem * arr, unsigned n){
if(n != 1){
if(n == 2){
if(arr[0] > arr[1]){
int change = arr[0];
arr[0] = arr[1];
arr[1] = change;
}
}else{
unsigned i = 0, j = 0, mit = (n+1)>>2, fin = n>>2;
elem * arr_2 = (elem *)malloc(sizeof(elem) * n), * mit_arr = arr+mit;
mergesort(arr, mit);
mergesort(mit_arr, fin);
while(i < mit || j < fin){
if(arr[i] <= mit_arr[j]){
arr_2[j+i] = arr[i];
i++;
}else{
arr_2[j+i] = mit_arr[j];
j++;
}
}
for(i=0; i<n; i++)
arr[i] = arr_2[i];
free(arr_2);
}
}
}
int main(){
unsigned a = 10;
int i;
elem * arr = (elem*)malloc(sizeof(elem) * a);
arr[0] = 12;
arr[1] = 3;
arr[2] = -3;
arr[3] = 22;
arr[4] = 12;
arr[5] = 11;
arr[6] = 4;
arr[7] = 9;
arr[8] = 10;
arr[9] = 2;
printf("something\n"); // 1
mergesort(arr, a);
printf("\n");
for(i=0; i<a; i++){
printf("%d, ", arr[i]);
}
printf("\n");
free(arr);
return 0;
}
The thing is that, despite the fact that the code doesn't do what I want and it seems like there is no error, if I comment out the line marked by 1 (printf("something\\n"); ) then the error "malloc(): corrupted top size" appears. I actually don't know why something like that is possible, so I came here to see if someone have an explanation.
I tried to debug the program with gdb and got the same error, but have more information:
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
but still without idea of what happened.
There are a couple of major issues with your code. These are things you should be able to test yourself by checking whether the values being used by your function are what you expect.
Here's the first issue. You have calculated the length of the first half of the array as (n+1)>>2, and then you assume the length of the remaining array is n>>2. That is simply not true. Shifting a value to the right by 2 binary places is a division by four.
It is far better to use "normal" math instead of attempting to be clever. This reduces the chance for errors, and makes your code easier to read.
unsigned mit = n / 2, fin = n - mit;
The other issue is your merge. You have made your while-loop run until both i and j are out-of-range. But in your loop, it's guaranteed that on at least one of the iterations, one of those values will be out-of-range.
A better way to merge arrays uses three loops. The first one runs until either of the arrays has been merged in, and the remaining two loops will copy the remaining part of the other array.
unsigned x = 0, i = 0, j = 0;
while(i < mit && j < fin){
if(arr[i] <= mit_arr[j]){
arr_2[x++] = arr[i++];
}else{
arr_2[x++] = mit_arr[j++];
}
}
while(i < mit){
arr_2[x++] = arr[i++];
}
while(j < fin){
arr_2[x++] = mit_arr[j++];
}
I am successful in identifying prime and composite from an array. But my qsort function seem to not have any effect when I print the output. I need the primes to be ascending and composite to be descending. When I run the code, it does not sort the output, though it identifies primes and composites.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return b - a;
}
int main() {
int i = 0, n, x, p, c, z, w, j = 0, k = 0, cmpst, null;
int prm;
int prime[50], composite[50], input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &n);
printf("Enter the numbers.\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &input[i]);;
}
for (i = 0; i < n; i++) {
if (input[i] % 2 != 0) {
prime[p++] = input[i];
prm = p;
} else
if (input[i] >= 2 && input[i] % 2 == 0) {
composite[c++] = input[i];
cmpst = c;
}
}
printf("Prime Numbers:");
qsort(prime, prm, sizeof(int), compare_Asc);
for (i = 0; i < p; i++) {
printf("%d", prime[p]);
}
printf("Composite Numbers:");
qsort(composite, cmpst, sizeof(int), compare_Desc);
for (i = 0; i < c; i++) {
printf("%d", composite[c]);
}
return 0;
}
There are some major issues, in the posted code, worth mentioning.
Variables
Declaring all the variables at the beginning of the scope, instead of just before where they are used, can hide bugs.
Uninitialized variables, are an even worse source of errors, because their values are indeterminated.
int i=0, n, x, p, c, z, w, j=0, k=0, cmpst, null;
// ^ ^ ^^^^ ?
// ... Later, in the code:
prime[p++] = input[i];
// ^^^ What value is incremented?
// Where is [p++]? Is it inside the prime array?
A correct initialization would prevent undefined behavior.
int p = 0, c = 0;
int composite[50], input[50];
for(int i = 0; i < n ; ++i) {
if ( is_prime(input[i]) ) { // <-- More on this, later.
prime[p++] = input[i];
}
else {
composite[c++] = input[i];
}
}
Loops
This happens a couple of times, just because the code itself is duplicated (another code smell):
for(i=0;i<p;i++){
// ^^^^^^^^^^^ We want to iterate over [0, p).
printf("%d",prime[p]);
// ^ But this always prints the element one past the end
}
Even if it's just a simple loop, it could be a good idea to write a (testable and reusable) function
void print_arr(size_t n, int arr[n])
{
for (size_t i = 0; i < n; ++i) {
printf("%d ", arr[i]);
} // ^
putchar('\n');
}
// ... Later, in main:
print_arr(p, prime);
print_arr(c, composite);
Primes or composite
I am successful in identifying prime and composite from an array
Well, no. Not with this code, I'm sorry.
if (input[i]%2 != 0) { // Those are ALL the ODD numbers!
prime[p++]=input[i];
}
else if(input[i]>=2 && input[i]%2==0){ // Those are the EVEN numbers greater than 0
composite[c++]=input[i];
}
// What about 0 and the even numbers less than 0?
Not all the odd numbers are prime number (it's a little more complicated than that) and 2 itself is a prime, not a composite.
It's unclear to me if this is a terminology issue or if the snippet is only a placeholder for a proper algorithm. In any case, there are multiple examples of primality test functions in SE sites (I'm quite confident some are posted almost every day).
Overflow risk
See chux - Reinstate Monica's comment:
return a-b; risks overflow when a, b are large int values.
Consider return (a > b) - (a < b); for a full range solution.
Single letter variables names are to be avoided... except for i, j and k used in for() loops only.
You're not updating the index of the arrays c and p as the numbers are being printed out. The arrays are being sorted fine.
In the code below I also remove redundant variables, and rename n to input_count, c to compo_count and p to prime_count.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return b - a;
}
int main ()
{
int i = 0;
int input_count = 0;
int prime_count = 0;
int compo_count = 0;
int prime[50];
int composite[50];
int input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &input_count);
printf("Enter the %d numbers.\n", input_count);
for (i = 0; i < input_count; i++)
{
scanf("%d", &input[i]);
}
for (i = 0; i < input_count; i++)
{
if (input[i] % 2 != 0)
{
prime[prime_count] = input[i];
prime_count += 1;
}
else if (input[i] >= 2 && input[i] % 2 == 0)
{
composite[compo_count] = input[i];
compo_count += 1;
}
}
printf("Prime Numbers:");
qsort(prime, prime_count, sizeof(int), compare_Asc);
for (i = 0; i < prime_count; i++)
{
printf("%d ", prime[i]); // <<-- HERE, not [p]
}
printf( "\n" );
printf ("Composite Numbers:");
qsort(composite, compo_count, sizeof(int), compare_Desc);
for (i = 0; i < compo_count; i++)
{
printf("%d", composite[i]); // <<-- HERE, not [c]
}
printf( "\n" );
return 0;
}
So for some Uni work I need to create an array using a function (my first time with C functions and pointers) but store the array as a pointer because i dont think C can use arrays in functions? And then also use another function to print out each element in the array. The code i use in main is:
int* x = get_lotto_draw();
print_array(x);
And then my functions are:
int* get_lotto_draw() //Returns an array of six random lottery numbers 1-49
{
int min = 1;
int max = 49;
int counter = 0;
srand(time(NULL));
int r = rand()%(max-min)+min;
int *arrayPointer = malloc(6 * sizeof(int));
for(counter = 0; counter <= 5; counter++)
{
arrayPointer[counter] = r;
}
return arrayPointer;
}
void print_array(int * array) //Print out the content of an array
{
int i = 0;
int printerArray[6] = {0, 0, 0, 0, 0, 0};
for(i = 0; i <= 5; i++)
{
printerArray[i] = array[i];
}
printf("array = %d", array);
printf("printerArray = %d", printerArray);
for(i = 0; i <= 5; i++)
{
printf("Array element %d : %d\n", i, printerArray[i]);
}
}
But im doing something wrong, and either the array isnt getting created correctly, or the print isnt working correctly. Thanks for your time.
What you want is:
void print_array(int * array) //Print out the content of an array
{
int i = 0;
for(i = 0; i <= 5; i++)
{
printf("Array element %d : %d\n", i, array[i]);
}
}
Following two lines could provoke undefined behavior
printf("array = %d", array);
printf("printerArray = %d", printerArray);
you can't use %d here, as array and printerArray decays to pointers in this context and in order to print pointer you should use %p and cast your arrays to void * (thanks to #user3447428 for his comment about cast )
So I am working on some homework, in which I have to create a global array of 500 random integers between 0 and 99. Then, I have to count how many are greater than 75, and how many are less than 50.
Here is my code:
#include <stdlib.h>
#include <stdio.h>
static int ARRAY[500];
static char str[1];
void main() {
int i = 0;
for (i = 0; i < 500; i++) {
int r = rand() % 99;
ARRAY[i] = r;
}
int gt75 = count75();
int lt50 = count50();
printf("%d\n", str, gt75);
printf("%d\n", str, lt50);
}
int count75() {
int i = 0, counter = 0;
for (i = 0; i < 500; i++) {
int n = ARRAY[i];
if (n > 75) {
counter += 1;
}
}
return counter;
}
int count50() {
int i = 0, counter = 0;
for (i = 0; i < 500; i ++) {
int n = ARRAY[i];
if (n < 50) {
counter += 1;
}
}
return counter;
}
However, after compiling and running my program, I get the following output:
4225008
4225008
This can't be right, as the list should only have 500 elements in the first place. What am I doing wrong?
You have two errors.
First, int r = rand() % 99; should be int r = rand() % 100; Otherwise you just get numbers between 0 and 98.
Second, your printf statements are odd. They should be:
printf("Greater than 75: %d\n", gt75);
printf("Less than 50: %d\n", lt50);
In the current printf statements, the str is cast to an int, which is interpreting the str pointer as an int, thus your strange output.
You're printing a char array with printf using "%d", which is for printing integers. Use "%s" for printing char arrays:
printf("%s\n", str, gt75);
Or, if you're trying to print the value of gt75 as an integer:
printf("%d\n", gt75);
I do not know why you would pass str in this case, though.
When you use "%d", you are telling printf to interpret the input as an int. Since str is actually a char array, it does not output correctly. Instead, you're printing the memory location of str, which is the value of an array.
You are always printing the value of str, which is not an int.
I cannot understand why i is set to 0 right after array is initialized to zero.
The program is working fine because I have reinitialized value of k to i.
But I could not find out why i becomes 0.
And why memset() is clearing the array, or setting the array to 0?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
long long int i = 123456789;
long long int j = 987654321;
long long int cnt = 0;
int array[9] ;
int xyz, k, x, rem, se;
xyz = 0;
// printf("I = %llf", i);
for (i; (i < j) && (cnt < 100000); i++)
{
k = i;
x = 0;
for (se = 0; se <= 9; se++)
{
array[se] = 0;
}
/*************************************************/
i = k; // Here i becomes zero. Why?
/************************************************/
//memset(array, 0, 9);
while(k != 0)
{
rem = k % 10;
for(se = 0; se <= 9; se++)
{
if(rem == array[se])
{
xyz = 1;
break;
}
}
if(rem == array[se])
{
xyz = 1;
break;
}
array[x++] = rem;
k = k / 10;
}
if (xyz != 1)
{
cnt++;
// printf("Cnt = %d ", cnt);
// printf("The value i is = %lld\n", i);
// Sleep(10);
}
xyz = 0;
// printf("The value i is = %lld\n", i);
// printf("Cnt = %d \n", cnt);
fflush(stdin);
}
printf("The value i is = %lld \n", i-1);
return 0;
}
You have a buffer overflow; since the buffer is on the stack, it might be regarded as a form of Stack Overflow†.
int array[9]; // Elements array[0] .. array[8]
...
for (se = 0; se <= 9; se++)
{
array[se] = 0;
}
It must be k that is being overwritten with the extra 0; i is assigned 0 because that's the value in k. You invoke 'undefined behaviour' when you write outside the boundaries of an array, as you did here. Undefined behaviour means that anything can happen and it is OK. Sometimes, it will seem to work; sometimes, there'll be unexpected side effects. Avoid 'undefined behaviour' at all costs.
The idiomatic for loop is:
for (se = 0; se < 9; se++)
array[se] = 0;
Note the < instead of <=.
† There are those who would disagree. See the comments.
You also ask about the (commented out) call to memset():
//memset(array, 0, 9);
The third parameter to memset() is the size in bytes of the area of memory to be set. You are setting 9 bytes out of a total of (probably) 36 in the array, which is unlikely to be what you wanted.
Here, the array is defined in the same function so it is safe and sensible to write:
memset(array, 0, sizeof(array));
If array was a parameter passed to a function, that would not work correctly; you would need a different size. For example:
void somefunc(int array[], int num)
{
...
memset(array, 0, num * sizeof(array[0]));
...
}
You are overwriting the end of the array.
int array[9] ;
for(se = 0; se <= 9; se++)
{
array[se] = 0;
}
In C, arrays are indexed from 0, so the loop goes one step to far. The idiomatic syntax is:
for(se = 0; se < 9; se++)
In other words, use < with the number of elements as the value. Often written to remove the scary numerical constant, like so:
for(se = 0; se < sizeof array / sizeof *array; se++)
This uses the sizeof operator to automatically (at compile-time) compute the proper number of elements, so that if you change the array definition the loop remains correct.
One way to check this is to check the pointer of x and array[9] by printing &x and &array[9].
If they are same, you are surely overwriting as mentioned.