Hey there everyone^^

Im almost finished on my mighty code of mighty... urm, -ness :mrgreen:

The finished code is actually to calcuate displacement thicknesses of various velocity profiles (read from flies as floats) using the trapezium rule.

Its sooo close, ive got a few little bugs remaining tho. Firstly, the first array value always reads in zero, instead of the correct number (in this case 0.3). Secondly, ive totally made a silly math error in the equaiton for the Trap rule, but dont worry about that ill fix it in no time!

If you'd like to compile it with my data, it uses a file of 10 float values as follows:
0.3
0.7
1.2
1.7
2.1
2.5
2.8
3
3
3

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define initial_value 0.07
#define interval 0.125
int read_one_float( float* out_float, FILE *f ) ;
int main(int argc, char *argv[])
{
    while (1)
    {
        system("cls");
        FILE *file_pointer = 0;
        char ch = 0;
        char filename[] = "" ;
        long lSize = 0;
        float tmp_float = 0, *buffer = 0, sum=0;
        int i = 0, j = 0, count;

        // Input filename.
        printf("\nEnter a filename : ");
        gets(filename);

        // Try to open the file.
        if ( (file_pointer = fopen(filename, "rb")) == NULL )
        {
                perror("\nError opening file");
                puts("\nEnter x to exit, any other to try again.");
                if ( (ch = getch()) == 'x')
                break;
        }
        else
        {
        printf("\nFile successfully opened\n");
        // assume total number of floats in file is same as number of new lines + 1.
        // calculate the size of buffer:
            while( EOF != (ch = fgetc(file_pointer)) )
            if( ch == '\n' )
                        lSize++ ;
            lSize++ ;
            rewind (file_pointer);
        // allocate memory to contain the whole file.
            buffer = (float*) malloc (sizeof(float)*lSize);
            if (buffer == NULL) return 1;
            else printf("\n%d bytes of memory allocated to buffer...", sizeof(float)*lSize);
        // copy the file into the buffer.
            while( 0 != read_one_float( &tmp_float, file_pointer ) )
            buffer[i++] = tmp_float ;
            printf("\nNumber of entries read : %d\n\n", i-- );
//================================================================================================================================================
        // calculate the displacement thickness using the Trapezium rule
            for (count=1; count<i; count++)
            sum+=(interval/2)*(1-((buffer[count]/buffer[i-1])))+(1 -((buffer[count-1]/buffer[i-1])));
            printf("boundary layer thickness = %f\n", sum);
        // terminate
            fclose (file_pointer);
            free (buffer);
        // prints values assigned into the array.
            printf("\nData read from file is :\n") ;
            for( j = i; j >= 0; j-- )
            printf("\nbuffer[%d] = %.1f", i-j, buffer[i-j] ) ;
            printf("\n\n") ;
        // waits for user input to continue
            puts("\nEnter x to exit, any other begin again!");
            if ( (ch = getch()) == 'x')
            break;
        }
    }
}
//--------------FUNCTIONS--------------

int read_one_float( float* out_float, FILE *f )
{
        char buf[100] = "" ;
    if (0 == fgets(buf, sizeof buf, f))
    return 0 ;
        *out_float = atof( buf ) ;
    return 1;
}

I suspect the erroneous section of code is lines 48-49!
Again, help with correcting the first array value would be great^^

Chris

Recommended Answers

All 9 Replies

Try printing variables to the screen as key code positions to see if they contain the values you suspect. Like right after the read, display what was read.

>> if ( (file_pointer = fopen(filename, "rb")) == NULL )

The program should be open for reading a text file not a binary file -- "rt" not "rb". for( j = i; j >= 0; j-- ) j should start at (i-1) because the ith row at that point does not contain a valid number.
or just loop the opposite direction for( j = 0; j < i; j++ )

Both answers above are correct. I tested the code in my Unix machine and surprisingly it worked fine. :).
Here I just found some code in my project where we use trapazoidal integration for Positioning Algorithm. Please don't ask me any questions regarding the maths that goes behind this I have no clue. :). And it's working code:

//###################################################
// Function Name    : trapzd()
//
// Description      : This returns the integral of the input function in the given
//                       range using the trapezoidal rule
//
//###################################################

#define FUNC(x) ((*func)(x))

