green
green

Reputation: 713

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

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:

enter image description here

enter image description here

Upvotes: 0

Views: 99

Answers (2)

lurker
lurker

Reputation: 58244

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!

Upvotes: 1

Mike
Mike

Reputation: 49403

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.

Upvotes: 1

Related Questions