How to detect data beyond certain value out of a fixed range - c

I've written a c program which can read a text file with single column of data. All the data can be read into the program with the following codes:
#include <stdio.h>
#include <cstdlib>
main()
{
char temp[20];
float t;
int a = 0, x = 0; //a is no. of data greater than 180 and x is no of data
FILE *fpt;
fpt = fopen("case i.txt", "r");
fscanf(fpt, "%s", temp); // read and display the column header
printf("%s\n", temp);
while (fscanf(fpt, "%f", &t) == 1)
{
printf("%.2f\n", t);
++x; //count for number of data
if (t > 180) {
++a; //count for number of data > 180
}
if (x > 2 && a == 2) { //place where bug is expected to occur
printf("2 out of 3 in a row is greater than 180");
a=0; //reset a back to zero
x=0;
}
}
fclose(fpt);
system("pause");
}
The problem comes when I want to detect like 2 out of 3 data are beyond 180 degree Celsius. I tried some ideas like when (no. of data > 2) and (two data > 180) then generate an error message, but it will have bug as it may have two data > 180 but when 4 data are read, that means it become 2 out of 4, not 2 out of 3, is it possible to be programmed? Thank you in advance for every help.
The following is the sample data and output:

You'll need to keep a "sliding window" of 3 values indicating how many are over 180.
So one approach would be something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char temp[20];
float t;
const int min_over = 2;
const int max_window = 3;
const int max_value = 180;
char over[max_window]; // a 1 means over, 0 otherwise
int oi = 0;
int num_values = 0;
FILE *fpt;
fpt = fopen("case i.txt", "r");
fscanf(fpt, "%s", temp); // read and display the column header
printf("%s\n", temp);
memset(over, 0, max_window);
while (fscanf(fpt, "%f", &t) == 1)
{
int num_hit, i;
printf("%.2f\n", t);
// Calculate num_hit: how many over in a window of max_window
//
over[oi] = (t > max_value) ? 1 : 0;
if (++oi >= max_window)
oi = 0;
for ( num_hit = i = 0; i < max_window; i++ ) num_hit += over[i];
// Only check for min_over/max_window after at least
// max_window values read; Reset the check
//
if ((++num_values >= max_window) && (num_hit >= min_over))
{
printf("It happened!\n");
memset(over, 0, max_window);
num_values = 0;
}
}
fclose(fpt);
system("pause");
}
Since you want a ratio of 2/3, that corresponds to min_over / max_window values.
I ran this on your commented data sample:
Temperature
190.00
190.00
170.00
It happened!
200.00
190.00
100.00
It happened!
100.00
190.00
190.00
It happened!

There are about a million billion different ways to do this, but you just need to keep track of how many samples exceed the threshold and then do whatever you want to do when you hit that mark.
Let's say, once you find your "2 out of 3" samples that exceed 180 you want to print the list and stop reading from the file:
FILE *fpt;
float t;
float samples[3] = {0}; // keep a record of 3 samples
int total = 0, i;
fpt = fopen("file1.txt", "r");
while (fscanf(fpt, "%f", &t) == 1) // read until there are no more samples
{
total = 0; // clear our counter
samples[2] = samples[1]; // toss out the old 3rd sample
samples[1] = samples[0]; // and shift them to make room for the
samples[0] = t; // one we just read
for(i = 0; i<3; i++)
if(samples[i] > 180) // if any are over 180
total++; // increment our counter
if(total == 2) { // if 2 of the 3 are over 180, we got 2 out of 3
printf("2 out of 3 samples are greater than 180!\n");
printf("1: %f\n2: %f\n3:%f\n", samples[2],samples[1],samples[0]);
break;
}
}
fclose(fpt);
It's not very efficient.. but should be pretty easy to understand.

Related

Calculating force vectors between N bodies returns incorrect values?

