Sixth Week Examples:
  Writing to a file. Reading a file.
  Greatest Common Divisor.

Following D. Milicic Sixth Week Examples, Eighth Week Examples.

Writing to a file


/**********************************************************************
A. Treibergs                                                      2-8-6

Program that opens a text file called "output.txt", writes to it, and 
closes it. The file can be read by any text editor or program that 
reads text files.

write_file.c
**********************************************************************/

# include <stdlib.h>
# include <stdio.h>
# include <math.h>



int 
main(void)
{
    int i;
    FILE *fp;                            /* Declaration of file variable */

    fp = fopen ( "output.txt", "w" );    /* Before a file can be used, it must be opened. */
                                         /* fopen returns a pointer to the file. */
                                         /* "w" for writing files, "r" for reading. */

    fprintf (fp, " Angle \t\t Sine \n" );        
    fprintf (fp, "-------  ---------------\n" );
    for ( i = 0; i <= 90; i++ )
                fprintf ( fp, "%6d \t %f21.15\n", i, sin( i * M_PI / 180.0 ) );

    fclose ( fp );                        /* closing returns file to system. */
                                          /* Newly written data may be lost without closing the file */


    return EXIT_SUCCESS;
}


Reading from a file

The first line of some data files (counter controlled files) contain the number of records (lines) in the data file. Then the lines may be read one by one inside a loop that executes that number of times. Other data files put distinctive flags or "sentinel signals" (for example -9999.9) that can be tested to detect the end of data. We shall demonstrate the third type, in which the program knows when the data ends when it hits the end of file mark. The fscanf not only reads the the data into the variables but also returns the number successfully read.
/**********************************************************************
A. Treibergs                                                      2-8-6

Program that opens a text file called "data.txt" reads from it, performs 
a calculation and closes the file. "data.txt" is assumed to be a text file
that contains double precision numbers separated by white space (line feeds,
tabs or blanks). The program will continue reading one number at a time 
until the end of file is reached. The program counts the number of data 
observations, and computes the mean of the sample.

read_file.c
**********************************************************************/

# include <stdlib.h>
# include <stdio.h>
# define FILENAME "data.txt"             /* macro for file name. You type it once here. */
                                         /* define inserts "data.txt" at every occurrence of FILENAME */

int 
main(void)
{
    int n;
    double x, sum;  
    FILE *fp;                            /* Declaration of file variable */

    n=0;
    sum=0.0;

    fp = fopen ( FILENAME, "r" );    /* Before a file can be used, it must be opened. */
    if( fp == NULL)
             {
              printf("Unable to read the file \"%s\"\n", FILENAME);
             }
    else
             {
              while( (fscanf(fp, "%lf", &x)) ==  1  )  /* fscanf reads x, returns number of vars read */
                 {
                       sum = sum + x;
                       n = n + 1;
                 }
              printf(" The data in file \"%s\" had %d observations\n with mean = %f\n",FILENAME, n,sum/n);
             }
 
     fclose ( fp );    /* closing returns file to system. */

    
    return EXIT_SUCCESS;
}


The file being read is called "data.txt". Here is an example of this file:
1 2 3 4 5 6 7 8 9 1.012345678e1
-1.0
-2
-3
-4
-5
-6 -7.0 -8 -9

An Easier Way to Read a Data File: UNIX "<" operator.


The system can replace the normal keyboard input by a data file. The data file is called when the executable file is run:

a.out <data2.txt

A data file that contains typographical errors, data2.txt is given after the program. The program reads only the data on the uncorrupted lines.


/**********************************************************************
A. Treibergs                                                     2-13-6

Program that opens a text file for reading. Inside the program the file is called 
"stdin" which is normally reserved for console.
To associate a data file name to stdin, on the call, add a pipe naming the input file:

a.out <data2.txt

This program expects two double precision number on each line, terminated by a \n.
It reads lines until it hits an end-of-file. If the data is corrupted so the
program cant read the numbers, it skips to the next record=line.

We could have used scanf to convert the incoming stream. In this program
however, we read the record in as a string, and then convert the string to numbers.
This handles garbage in the data better than directly using scanf.
Try corrupting the data file to see what happens.

read_file.c
**********************************************************************/

# include <stdlib.h>
# include <stdio.h>



