Calculating an array size [duplicate] - c

This question already has answers here:
Get the number of elements that it has a value in array
(3 answers)
Closed 8 years ago.
I have this code:
int main() {
int array[5];
int x;
int n;
for(x = 0; x != 5; x++) {
scanf("%d", &n);
if(n % 2 == 0) {
array[x] = n;
}
printf("%d", sizeof(array))
I'd like to know how many variable are saved in the array.
Given that the user entered "2, 3, 5, 6, 7, 8" and it would only get "2,6,8", is there any way to get the size of that?
One way I could do this is to make another int:
int main() {
int array[5];
int x;
int g = 0;
int n;
for(x = 0; x != 5; x++) {
scanf("%d", &n);
if(n % 2 == 0) {
array[x] = n;
g++;
}
printf("%d", g);
Is there any way to do this without incrementing g inside the if block?

You must keep track of the count, or else you won't know what index to use for the array. Your current code doesn't work because you're leaving gaps in the array between the even numbers:
for (x = 0; x != 5; x++) {
scanf("%d", &n);
if (n % 2 == 0) {
array[x] = n;
g++;
}
For the input "2 3 5 6 7", you are storing the number 2 at position 0 in the array, and the number 6 at position 3. At the other positions there is random data. They aren't even zero values because you declared the array inside a function. By the way, a fixed-size array should be declared in the global scope, outside any function. That's because variables inside a function are allocated in a stack frame, which is a small and transient piece of memory. You want your arrays on the heap, which is big and long-lived.
The following code contains several improvements. It defines a constant for the length of the array, and checks the current count before saving a number. (Bad things happen if you write beyond the end of an array.) Also, this code imposes no fixed limit on the amount of data it will read. It keeps calling scanf until the end-of-file value, EOF, is returned.
#include <stdio.h>
#include <stdlib.h>
#define MAX_COUNT 1000
int even[MAX_COUNT];
int main() {
int x,
count = 0; /* Track the number of even numbers. */
while (scanf("%d", &x) != EOF) { /* Get an integer from standard input. */
if(x % 2 == 0) { /* Is it even? */
if (count == MAX_COUNT) { /* If so, check the count first. */
printf("I have reached the limit of %d! I cannot store %d.",
MAX_COUNT, x); /* Fail gracefully if the array is */
} else { /* full. Otherwise, we can go */
even[count++] = x; /* ahead and save the number. */
}
}
}
printf("There are %d even numbers.\n", count);
return 0;
}

You need to keep track of this yourself.
Perhaps by using an extra variable (as you show in your second example), or by having a sentinel value that you can count up to (like how we use the null character in strings)

Related

Unexpected output of a growing dynamic array

I am attempting to create a dynamic array that will grow in size if needed, as I don't know how large the array will actually be. My code seems to work until the 8th element of the array where I start to see very large incorrect values that I did not enter. Not sure why this is happening.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
int val;
int userInput;
int* arr;
int size = 1;
int arrIndex = 0;
arr = (int*) malloc(sizeof(int) * size);
/* prompt the user for input */
printf ("Enter in a list of numbers to be stored in a dynamic array.\n");
printf ("End the list with the terminal value of -999\n");
/* loop until the user enters -999 */
scanf ("%d", &val);
while (val != -999)
{
if (arrIndex >= size)
{
size++;
}
arr[arrIndex] = val;
arrIndex++;
/* get next value */
scanf("%d", &val);
}
int j = 0;
for(j = 0; j < size ; j++)
{
printf("%d \t", arr[j]);
}
}
The size of the array remains 1 and doesn't increase while incrementing size variable.
Your code worked until 8th element because adjacent memory after the array upto 7th element must be free.
In C array index out of bound is not checked and it is programmers responibility.
if you want to increase or decrease size of array you can use realloc inside while loop:
arr=(int*)realloc(arr,sizeof(int)*size);
Also Correct this if condition in your code initially arrayindex is 0 and size is 1 which results in false.
if (arrIndex >= size)
{
size++;
}

What is wrong with my hash function?

I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.

exceeding 500000 with the method of Erastosthenes

i got a problem which i can't solve
I want to know all prime numbers below a given limit x. Allowing me to enter x and calculate the prime numbers using the method of Erastosthenes. Displaying the result on the screen and saving it to a text file.
Calculating the primenumbers below the x, printing them and saving them to a text file worked, the only problem i have is that x can't exceed 500000
could you guys help me?
#include <stdio.h>
#include <math.h>
void sieve(long x, int primes[]);
main()
{
long i;
long x=500000;
int v[x];
printf("give a x\n");
scanf("%d",&x);
FILE *fp;
fp = fopen("primes.txt", "w");
sieve(x, v);
for (i=0;i<x;i++)
{
if (v[i] == 1)
{
printf("\n%d",i);
fprintf(fp, "%d\n",i);
}
}
fclose(fp);
}
void sieve(long x, int primes[])
{
int i;
int j;
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
for (i=2;i<sqrt(x);i++) // loop through all the numbers up to the sqrt(n)
{
for (j=i*i;j<x;j+=i) // mark off each factor of i by setting it to 0 (False)
{
primes[j] = 0;
}
}
}
You will be able to handle four times as many values by declaring char v [500000] instead of int v [100000].
You can handle eight times more values by declaring unsigned char v [500000] and using only a single bit for each prime number. This makes the code a bit more complicated.
You can handle twice as many values by having a sieve for odd numbers only. Since 2 is the only even prime number, there is no point keeping them in the sieve.
Since memory for local variables in a function is often quite limited, you can handle many more values by using a static array.
Allocating v as an array of int is wasteful, and making it a local array is risky, stack space being limited. If the array becomes large enough to exceed available stack space, the program will invoke undefined behaviour and likely crash.
While there are ways to improve the efficiency of the sieve by changing the sieve array to an array of bits containing only odd numbers or fewer numbers (6n-1 and 6n+1 is a good trick), you can still improve the efficiency of your simplistic approach by a factor of 10 with easy changes:
fix primes[0] and primes[1] outside the loop,
clear even offsets of prime except the first and only scan odd numbers,
use integer arithmetic for the outer loop limit,
ignore numbers that are already known to be composite,
only check off odd multiples of i.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sieve(long x, unsigned char primes[]) {
long i, j;
for (i = 0; i < x; i++) {
primes[i] = i & 1;
}
primes[1] = 0;
primes[2] = 1;
/* loop through all odd numbers up to the sqrt(x) */
for (i = 3; (j = i * i) < x; i += 2) {
/* skip composite numbers */
if (primes[i] == 0)
continue;
/* mark each odd multiple of i as composite */
for (; j < x; j += i + i) {
primes[j] = 0;
}
}
}
int main(int argc, char *argv[]) {
long i, x, count;
int do_count = 0;
unsigned char *v;
if (argc > 1) {
x = strtol(argv[1], NULL, 0);
} else {
printf("enter x: ");
if (scanf("%ld", &x) != 1)
return 1;
}
if (x < 0) {
x = -x;
do_count = 1;
}
v = malloc(x);
if (v == NULL) {
printf("Not enough memory\n");
return 1;
}
sieve(x, v);
if (do_count) {
for (count = i = 0; i < x; i++) {
count += v[i];
}
printf("%ld\n", count);
} else {
for (i = 0; i < x; i++) {
if (v[i] == 1) {
printf("%ld\n", i);
}
}
}
free(v);
return 0;
}
I believe the problem you are having is allocating an array of int if more than 500000 elements on the stack. This is not an efficient way, to use an array where the element is the number and the value indicates whether it is prime or not. If you want to do this, at least use bool, not int as this should only be 1 byte, not 4.
Also notice this
for (i=0;i<x;i++)
{
primes[i]=1; // we initialize the sieve list to all 1's (True)
primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
}
You are reassigning the first two elements in each loop. Take it out of the loop.
You are initializing x to be 500000, then creating an array with x elements, thus it will have 500000 elements. You are then reading in x. The array will not change size when the value of x changes - it is fixed at 500000 elements, the value of x when you created the array. You want something like this:
long x=500000;
printf("give a x\n");
scanf("%d",&x);
int *v = new int[x];
This fixes your fixed size array issue, and also gets it off the stack and into the heap which will allow you to allocate more space. It should work up to the limit of the memory you have available.

Updating my array board game

So I'm creating a game. It has a 5 by 5 board filled with characters a, b and c. I need to create a function where if the board detects the same letter next to each other, it disappears and the emptied cells are replaced with a new set of letters (a,b,c). So a bit like the candy crush game. I also need to display the number of moves that are made before the game ends. Here's where I am so far
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 10
//creates board and fills in the letters randomly
int board()
{
char grid[MAX][MAX];
char letter[3] = {'a', 'b', 'c'};
int i,j,row,col;
printf("Please enter your grid size: ");
scanf("%d %d", &row, &col);
if(row < 10 && col < 10){
for(i=0; i < MAX; i++){
for(j=0; j < MAX; j++){
grid[i][j] = letter[rand()%3];
}
}
for(i=0; i < MAX; i++){
for(j=0; j < MAX; j++){
printf("%c ", grid[i][j]);
}
printf("\n");
}
}
else{
printf("Board is too big\n");
board();
}
return 0;
}
//the count doesn't quite do what I need it to
int moveCount()
{
char s;
printf("Press s to start: ");
scanf("%c", &s);
if(s == 's' || s == 'S'){
int count;
int max = 10;
for(count=1; count < max; count++)
if(count == max){
-printf("No more moves can be made");
}
else{
printf("Number of moves made: %d\n", count);
}
}
else{
printf("That is not s\n");
moveCount();
}
}
//Trying to check to make sure that n board is always atleast three cells
int inputCheck(){
int n, m;
if(n == 3 || n > 3 && m == 1 || m > 1){
moveCount();
}
}
int main()
{
board();
inputCheck();
}
What's the best way to implement a function that checks if neighbouring cells are the same and then deletes them. I would imagine doing something like if(myArray[0][0] == 'a' && myArray[0][1] == 'a'{do something}...but i don't know if that's the best way or how I would loop that. Also how to correctly implement a count that displays the move made?
I realise this code has a lot of flaws but I'm quite new so go easy please. Thanks for any help or a push in the right direction.
A serious bug here:
int n, m;
if(n == 3 || n > 3 && m == 1 || m > 1){
n and m are used uninitialized.
And you need to #include <stdlib.h> for rand()
In answer to your actual question, something like this would work. This is rather sloppy, but it's my 5 min answer. I assume grid is the actual board, which exists only in your board() function at the moment, so I simply added that as a parameter. AKA You're going to have to make it fit your actual game.
inline int clamp (int v, int min, int max) {
return (v < min) ? min: (v > max) ? max: v;
}
void place (char ltr, int x, int y, char grid[MAX][MAX])
{
grid[y][x] = ltr; // TODO: put bounds checking around x & y
for (int i = clamp(y - 1, 0, MAX); i <= clamp (y + 1, 0, MAX); i++) {
for (int j = clamp(x - 1, 0, MAX); j <= clamp(x + 1, 0, MAX); j++) {
if (i != y || j != x && grid[i][j] == ltr) {
grid[i][j] = '\0'; // TODO: replace null char with desired one.
}
}
}
}
The board function is set up just fine.
As the previous answers said parameters are the best way to check a value if you are going to check them within a different function, if you wish to check them within your function a simple if command would do the trick.
I would not pass an entire array as a parameter, instead I would use a pointer to that specific cell. Then, upon a person choosing a cell they are given a memory address that you could then compare the information stored inside that memory address with the other they are comparing.
Quick Pointer Lesson
- * is used to create a pointer. For instance, char *ch = array; would point to the memory address of the entire array. And then through more research you will be able to go to a specific memory address in a 2-D array, such as your board, see what is at that location and compare it to the contents contained in another memory address within your 2-D array.
Why would you want to to this?
Since this is not Java, we can about memory management in C and using an entire array as a parameter is the easy but more memory costly way of doing it. Plus, pointers are a fundamental element within most programming languages and knowing them well will make you a much better programmer.
Happy Travels!!
Also this will also be easier to go through your board to say, this person chose this address at array[3][2], there are only four memory address they would be choosing from at that point. Which ever way they choose to go, the memory address will be there and you will be able to compare both with minimal system usage and a quick response.

program in C is crashing when more memory is used

I have to do as a school assigment small program in C that will read standart input and prints some standart output. To be more specific, it's about reading numbers and sorting them.
(you can skip this, it's just for understanding the code)
First line of the input should determine how many lines of numbers there will be. Second line is ammount of numbers in next line. Third line are to concrete numbers. Fourth line is ammount of numbers in next line and so on until it reaches K number of lines. Restrictions are 0 < K <= 10 (max 10 sequences), each sequence can contain max 10.000.000 numbers and each number's value is max 10.000.000
Example
Input:
2 //which means that there will be 2 sequences (lines) of numbers and their corresponding ammount
3 //in the first sequence there will be 3 numbers
5 99912 45 //first sequence
6 //in the second sequence there will be 6 numbers
9489498 22131 0 521313 7988956 5 //second sequence
Ouptup:
0 5 5 45 22131 99912 521313 7988956 9489498
So I have done a working program but it seems to be unstable with higher values. However I can't determine when and where exactly the program fails. On my computer, I have tested all possible max values and it returned correct output in reasonable time, but on a school server where tests are done it just can't handle high values and fails.
There is one thing, that the program should only use C, not C++, but I am not very sure of differences between them and as I was using C++ compiler, it's possible that my code isn't just raw C.
I am a C beginner and this is something like "Hello world" for me, so please, can you just quick look through the code and say what can cause the unstability? Thanks
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int k, n, i, y, x, index = 0;
int *numbers = (int*) malloc(100000000 * sizeof(int));
if(numbers == NULL){
exit(1);
}
scanf("%d", &k);
for (x = 0; x < k; x++) {
y = 0;
scanf("%d", &n);
while(scanf("%d", &i) > 0){
numbers[index++] = i;
if(++y == n){
break;
}
}
}
for(y = 0;y < index;y++){ //find and print all 0's, because later I will use 0 as a
//already used (printed) element in array and ignore it
if(numbers[y] == 0){
if(y == index-1){
printf("0");
}else{
printf("0 ");
}
}
}
int smallest, smallestIndex;
for(x = 0;x < index;x++){ //print all other numbers in ascending order
smallest = 0;
for(y = 0;y < index;y++){ //find current smallest number
if((numbers[y] < smallest || smallest == 0) && numbers[y] != 0){
smallest = numbers[y];
smallestIndex = y;
}
}
numbers[smallestIndex] = 0;
if(smallest > 0){
if(x == index-1){
printf("%d", smallest);
}else{
printf("%d ", smallest);
}
}
}
free(numbers);
numbers = NULL;
return 0;
}
Based on the information you give, I think this is simply a resource limitation on the server. The server simply runs out of memory and your malloc() fails. I suggest you debug or do this:
if(numbers == NULL){
printf("malloc() failed\n");
exit(1);
}
The code for printing the initial zeros is suspicious:
for(y = 0;y < index;y++){ //find and print all 0's, because later I will use 0 as a
//already used (printed) element in array and ignore it
if(numbers[y] == 0){
if(y == index-1){
printf("0");
}else{
printf("0 ");
}
}
Suppose you have a sequence with 0 as the last element (e.g. 1 2 3 4 5 0); i guess this code will print just 0 with no space after it, and the subsequent code will print 1 2 3 4 5, so you will get something like 01 2 3 4 5.
I understand that you want the output to be as beautiful as possible, that is, without a space at the end. Please also note that a newline (\n) at the end of output might be good.
I rewrote beginning parts of your program to get you on the right path. This should help you but I can't be sure since I don't really know what is causing your program to crash.
This implements the realloc function which should make your program drastically more efficient than it is now. If you don't know what realloc is you can read about it here, and here.
#include <stdio.h>
#include <stdlib.h>
#define BUFFER 256 //for memory management
int main(void)
{
int k, n, i, y , x, index = 0, bff; //declare integer 'bff' and set it to BUFFER
int *numbers = NULL, *tmp; //declare a pointer (numbers) for allocated memory, and a pointer (tmp) for the realloc function
if(!(numbers = malloc(BUFFER * sizeof(int)))) //allocate space for 'bff' integers
{
exit(1); //allocation failed
}
scanf("%d", &k);
for (x = 0; x < k; x++)
{
scanf("%d", &n);
while(scanf("%d", &i) > 0)
{
if(bff <= index) //if the size of index grows larger than the amount of space we allocated
{
bff += BUFFER; //increase the size of bff by BUFFER
if(!(tmp = realloc(numbers, bff * sizeof(int)))) //resize our allocated memory block using the tmp pointer
{
free(numbers); //allocation failed so free already allocated memory
exit(1); //and terminate the program
}
numbers = tmp; //make numbers point to the same location as tmp
numbers[index++] = i;
if(++y == n) break;
}
}
}
.
.
.
free(numbers);
return 0;
}
Keep in mind there are more efficient ways to use realloc. I just posted this here to get you on the right track. Good luck!
You are allocating the wrong amount of memory. The specification states that each sequence can contain 10 million values whereas you allocate a fixed amount. There may be up to k*10 million values of input, and you cannot know that the amount you allocate is enough.
As pointed out by m0skit0, the problem may also be due to over-allocation.
To fix the problem you should allocate the needed amount of memory, no more, no less.
Use the sequence length provided for each sequence to do that.
Also, you need to check the return value of malloc and realloc. If the return value is NULL then the allocation failed and you should print an error message and exit.

Resources