float CCitaComputation::trapzd (float (*func)(float),
                                float zStartValue,
                                float zEndValue,
                                int zNoOfIterations)
{
  static const char *fn = "CCitaComputation::trapzd";
  float x,tnm,lSumFloat,del;
  static float zResultFloat;
  int it,j;

  if (zNoOfIterations== 1)
  {
      return (zResultFloat=0.5*(zEndValue-zStartValue)*(FUNC(zStartValue)+FUNC(zEndValue)));
  }
  else
  {
      for (it=1,j=1;j<zNoOfIterations-1;j++) it <<= 1;
      tnm=it;
      del=(zEndValue-zStartValue)/tnm;                  // This is the spacing of the points to be added.
      x=zStartValue+0.5*del;
      for (lSumFloat=0.0,j=1;j<=it;j++,x+=del) lSumFloat += FUNC(x);

      zResultFloat=0.5*(zResultFloat+(zEndValue-zStartValue)*lSumFloat/tnm);        // This replaces zResultFloat by its refined value.
      return zResultFloat;
  }
}

PS: There is a book called "Numerical recipes in C". It contains implementation for most commonly used match algos/functions in C. Might be useful.

Thnaks for the replies guys^^ I made the small addendum to the code you suggested Ancient Dragon, and although it produces a slightly neater output, it still failes to read the first value in the file :(

And Im sorry I cnat fulfill your request Walt, I have no idea how to do that x_x!

Anyway, I have to submit the code this afternoon, and I fixed the trap rule part (really silly error on my part there, as suspected =P) So 1 little bug shouldnt be too big of a deal.

Wont stop me spending the next 6 hours trying to figure it out though! Ive since decided the error probably lies in this portion of code:

// copy the file into the buffer.
            while( 0 != read_one_float( &tmp_float, file_pointer ) )
                buffer[i++] = tmp_float ;
                printf("\n\tNumber of entries read : %d\n\n", i-- );

you need some braces around that loop

// copy the file into the buffer.
            while( 0 != read_one_float( &tmp_float, file_pointer ) )
            {
                buffer[i] = tmp_float ;
                printf("\n\tNumber of entries read : %d, value: %f\n\n", i , buffer[i]);
                ++i;
            }

> #define FUNC(x) ((*func)(x))
Why? func(x) works just as well, even when it is a function pointer.

> gets(filename);
No points for using gets()

> buffer = (float*) malloc (sizeof(float)*lSize);
There is no need to cast malloc in C either, if you've done things properly.
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1047673478&id=1043284351
At best, it does nothing.
At worst, it hides some important error messages you really ought to fix.

> if (buffer == NULL) return 1;
> while( EOF != (ch = fgetc(file_pointer)) )
Swapping arguments in the hope of trapping unintended assignments is
a) redundant, with most modern compilers being able to tell you anyway. It was a popular trick in the 1980's, but the world has moved on.
b) useless unless you apply the rule consistently in your code.
c) much harder to read than you might imagine.

I see a lot of control structures without braces, which coupled with the complete lack of indentation makes the code REALLY hard to follow.

There is no need to cast malloc in C either, if you've done things properly.

Swapping arguments in the hope of trapping unintended assignments is
a) redundant, with most modern compilers being able to tell you anyway. It was a popular trick in the 1980's, but the world has moved on.
b) useless unless you apply the rule consistently in your code.
c) much harder to read than you might imagine.

I see a lot of control structures without braces, which coupled with the complete lack of indentation makes the code REALLY hard to follow.

Maybe it hasnt occurred to you that ive only been learning C for 5-6 days give or take, in between lectures and other deadlines :sad:

Im quite proud of myself since Sunday night I didnt even know how to cast

printf

!

>Maybe it hasnt occurred to you that ive only been learning C for 5-6 days
>give or take, in between lectures and other deadlines
Unless you're embarrassed that Salem made some astute and accurate observations, I don't see what this has to do with anything. Lack of experience doesn't exempt you from learning good programming practices.

>b) useless unless you apply the rule consistently in your code.
That would be fine, if it were possible to apply the rule consistently and get consistently good results. ;)

This is, shall we say, an exceedingly bad idea:

char filename[] = "" ;
// ...
 
// Input filename.
printf("\nEnter a filename : ");
gets(filename);

First you declare a string that can hold one character; then you use gets() to read it in.

I suggest

char filename[BUFSIZ], *p;

fgets(filename, sizeof filename, stdin);
if((p = strchr(filename, '\n'))) *p = 0;

where BUFSIZ if a constant defined in <stdio.h>: it is usually around 512; and strchr() is in <string.h>.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.