int 
main(void)
{
    int  lines=0, m;
    double x,y;
    char inrecord[100];           /* More stable to read the input line as char string */



    while( fgets(inrecord,99,stdin) != NULL)   /*  fgets picks up input string terminated by nextline. 
                                                   fgets returns NULL when it tries to read an end-of-file. */
    {
        printf("%s\n",inrecord);               /* We just dump the incoming string, to see what happens with garbage chars. */
        m=sscanf(inrecord, "%lf %lf", &x,&y);  /* sscanf converts incoming stream from string inrecord, just as scanf
                                               /* converts incoming from stdin, using the format conversion specifier string. */
        if (m < 2) continue;                   /* sscanf returns the number of variables successfully converted. It returns -1 
                                               /* if it tries to convert an end of file. Here we skip to next loop if all vars not right. */


        printf("%22.15f %22.15f  %d\n", x, y,m); /* here all vars are present and correct. We just print them to see. */
        lines++;
    }

    printf(" %d records successfully read.\n",lines);
    

    return EXIT_SUCCESS;
}



The corrupted data file data2.txt
1.0  3.3
2.1  3.x
3.5  5.1
6.6  3e1
hh7.7  12
2.2 0.7e1
9.4  15.2




Greatest common divisor


/**********************************************************************
A. Treibergs                                                      2-9-6

Euclid's Algorithm. Given positive integers m,n (m>n) find positive
integers so that
     m  =    q_1    n      +   r_1
     n  =    q_2   r_1     +   r_2
    r_1 =    q_3   r_2     +   r_3
        .
        .
        .
r_(n-2) =    q_n   r_(n-1) +   r_n
r_(n-1) =  q_(n+1) r_n     +    0.

Then  gcd(m,n) = r_n (>0).

euclid.c
**********************************************************************/

# include <stdio.h>
# include <stdlib.h>

int 
main(void) 
{
   int m, n, p, q, r;

   printf ( "Euclid's Algorithm\n\n Enter two positive integers : ");
   scanf ( "%d %d", &n, &m);
   p=abs (m);
   q=abs (n);
        
   if ( p+q > 0 )
   {
           if( q == 0 )                        /* swap p and q if q is zero */
           {
                    r = p;
                    p = q;
                    q = r;
            }
           do                                 /* do Euclid's algorithm */
           {                             
                    r = p % q;
                    printf ( "%15d = %d * %d  +  %d\n", p, p/q, q, r);
                    p = q;
                    q = r;
           }
           while ( r != 0);

           printf ( " The greatest common divisor is %d.\n", p);
           if (p == 1)
                    printf ( " The numbers are relatively prime.\n");
    }
    else
           printf ( "At least one number must be nonzero.\n");

    return EXIT_SUCCESS;
}



Recursive GCD


/**********************************************************************
A. Treibergs                                                      2-9-6

Euclid's Algorithm via recursive functions

euclid2.c
**********************************************************************/

# include <stdio.h>
# include <stdlib.h>


int 
gcd(int a, int b)
{
   int q, res;

   q = a % b;
   if (q == 0)
          res = b;
   else
          res = gcd ( b, q );

  return ( res );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

int 
main(void) 
{
   int n, m, g;

   printf ("Recursive Euclid's Algorithm\n\n Enter two positive integers : ");
   scanf ("%d %d", &n, &m );

   g = gcd( m, n );

   printf ( " The largest common divisor is %d\n", g );
   if ( g == 1)
           printf ( " The numbers are relatively prime.\n");

   return EXIT_SUCCESS;
}


Easier way to write a file: UNIX ">" operator.


/**********************************************************************
A. Treibergs                                                     2-13-6

Program that opens a text file. Inside the program the file is called 
"stdout." the prog writes to it and closes it. 
To identify the file name, on the call

a.out >dat3.txt

You can print the file, e.g., via

cat dat3.txt


The file can be read by any text editor or program that 
reads text files.

today.c
**********************************************************************/

# include <stdlib.h>
# include <stdio.h>
# include <math.h>



int 
main(void)
{
    int i;

    fprintf (stdout, " Angle \t\t Sine \n" );        
    fprintf (stdout, "-------      -----------------\n" );
    for ( i = 0; i <= 90; i++ )
                fprintf ( stdout, "%6d \t %21.15f\n", i, sin( i * M_PI / 180.0 ) );

    fclose ( stdout );                        /* closing returns file to system. */
                                          /* Newly written data may be lost without closing the file */


    return EXIT_SUCCESS;
}

The first few lines of the file created by the program, dat3.txt
 Angle 		 Sine 
-------      ---------------
     0 	     0.000000000000000
     1 	     0.017452406437284
     2 	     0.034899496702501
     3 	     0.052335956242944
     4 	     0.069756473744125
     5 	     0.087155742747658
     6 	     0.104528463267653
    . . . . . . .