I have a C binary file with 5123 values in the form of a 3-dimensional cube. I need to access the position in the cube with the highest value, which is the density. Once I have the position of the highest value, I need to create a smaller 3D cube about this position with values that are obviously smaller than 512 (the dimension of the cube). start represents the position at one corner of the smaller cube. p is the binary file obviously.
fseek(p,0,SEEK_END);
lSize = ftell(p);
rewind(p);
dim = pow(lSize/sizeof(float),1.0/3.0);
printf("File size: %lu bytes, Grid size: %d \n", lSize,(int)dim);
max = 0;
counter = 0;
index = 0;
while(fread(&density,sizeof(float),1,p),!feof(p) && !ferror(p)) {
if(density > max) max = density,index = counter;
counter += 1;
}
sub = 256;
start = index - (pow(dim,2)+dim+1)*(sub/2-1);
printf("3d coordinates of highest density: %lu,%lu,%lu, Dimension of cube: %d\n",index % 512;(index / 512) % 512;index / (512 * 512),(int)dim);
printf("The maximum density is: %e with index: %lu \n", max,index);
rewind(p);
fseek(p,start*sizeof(float),SEEK_SET);
fseek(q,start*sizeof(float),SEEK_SET);
fseek(r,start*sizeof(float),SEEK_SET);
fseek(s,start*sizeof(float),SEEK_SET);
fseek(t,start*sizeof(float),SEEK_SET);
u = fopen("results_dens.dat", "w");
if (u == NULL) { printf("Unable to open output results file!"); exit(1); }
for (ibox=0;ibox<nbox;ibox++){
for (k=0;k<nz[ibox];k++){
fseek(p,(start+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(q,(start+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(r,(start+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(s,(start+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(t,(start+k*dim*dim)*sizeof(float),SEEK_SET);
for (j=0;j<ny[ibox];j++){
fseek(p,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(q,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(r,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(s,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
fseek(t,(start+j*dim+k*dim*dim)*sizeof(float),SEEK_SET);
for (i=0;i<nx[ibox];i++){
I am aware that the above code runs without any errors. However, a lot rides on the value of index above. I am unsure of how positions are defined in C. I am aware that these are memory locations but by doing some rough calculations, the value of index that I derive seems to be close to the edge of the box and not the centre.
5123 = 134217728.
The value of index is 66978048, 130816 positions from the middle position value of 67108864. But, 130816 is approximately 512*256 meaning that if the middle position of the grid is at the edge of the box, then so is index above.
Perhaps this will help. First, I created a test file with the following program:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int makeCube(const char *fn, int dim)
{
FILE *p;
const int center = dim/2;
p = fopen(fn,"w");
for (int i=0; i < dim; ++i)
for (int j=0; j < dim; ++j)
for (int k=0; k < dim; ++k) {
float f = dim - sqrtf(pow(i-center,2)+
pow(j-center,2)+pow(k-center,2));
fwrite(&f, sizeof(float), 1, p);
}
fclose(p);
return 0;
}
int main()
{
const int dim = 512;
makeCube("cube.bin", dim);
return 0;
}
Next I rewrote your code to have correct syntax and to print some diagnostics which seemed useful:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int subCube(FILE *p, int dim)
{
float density;
float max = 0;
long index = 0;
long counter;
for (counter=0; fread(&density,sizeof(float),1,p); ++counter) {
if(density > max) {
max = density;
index = counter;
}
}
printf("The maximum density is: %e with index: %lu \n", max,index);
int i = index/dim/dim;
int j = (index - (i*dim*dim))/dim;
int k = (index - ((i*dim)+j)*dim);
printf("This corresponds to coordinates (%d,%d,%d)\n", i,j,k);
}
int main()
{
const int dim = 512;
FILE *p = fopen("cube.bin","r");
subCube(p, dim);
fclose(p);
return 0;
}
When I run that program, I get the following output:
The maximum density is: 5.120000e+02 with index: 67240192
This corresponds to coordinates (256,256,256)
Since the test data was basically a sphere with greatest density at the middle, this is exactly as expected.
Note that I have played fast and loose with error handling (there isn't any!) but it's omitted for clarity and not because you should actually omit it in a real program.
Related
I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.
I have to write a program to open a file that contains 3 columns, each row represents data for a baseball player. the first columns represents the players number, second is times at bat, lastly the third is average hits. I have to sort the players in descending order of average hits. I am having a problem, it orders them in descending order of number times at bat. also the first 3 numbers are not printing out correctly.
here are the first 3 players data
3 5 .400
5 1 .000
9 30 .167
here is my code.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float BattingA[13], At_Bat[13];
int Player_ID[13];
void Sort_Arrays(int ID[], float at_bat[], float average[]);
int main()
{
int ID[13];
float at_bat[13], average[13];
FILE *readfile;
int i;
if ((readfile = fopen("cubs-batting-ws-ab-avg.txt", "r")) == NULL)
{
printf("The file failed to open\n");
}
for (i = 0; i < 13; i++)
{
fscanf(readfile, "%d %f %f", ID + i, at_bat + i, average + i);
Sort_Arrays(ID, at_bat, average);
}
printf("numbers\n");
for (i = 0; i < 13; i++)
{
printf("%d %.0f %.3f \n", ID[i], at_bat[i], average[i]);
}
if (fclose(readfile) == EOF)//close the file.
{
printf("The file failed to close.\n");
}
return 0;
}
void Sort_Arrays(int ID[], float BattingA[], float AtBat[])
{
int x, y = 13, z;
float New, NewID, NewAtBat;
for (x = 0; x < y; x++)
{
for (z = x + 1; z < y; z++)
{
if (BattingA[x] < BattingA[z])
{
NewID = ID[x];
NewAtBat = AtBat[x];
New = BattingA[x];
ID[x] = ID[z];
AtBat[x] = AtBat[z];
BattingA[x] = BattingA[z];
ID[z] = NewID;
AtBat[z] = NewAtBat;
BattingA[z] = New;
}
}
}
}
anything you could do to help i would really appreciate it.
thank you all.
The arguments are being passed to the Sort_Arrays function in the wrong order. at_bat is being passed in as the 2nd argument. As Sort_Arrays is written to sort according to the 2nd argument, your arrays are being sorted according to at_bat.
I have written code that allows you to enter one dimension of a NxN double array. It will then print random numbers in a 2D array and it finds the maximum and minimum number of each row. It then prints them and their coordinates (row and column).
ATTENTION!!!!
I have altered my code in such a way that it finds the minimum number of the maximum. I now don't know how to find it's coordinates
My code is as follows:
int N, i, j, min=1000, max, m , o;
time_t t;
int masyvas[100][100], minmax[100];
printf("Enter one dimension of a NxN array\n");
scanf("%d", &N);
srand((unsigned) time(&t));
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
masyvas[i][j] = rand() % 10;
printf("%4d", masyvas[i][j]);
}
printf("\n");
}
int k, l, idkeymax, idkeymin;
for(k=0; k<N; k++)
{
max=-1000;
for(l=0; l<N; l++)
{
if(max<masyvas[k][l])
{
max=masyvas[k][l];
}
}
minmax[k]=max;
}
for(m=0; m<N; m++)
{if(minmax[m]<min)
min=minmax[m];
}
printf("maziausias skaicius tarp didziausiu yra %d eiluteje %d stulpelyje %d\n",min);
Here's the pseudo code of what you need to do.
for row in grid {
row_max = max_in_row(row)
grid_min = min(grid_min, row_max)
}
Step one is to write a routine that finds the max and location in a list. You could do this as one big function, but it's much easier to understand and debug in pieces.
You also need the index where it was found. Since C can't return multiple values, we'll need a struct to store the number/index pair. Any time you make a struct, make routines to create and destroy it. It might seem like overkill for something as trivial as this, but it will make your code much easier to understand and debug.
typedef struct {
int num;
size_t idx;
} Int_Location_t;
static Int_Location_t* Int_Location_new() {
return calloc(1, sizeof(Int_Location_t));
}
static void Int_Location_destroy( Int_Location_t* loc ) {
free(loc);
}
Now we can make a little function that finds the max number and position in a row.
static Int_Location_t* max_in_row(int *row, size_t num_rows) {
Int_Location_t *loc = Int_Location_new();
/* Start with the first element as the max */
loc->num = row[0];
loc->idx = 0;
/* Compare starting with the second element */
for( size_t i = 1; i < num_rows; i++ ) {
if( row[i] > loc->num ) {
loc->num = row[i];
loc->idx = i;
}
}
return loc;
}
Rather than starting with some arbitrary max or min, I've used an alternative technique where I set the max to be the first element and then start checking from the second one.
Now that I have a function to find the max in a row, I can now loop over it, get the max of each row, and compare it with the minimum for the whole table.
int main() {
int grid[3][3] = {
{10, 12, 15},
{-50, -15, -10},
{1,2,3}
};
int min = INT_MAX;
size_t row = 0;
size_t col = 0;
for( size_t i = 0; i < 3; i++ ) {
Int_Location_t *max = max_in_row(grid[i], 3);
printf("max for row %zu is %d at %zu\n", i, max->num, max->idx);
if( max->num < min ) {
min = max->num;
col = max->idx;
row = i;
}
Int_Location_destroy(max);
}
printf("min for the grid is %d at row %zu, col %zu\n", min, row, col);
}
I used a different technique for initializing the minimum location, because getting the first maximum would require repeating some code in the loop. Instead I set min to the lowest possible integer, INT_MAX from limits.h which is highest possible integers. This allows the code to be used with any range of integers, there are no restrictions. This is a very common technique when working with min/max algorithms.
This my first post on here. I'd like to ask about a problem that I am trying to do for homework.
I'm supposed to be constructing a for loop for the "first 5 factorials" and display results as a table. I followed an example in the book, and I have my for loop and my operations set up, but I don't know what to do to produce the loop in the table. Here is my program:
#include <stdio.h>
int main(void) {
//Problem: Display a range for a table from n and n^2, for integers ranging from 1-10.
int n, factorialnumber, i;
printf("TABLE OF FACTORIALS\n");
printf("n n!\n");
printf("--- -----\n");
for (n = 1; n <= 10; n++) {
factorialnumber = factorialnumber * n;
printf("\n %i = %i", factorialnumber, n);
}
return 0;
}
I know the printf here is wrong. What would I type?
BTW, I'm using codeblocks.
The problem is that you didn't initialize the variables (e.g. factorialnumber). If it has an initial value of 6984857 let's say, the whole algorithm would be messed up.
Try this :
#include <stdio.h>
int main(void) {
//Problem: Display a range for a table from n and n^2, for integers ranging from 1-10.
int i, factorialnumber = 1;
int n = 10; // Max number to go through
printf("TABLE OF FACTORIALS\n");
printf("i i!\n");
printf("--- -----\n");
for (i = 1; i <= n; i++) {
factorialnumber *= i;
printf("%d! = %d\n", i, factorialnumber);
}
return 0;
}
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.