I'm trying to write a function that calculates the force vectors acting on a body from N bodies using F = GMm/r^2 (given the masses and initial positions in .txt files), and stores the values in a dynamically allocated array. I think the issue stems from the calculation of the radius (distance between 2 bodies), as the values returned are incorrect. The position vectors in the initial_positions.txt file are in this format (without the headers):
pos_x pos_y pos_z
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
The masses in the masses.txt file are in this format:
1
2
3
4
5
So that the body with mass 1 has initial position (1, 2, 3), the body with mass 2 has initial position (4, 5, 6) etc.
My code to read in the files and calculate the force vectors:
#include <stdio.h>
#include <stdlib.h>
int NumberOfBodies(void) //finds the number of bodies from masses.txt file.
{
char character;
char previousCharacter;
int numberOfBodies = 1;
FILE *file = fopen("masses.txt", "r");
if (file == NULL)
{
printf("\nUnable to access the 'masses.txt' file.\n");
exit(1);
}
else
{
while ((character = fgetc(file)) != EOF)
{
if (character == '\n' && previousCharacter != '\n')
{
numberOfBodies++;
}
previousCharacter = character;
}
}
fclose(file);
return numberOfBodies;
}
double *ReadMasses(int numberOfBodies) //reads masses.
{
int row;
int line;
double *masses = malloc(sizeof(double) * numberOfBodies);
FILE *file = fopen("masses.txt", "r");
if (file == NULL)
{
printf("\nUnable to access the 'masses.txt' file.\n");
exit(1);
}
for (row = 0; row < numberOfBodies; row++)
{
line = fscanf(file, "%lf", &masses[row]);
if (line == EOF)
{
break;
}
}
fclose(file);
return masses;
}
double **ReadInitialPositions(int numberOfBodies) //reads initial positions.
{
int row;
int scan;
double **initialPositions = malloc(sizeof(double*) * numberOfBodies);
for (row = 0; row < numberOfBodies; row++)
{
initialPositions[row] = malloc(sizeof(double) * 3); //hardcoded as we only consider x, y, and z components of position.
}
FILE *file = fopen("initial_positions.txt", "r");
if (file == NULL)
{
printf("\nUnable to access the 'initial_positions.txt' file.\n");
exit(1);
}
for (row = 0; row < numberOfBodies; row++)
{
scan = fscanf(file, "%lf %lf %lf", &initialPositions[row][0], &initialPositions[row][1], &initialPositions[row][2]);
if (scan == EOF)
{
break;
}
}
fclose(file);
return initialPositions;
}
double **CalculateForces(int numberOfBodies, double *masses, double **initialPositions) //function to calculate force vectors.
{
int row;
int column;
int currentBody = 0;
double radius;
double gravitationalConstant = 6.6743;
double **forces = malloc(sizeof(double*) * numberOfBodies);
for (row = 0; row < numberOfBodies; row++)
{
forces[row] = malloc(sizeof(double) * 3);
}
for (row = 0; row < numberOfBodies; row++)
{
for (column = 0; column < 3; column++)
{
if (row != currentBody)
{
radius = (initialPositions[row][column] - initialPositions[row][currentBody]); //I suspect the issue stems from this line.
forces[row][column] = (gravitationalConstant * masses[row] * masses[currentBody]) / (radius * radius);
currentBody++;
}
else
{
forces[row][column] = 0;
currentBody++;
}
}
}
for (row = 0; row < numberOfBodies; row++)
{
for (column = 0; column < 3; column++)
{
printf(" %lf", forces[row][column]); //Prints force vectors.
}
printf(" \n");
}
return forces;
}
int main(void)
{
int numberOfBodies;
double *masses;
double **initialPositions;
numberOfBodies = NumberOfBodies();
masses = ReadMasses(numberOfBodies);
initialPositions = ReadInitialPositions(numberOfBodies);
CalculateForces(numberOfBodies, masses, initialPositions);
return 0;
}
NumberOfBodies(), ReadMasses(), and ReadInitialPositions() all seem to be working as intended. Thanks in advance!:)
This has all the earmarks of code written without a firm grasp of the math. Try writing out the math first.
GMm/r^2 gives the scalar force between two bodies. It acts along the direction vector between the bodies. Consequently, the scalar must be split into its vector components. Splitting is just just multiplying by the direction vector scaled to unit length.
More to the point, if you are computing the force between bodies a and b, then
Rab^2 = (xb - xa)^2 + (yb - ya)^2 + (zb - za)^ 2
Fab = ma mb / Rab^2
A unit vector from a to b has coordinates
Uabx = (xb - xa) / Rab
Uaby = (yb - ya) / Rab
Uabz = (zb - za) / Rab
Of course Rab = sqrt(Rab^2) computed above.
The three components of the force acting on a due to b are
Fabx = Uabx * Fab
Faby = Uaby * Fab
Fabz = Uabz * Fab
The force acting on b due to a is Fb = -Fa.
Working this out as an algorithm:
For each pair a,b of bodies
Find r^2 the distance between a and b.
Find Fab the scalar force between a and b.
Find Ua the unit vector from a toward b.
Find vector Fa by splitting Fab into three components using Ua.
Add Fa into the total force acting on a.
Add -Fa into the total force acting on b.
A quick look at your code shows it can't be very close to correct. Ex: it computes three different values of r for a pair of bodies. There can be only one distance between two points in space!
Hint: To get all pairs of integers (ignoring order) in [0..n-1] that don't include self-pairs like (1, 1), the standard pattern is loops that look like this:
for (j = 1; j < n; j++)
for (i = 0; i < j; i++)
This will iterate over i-j pairs in the order (0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (2, 3), ...

making kruskal's algorithm in c (segmentation fault)

In this code I want to make Kruskal's algorithm, which calculates a minimum
spanning tree of a given graph. And I want to use min-heap and disjoint set at the code.
To make time complexity of O(e log n), where e is the number of edges and n is the number of vertices in the graph, I will use heap and disjoint set trees.
So the method I went with was:
Check the numbers of vertices and edges in the given input file and make parent array and struct edge which can include at most 10000 vertices and 50000000 edges.
Sort the edges by the weight in a min heap in descending order.
Take out edges from min heap one by one and check whether it makes cycle until min heap is empty
If the number of edges selected is vertices-1 (if all vertices already connected ) break the while loop and print each edges and sum of weights. If all vertices can make minimum spanning tree it prints connected and if all vertices can not make minimum spanning tree it prints disconnected.
I thought the code is well done but when I run this in putty, it is exiting with segmentation fault (core dumped)
input (example)
7
9
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12
3 4 22
3 6 18
4 5 25
4 6 24
result(I want)
0 5 10
2 3 12
1 6 14
1 2 16
3 4 22
4 5 25
99
CONNECTED
I checked the edges are well stored in min-heap in descending order. But I think it has mistakes in making minimum spanning tree. These are points that I am suspicious in the code.
Should I make edge minheap by dynamic allocation instead of minheap[50000000]?
Should I make additional data structures apart from the array parent and struct edge.
It is the code I made! Can you give me help or advice ?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define maxvertice 10000
#define maxedge 50000000
typedef struct edge { //structure to store vertices and weight
int a, b;
int w;
}
edge;
int n = 0; //numbers of edge in the minheap
int parent[maxvertice] = {-1,};
//array to represent disjoint sets! parent which stores the vertice connected
//if it is not connected(independent) it's parent is -1
edge minheap[maxedge]; //heap that sorts edges
void insertheap(edge item, int * n); // arrange edges by the weight in descending order
edge deleteheap(int * n); //popping out from the root (in descending order)
void makeunion(int x, int y); // this make x and y combined
int findparent(int i);
int main(int argc, char * argv[]) {
double start, end;
int i, nv, ne, sumofweight = 0, isitdone;
int cnt_edge = 0;
edge item;
//////////////
if (argc != 2) {
printf("usage: ./hw3 input_filename\n");
return 0;
}
FILE * fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("The input file does not exist.\n");
return 0;
}
FILE * result = fopen("hw3_result.txt", "w");
start = (double) clock() / CLOCKS_PER_SEC;
fscanf(fp, "%d", & nv);
printf("to test : number of vertices : %d\n", nv);
fscanf(fp, "%d", & ne);
printf("to test : number of edges : %d\n", ne);
for (i = 0; i < ne; i++) {
int firstv, secondv, weight;
edge newedge;
fscanf(fp, "%d %d %d", & firstv, & secondv, & weight);
newedge.a = firstv;
newedge.b = secondv;
newedge.w = weight;
// get vertices and edge's weight from the input file and put in heap
insertheap(newedge, & n);
}
/*
for(i =0 ; i<ne; i++){
item= deleteheap(&n);
printf("%d", item.w);
}*/
while (minheap != NULL) { //pop out from the heap until mst is completed
item = deleteheap( & n);
//union at array parent
int par1, par2;
par1 = findparent(item.a);
par2 = findparent(item.b);
if (par1 != par2) {
makeunion(par1, par2);
printf("%d %d %d\n", item.a, item.b, item.w);
cnt_edge = cnt_edge + 1;
sumofweight += item.w;
}
if (cnt_edge == nv - 1) break;
}
if (cnt_edge == nv - 1) {
// fprintf(result, "CONNECTED");
printf("%d\n", sumofweight);
printf("CONNECTED");
}
if (cnt_edge < nv - 1) {
// fprintf(result, "DISCONNECTED");
printf("DISCONNECTED\n");
}
end = (((double) clock()) / CLOCKS_PER_SEC);
fclose(fp);
fclose(result);
printf("output written to hw3_result.txt.\n");
printf("running time: %1f", (end - start));
printf(" seconds\n");
}
void makeunion(int x, int y) {
parent[x] = y;
}
int findparent(int i) {
for (; parent[i] >= 0; i = parent[i]);
return i;
}
void insertheap(edge item, int * n) {
int i;
i = * n;
++( * n);
while ((i != 0) && (item.w < minheap[i / 2].w)) {
minheap[i] = minheap[i / 2];
i /= 2;
}
minheap[i] = item;
printf("to test : the wieght %d is inserted in :%d \n", item.w, i);
}
edge deleteheap(int * n) {
int parent, child;
parent = 0;
child = 1;
edge item, temp;
item = minheap[0];
temp = minheap[( * n) - 1];
( * n) --;
while (child <= * n) {
if ((child < * n) && (minheap[child].w > minheap[child + 1].w)) child++;
if (temp.w <= minheap[child].w) break;
minheap[parent] = minheap[child];
parent = child;
child *= 2;
}
minheap[parent] = temp;
return item;
}

C variable specified as a long long but recognized as an int

I'm working on a program that checks the validity of credit card numbers for the CS50 class I'm taking (it's legal I swear haha) and I'm currently working on correctly getting the first two numbers of each CC# to check what company it is from. I've commented what each part does for clarity and also commented where my problem arises.
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <math.h>
#include <string.h>
int main(void)
{
long long ccn = get_long_long("Enter CCN: \n");
int count = 0;
long long ccn1 = ccn;
// finds the amount of digits entered and stores that in int count.
while (ccn1 != 0)
{
ccn1 /= 10;
+count;
}
printf("%i \n", count);
// ln 17- 19 should take int count, subtract two, put that # as the power of 10,
// then divide the CC# by that number to get the first two numbers of the CC#.
long long power = count - 2;
// here is where i get the error. its a long long so it
// should hold up to 19 digits and im only storing 14 max
// but it says that 10^14th is too large for type 'int'
long long divide = pow(10,power);
long long ft = ccn / divide;
printf("power: %i \n", power); //ln 20-22 prints the above ints for debug
printf("Divide: %lli \n", divide);
printf("First two: %lli \n", ft);
string CCC;
// ln 24-35 cross references the amount of digits in the CC#
// and the first two digits to find the comapany of the credit card
if ((count == 15) && (ft = 34|37))
{
CCC = "American Express";
}
else if ((count == 16) && (ft = 51|52|53|54|55))
{
CCC = "MasterCard";
}
else if ((count = 13|16) && (ft <=49 && ft >= 40))
{
CCC = "Visa";
}
printf("Company: %s\n", CCC);
}
The first issue is the +count in the loop. This should be ++count. Because of this, count stays at 0 and power = -2. You can avoid all that power stuff. You already have the loop, you can use it to get the first two digits:
int ft = 0;
while (ccn1 != 0)
{
// When you are down to 10 <= ccn1 < 100, store it
if (ccn1 < 100 && ccn1 > 9) ft = ccn1;
ccn1 /= 10;
++count;
}
Your second issue is how you do your comparisons.
if ((count == 15) && (ft = 34|37))
First, = is assignment, and == tests equality. Second, | is bitwise OR, || is logical OR. Third, you can't test multiple values like that. Correct way:
if ((count == 15) && (ft == 34 || ft == 37))

Read data values from text file along with number of rows and columns in C

I have a data file in .txt format with 7 rows and 4 columns.
I am using following code to read these values:
#include<stdio.h>
#include<math.h>
int main()
{
int N=7, i;
double x[7], y[7], p[7], q[7];
FILE *f1;
f1=fopen("data.txt","r");
for(i=0;i<N;i++)
fscanf(f1,"%lf %lf %lf %lf", &p[i], &q[i], &x[i], &y[i]);
fclose(f1);
}
Here N is the number of rows in the data file, which I know in advance.
Is there any way to read the number of rows in the data file, so that I can generalize this code for any data file without knowing the value of N in advance.
NOTE: The number of columns is not changing between different data files.
You have to count the lines yourself (like this for example), and then rewind the file pointer to the start of the file, to actually parse it, now that you found N.
To reset the pointer to the start of the file, do this:
fseek(fptr, 0, SEEK_SET);
Another way is to find out the size of your data and do some calculations, like this:
% Read the vector size
d = fread (fid, 1, 'int');
vecsizeof = 1 * 4 + d * 4;
% Get the number of vectrors
fseek (fid, 0, 1);
a = 1;
bmax = ftell (fid) / vecsizeof;
b = bmax;
if nargin >= 2
if length (bounds) == 1
b = bounds;
elseif length (bounds) == 2
a = bounds(1);
b = bounds(2);
end
end
assert (a >= 1);
if b > bmax
b = bmax;
end
if b == 0 | b < a
v = [];
fclose (fid);
return;
end
% compute the number of vectors that are really read and go in starting positions
n = b - a + 1;
fseek (fid, (a - 1) * vecsizeof, -1);
Relevant matlab code can be found here.
/* count the number of rows in the given text table */
#include<stdio.h>
int main()
{
int count = 0;
FILE* ptr = fopen("D:\\test.txt","r");
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
/* Assuming that test.txt has content in below
format with 4 row and 3 column
NAME AGE CITY
aaa 21 xxxxx
bbb 23 yyyyy
ccc 24 zzzzz
ddd 25 qqqqqq */
char* buffer[100];
while (fscanf(ptr,"%*s %*s %s ",buffer)==1)
{
count++;
//printf("%s\n", buffer);
}
// if there are column name present in the table in first row
printf("count = %d", (count-1));
return 0;
}

custom string alignment using printf in C

I'm trying to get the following output from the given array
Apples 200 Grapes 900 Bananas Out of stock
Grapefruits 2 Blueberries 100 Orangess Coming soon
Pears 10000
Here's what I came up so far (feels like I'm overdoing it), however, I'm still missing something when padding the columns. I'm open to any suggestions on how to approach this.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
char *fruits[][2] = {
{"Apples", "200"},
{"Grapes", "900"},
{"Bananas", "Out of stock"},
{"Grapefruits", "2"},
{"Blueberries", "100"},
{"Oranges", "Coming soon"},
{"Pears", "10000"},
};
int get_max (int j, int y) {
int n = ARRAY_SIZE(fruits), width = 0, i;
for (i = 0; i < n; i++) {
if (i % j == 0 && strlen(fruits[i][y]) > width) {
width = strlen(fruits[i][y]);
}
}
return width;
}
int main(void) {
int n = ARRAY_SIZE(fruits), i, j;
for (i = 0, j = 1; i < n; i++) {
if (i > 0 && i % 3 == 0) {
printf("\n"); j++;
}
printf("%-*s ", get_max(j, 0), fruits[i][0]);
printf("%-*s ", get_max(j, 1), fruits[i][1]);
}
printf("\n");
return 0;
}
Current output:
Apples 200 Grapes 900 Bananas Out of stock
Grapefruits 2 Blueberries 100 Oranges Coming soon
Pears 10000
You are computing widths wrong. In essence, you want to be able to compute the width of a particular column. Thus, in your get_max function, you should be able to specify a column. We can then pick out the elements from the list based on whether their index mod 3 is equal to the column. This can be accomplished as such:
int get_max (int column, int y) {
...
if (i % 3 == column /* <- change */ && strlen(fruits[i][y]) > width) {
...
}
Then in your main loop, you want to choose the widths of the columns based on what column you are currently in. You can do that by taking the index mod 3:
for (i = 0, j = 1; i < n; i++) {
...
printf("%-*s ", get_max(i % 3 /* change */, 0), fruits[i][0]);
printf("%-*s ", get_max(i % 3 /* change */, 1), fruits[i][1]);
}
This should work as you expect.
I dint try understanding your logic but i think you can space the data using tab with "\t":
printf("%s \t %d","banana", 200);

Resources