?
Solved

Error checking with double and dividing the program into 2 modules  (stdout and stdin)

Posted on 2003-03-27
12
Medium Priority
?
308 Views
Last Modified: 2010-04-15
Im trying to make the program exit if the user is not entering a double in startkm and endkm
Here is how the program looks like:
[code]

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

int main ( void )
{
     char line[82];
     int startkm, endkm, last , total = 0 ;
     int no_of_trips = 0;
     float avg_trip_length ;
     int i;
     int count;

     last = -1; /* date being checked when user will enter the first line */
     while ( fgets ( line, sizeof line, stdin ) != NULL )
     {
          //validate(...);
          i = 0; count = 0;
          while (line[i] != '\n' && line[i] != '\0') {
               if (line[i] == '\t') {
                    count++;
               }
               if ( i >= 79 )
               {
                    fprintf ( stderr, "\n The input exceeds 80 characters. " ) ;
                    return EXIT_FAILURE;

               } /* end if, for */
               i++;
          }
          if (count != 4) /*not 4 blank-spaces: error*/
          {
               fprintf(stderr, "\nYou did not enter 5 fields. Error.");
               return EXIT_FAILURE;
          }      

        sscanf( line, "%*[^\t]%d %d%*[^\t]%*[^\n]", &startkm, &endkm ) ;        
        total += ( endkm - startkm ) ;
 
        if ( startkm >= endkm )
        {
           fprintf(stderr, "\n Invalid. Start km must be greater than end km... " ) ;
           return EXIT_FAILURE;

        } /* end if */
     
        if ( startkm < last )
        {
           fprintf(stderr, "\nError! Start km in one record must be greater or less than end km of the previous record. " ) ;
           return EXIT_FAILURE;

        } /* end if */
        no_of_trips++ ;
        last = endkm;
   
     } /* end while */

 avg_trip_length = calc_avg( total, no_of_trips ) ;
 printf( "\n Number of trips: %d \n Total kilometres: %d \n Average trip length: %.2f\n", no_of_trips, total , avg_trip_length ) ;

 return 0 ;
                   
} /* end of main () */

float calc_avg ( int t, int n )
{
 return ( ( float ) t ) / n ;

} /* end of calc_avg () */

[/code]

Now I am not too shure how to check that start km and end km are both decimal numbers and that the program will exit if its not by showing an error..

A easier way would be using StringTok. but Ill need to remove sscanf and I dont have the strength to redo the whole program again

I want the program to read the double of startkm and endkm to read it as a string
Here is what im doing using sscanf but its not giving me the correct error:

[code]
sscanf( line, "%*[^\t a-zA-Z ]%d%*[0-9] %d%*[0-9]%*[^\t a-zA-Z]%*[^\n]", &startkm, &endkm ) ;
[/code]

Should I add an if statement to prove that if the string is not between 0-9 then exit?
thats getting really confusing..
TQ.
0
Comment
Question by:thibo
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
  • 2
  • +1
12 Comments
 
LVL 6

Expert Comment

by:gj62
ID: 8222257
You've got a few things going on here.

First, you keep saying double (which allows decimals, e.g. 5.4356, etc).  

However, you define them as int's, and use %d (for ints), rather than %lf (doubles) in your scanf.

Lastly, I'd recommend that you read the user input into a string, then convert the string into your double (be sure you declare it as a double) using strtod().  You have more flexibility checking for errors that way...
0
 

Author Comment

by:thibo
ID: 8222289
Ok so I would need to do:

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

int main ( void )
{
    char line[82];
    double startkm, endkm,
    int last , total = 0 ;
    int no_of_trips = 0;
    float avg_trip_length ;
    int i;
    int count;

    last = -1; /* date being checked when user will enter the first line */
    while ( fgets ( line, sizeof line, stdin ) != NULL )
    {
         //validate(...);
         i = 0; count = 0;
         while (line[i] != '\n' && line[i] != '\0') {
              if (line[i] == '\t') {
                   count++;
              }
              if ( i >= 79 )
              {
                   fprintf ( stderr, "\n The input exceeds 80 characters. " ) ;
                   return EXIT_FAILURE;

              } /* end if, for */
              i++;
         }
         if (count != 4) /*not 4 blank-spaces: error*/
         {
              fprintf(stderr, "\nYou did not enter 5 fields. Error.");
              return EXIT_FAILURE;
         }      

       sscanf( line, "%*[^\t]%f %f%*[^\t]%*[^\n]", &startkm, &endkm ) ;        
       total += ( endkm - startkm ) ;

       if ( startkm >= endkm )
       {
          fprintf(stderr, "\n Invalid. Start km must be greater than end km... " ) ;
          return EXIT_FAILURE;

       } /* end if */
     
       if ( startkm < last )
       {
          fprintf(stderr, "\nError! Start km in one record must be greater or less than end km of the previous record. " ) ;
          return EXIT_FAILURE;

       } /* end if */
       no_of_trips++ ;
       last = endkm;
 
    } /* end while */

avg_trip_length = calc_avg( total, no_of_trips ) ;
printf( "\n Number of trips: %d \n Total kilometres: %d \n Average trip length: %.2f\n", no_of_trips, total , avg_trip_length ) ;

return 0 ;
                 
} /* end of main () */

float calc_avg ( int t, int n )
{
return ( ( float ) t ) / n ;

} /* end of calc_avg () */

[/code]

Do i need to increment new pointers for converting string into double like for ex.:

char *string, *compString;
.
.
.
string = ?
x = strtod( string, &compString);

TQ.
0
 
LVL 6

Expert Comment

by:gj62
ID: 8222346
I gotta run - on the surface, this looks closer.  However, last and total also need to be doubles to be correct.

You haven't really used strings - you are still using scanf with format specifiers for your numbers.  You can do it this way, but you have less flexibility when checking for errors...

Anyhow, since you are not reading from strings (you said you don't want to use strtok, you can just ignore my recommendation to use strtod.


0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:thibo
ID: 8222367
k ill try it again to make it work
thx for ure help
:)
0
 

Author Comment

by:thibo
ID: 8222460
I tried making all the variables double but it is not compiling properly..
0
 
LVL 8

Accepted Solution

by:
adg080898 earned 200 total points
ID: 8224104
I fixed a few syntax errors and added one validity check. You were mixing floats and doubles and ints. When scanning from scanf you have to be careful about floats and doubles. Use %f for floats and %lf (pronounced ell-eff) for doubles.

Another problem was that there was no prototype for calc_avg so the compiler assumed that it returned int. It doesn't return int and the compiler later notices that it does not return int, giving error messages. I added a prototype to allow the compiler to see that it returns double.

[code]

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

// Prototype for forward reference
double calc_avg ( double t, double n );

int main()
{
   char line[82];
   float startkm, endkm;
   int no_of_trips = 0;
   double total = 0 , avg_trip_length, last ;
   int i;
   int count;

   last = -1; /* date being checked when user will enter the first line */
   while ( fgets ( line, sizeof line, stdin ) != NULL )
   {
        //validate(...);
        i = 0; count = 0;
        while (line[i] != '\n' && line[i] != '\0') {
             if (line[i] == '\t') {
                  count++;
             }
             if ( i >= 79 )
             {
                  fprintf ( stderr, "\n The input exceeds 80 characters. " ) ;
                  return EXIT_FAILURE;

             } /* end if, for */
             i++;
        }
        if (count != 4) /*not 4 blank-spaces: error*/
        {
             fprintf(stderr, "\nYou did not enter 5 fields. Error.");
             return EXIT_FAILURE;
        }      

      i = sscanf( line, "%*[^\t]%f %f%*[^\t]%*[^\n]", &startkm, &endkm ) ;        
       if (i == 0) {
            fprintf(stderr, "\nIgnored line" ) ;
            continue;
       }
       if (i == EOF)
            break;

      total += ( endkm - startkm ) ;

      if ( startkm >= endkm )
      {
         fprintf(stderr, "\n Invalid. Start km must be greater than end km... " ) ;
         return EXIT_FAILURE;

      } /* end if */
   
      if ( startkm < last )
      {
         fprintf(stderr, "\nError! Start km in one record must be greater or less than end km of the previous record. " ) ;
         return EXIT_FAILURE;

      } /* end if */
      no_of_trips++ ;
      last = endkm;
 
   } /* end while */

avg_trip_length = calc_avg( total, no_of_trips ) ;
printf( "\n Number of trips: %d \n Total kilometres: %lf \n Average trip length: %.2lf\n", no_of_trips, total , avg_trip_length ) ;

return 0 ;

} /* end of main () */

double calc_avg ( double t, double n )
{
   return t / n ;
} /* end of calc_avg () */

[code ends]
0
 

Author Comment

by:thibo
ID: 8224533
Thx for your help
But it has already been corrected in another way.
This is how the program is running right now:

[start code]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//#include "Car.h"


float calc_avg ( double, int ) ;


int main ( void )
{
   char line[82], temp1[10], temp2[10];
   double startkm, endkm, total = 0, last ;
   int no_of_trips = 0;
   float avg_trip_length ;
   int i, count;

   last = -1.0 ;

   while (fgets ( line, sizeof line, stdin ) != NULL )
   {
        //validate(...);
        i = 0; count = 0;
        while (line[i] != '\n' && line[i] != '\0') {
             if (line[i] == '\t') {
                  count++;
             }
             if ( i >= 79 )
             {
                  fprintf ( stderr, "\nThe input exceeds 80 characters. " ) ;
                  return EXIT_FAILURE;

             } /* end if, for */
             i++;
        }
        if (count != 4) /*not 4 blank-spaces: error*/
        {
             fprintf(stderr, "\nYou did not enter 5 fields. Error.");
             return EXIT_FAILURE;
        }      

      sscanf( line, "%*[^\t]%s %s%*[^\t]%*[^\n]",  temp1, temp2 );

      for (i = 0 ; temp1[i] != '\0' ; i++)
        {
          if (( ! isdigit ( temp1[i] )) && temp1[i] != '.')
          {
            fprintf( stderr, "\nNot a valid number. " ) ;
            return EXIT_FAILURE ;

             } // end if

        } // end for

        for (i = 0 ; temp2[i] != '\0' ; i ++ )
        {
          if (( ! isdigit ( temp2[i] )) && temp2[i] != '.')
          {
            fprintf( stderr, "\nNot a valid number. " );
            return EXIT_FAILURE ;

             } // end if

        } // end for      

    startkm = atof ( temp1 ) ;
    endkm = atof ( temp2 ) ;
   
      total += ( endkm - startkm ) ;

      if ( startkm >= endkm )
      {
         fprintf(stderr, "\nInvalid. Start km must be less than end km... " ) ;
         return EXIT_FAILURE;

      } /* end if */
   
      if ( startkm < last )
      {
         fprintf(stderr, "\nError! Start km in one record must be greater or less than end km of the previous record. " ) ;
         return EXIT_FAILURE;

      } /* end if */
      no_of_trips++ ;
      last = endkm ;

   } /* end while */

avg_trip_length = calc_avg( total, no_of_trips ) ;
printf( "\n Number of trips: %d \nTotal kilometres: %lf \n Average trip length: %f\n", no_of_trips, total , avg_trip_length ) ;


return 0 ;
                 
} /* end of main () */

float calc_avg ( double t, int n )
{
return  ( ( float ) t ) / n  ;

} /* end of calc_avg () */

[end code]

Its working ok now but i would like now to divide the program into 2 modules and a header file:

a stdin named car.c where the main is:
[code]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "Car.h"

int main ( void )
{
      char line[82];
      int  last , total = 0 ;
      float startkm, endkm;
      int no_of_trips = 0;
      
      float avg_trip_length ;
      int i;
      int count;

      last = -1.0; /* date being checked when user will enter the first line */
      while ( fgets ( line, sizeof line, stdin ) != NULL )
      {
            validateInput(line);
      } /* end while */

 avg_trip_length = calc_avg( total, no_of_trips ) ;
 printf("\n Number of trips: %d \nTotal kilometres: %lf \n Average trip length: %f\n", no_of_trips, total , avg_trip_length);

 return 0 ;
                   
} /* end of main () */
[/code]

However, Im still having problem dividing the program into 2 parts....
The program should read from stdin (Standard Input)which would be in this case "Car.c" containing the main function.
After reading all input records, the program should print (stdout, standard output) the nb of trips, total nb of km and average trip length from another file named "validate.c". He should also check if there are any errors...
and to conclude a header..
This is what i did so far but get errors:

Car.c

[code]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "Car.h"

int main ( void )
{
      char line[82];
      int  last , total = 0 ;
      float startkm, endkm;
      int no_of_trips = 0;
      
      float avg_trip_length ;
      int i;
      int count;

      last = -1.0; /* date being checked when user will enter the first line */
      while ( fgets ( line, sizeof line, stdin ) != NULL )
      {
            validateInput(line);
      } /* end while */

 avg_trip_length = calc_avg( total, no_of_trips ) ;
 printf("\n Number of trips: %d \nTotal kilometres: %lf \n Average trip length: %f\n", no_of_trips, total , avg_trip_length);

 return 0 ;
                   
} /* end of main () */
[/code]

validate.c

[code]

#include "Car.h"

int validateInput(char *line) {
int i, count;
char temp1[10], temp2[10];      
double startkm, endkm, total = 0, last;
int no_of_trips = 0;      
last = -1.0;      


      while (line[i] != '\n' && line[i] != '\0') {
            if (line[i] == '\t') {
                  count++;
            }
            if ( i >= 79 )
            {
                  fprintf( stderr, "\n The input exceeds 80 characters. " );
                  return EXIT_FAILURE;

            } /* end if, for */
            i++;
      }
      if (count != 4) /*not 4 blank-spaces: error*/
      {
            fprintf(stderr, "\nYou did not enter 5 fields. Error.");
            return EXIT_FAILURE;
      }       

   sscanf( line, "%*[^\t]%s %s%*[^\t]%*[^\n]", temp1, temp2 ) ;

   for (i = 0 ; temp1[i] != '\0' ; i++)
        {
          if (( ! isdigit ( temp1[i] )) && temp1[i] != '.')
          {
            fprintf( stderr, "\nNot a valid number. " ) ;
            return EXIT_FAILURE ;

             } // end if

        } // end for

        


      for (i = 0 ; temp2[i] != '\0' ; i ++ )
        {
            if (( ! isdigit ( temp2[i] )) && temp2[i] != '.')
            {
                      fprintf( stderr, "\nNot a valid number. " );
                        return EXIT_FAILURE ;
      
            } // end if

      } // end for      


      startkm = atof ( temp1 );
      endkm = atof ( temp2 );
   
   
   total += ( endkm - startkm );

   if ( startkm >= endkm )
   {
       fprintf(stderr, "\n Invalid. Start km must be less than end km... " );
       return EXIT_FAILURE;

   } /* end if */
 
   if ( startkm < last )
   {
       fprintf(stderr, "\nError! Start km in one record must be greater or less than end km of the previous record. " ) ;
       return EXIT_FAILURE;

   } /* end if */
   no_of_trips++ ;
   last = endkm;


      return ' ';
}

float calc_avg (double t, int n)
{
      return ((float) t) /n;
} /* end of calc_avg () */

[/code]

header named Car.h
[code]

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


float calc_avg ( double, int ) ;
int validateInput(char *);

[/code]




0
 
LVL 8

Expert Comment

by:adg080898
ID: 8229561
What error messages do you get?
0
 

Author Comment

by:thibo
ID: 8229826
its ok adq
working ok now
Thx a lot!
0
 

Author Comment

by:thibo
ID: 8284877
Hi!
This is how my program start (I managed to divid it into 2 modules and a header file):
<code>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "Validate.h"

int main ( void )
{
   char line[82];
   
   float avg_trip_length;
   
   /*If the program is finding an error from validate.c, it will exit from main*/
   while ( fgets ( line, sizeof line, stdin ) != NULL )
   {
        if(validateInput(line) == EXIT_FAILURE)
        {
             return EXIT_FAILURE;
        }


   } /* end while */

/* Get the average trip length from calc_avg and print all the details */

avg_trip_length = calc_avg( totalKM(), TotalTrips() );
printf("\n Number of trips: %d \nTotal kilometres: %f \n Average trip length: %f\n", TotalTrips(), totalKM() , avg_trip_length);

return 0;
               
} /* end of main () */

/* end of Car.c*/
/*******************************/

#include "Validate.h"

int no_of_trips = 0;
double total = 0;


int TotalTrips()
{
   return no_of_trips;
}


double totalKM()
{
   return total;
}


/*Check if the program is finding any errors. If there are no errors, the program will return EXIT_SUCCESS*/
int validateInput(char *line) {

   int i, count;
   char temp1[90], temp2[90];    
   double startkm, endkm;
   static double last;    
   count =0;
   i = 0;

   while (line[i] != '\n' && line[i] != '\0') {
        if (line[i] == '\t') {
             count++;
        }
        if ( i >= 79 )
        {
             fprintf( stderr, "\n The input exceeds 80 characters. " );
             return EXIT_FAILURE;

        } /* end if, for */
        i++;
   }
   if (count != 4) /*not 4 blank-spaces: error*/
   {
        fprintf(stderr, "\nYou did not enter 5 fields. Error ");
        return EXIT_FAILURE;
   }      

   sscanf( line, "%*[^\t]%s %s%*[^\t]%*[^\n]", temp1, temp2 );

   
   for(i = 0 ; temp1[i] != '\0' ; i++)
        {
       if (( ! isdigit ( (int)temp1[i] )) && (int)temp1[i] != '.')
       {
         fprintf( stderr, "\nNot a valid number. " ) ;
         return EXIT_FAILURE ;

          } // end if

     } // end for

   for(i = 0 ; temp2[i] != '\0' ; i ++ )
        {
        if (( ! isdigit ( (int)temp2[i] )) && (int)temp2[i] != '.')
        {
                 fprintf( stderr, "\nNot a valid number. " );
                  return EXIT_FAILURE ;
   
        } // end if

   } // end for      

   /* Converting string to double */

   startkm = atof ( temp1 );
   endkm = atof ( temp2 );


total += ( endkm - startkm );

if ( startkm >= endkm )
{
    fprintf(stderr, "\n Invalid. Start km must be less than end km... " );
    return EXIT_FAILURE;

} /* end if */

if ( startkm < last )
{
    fprintf(stderr, "\nError! Start km in one record > than end km of the previous record. " ) ;
    return EXIT_FAILURE;

} /* end if */
no_of_trips++; /*update numbers of trip */
last = endkm;


   return EXIT_SUCCESS;
}

/* Calcul the average trip length */
float calc_avg (double t, int n)
{
   return ((float) t) /n;
} /* end of calc_avg () */

/*end of validate.c*/

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

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


float calc_avg ( double, int ) ;
int validateInput(char *);
int TotalTrips();
double totalKM();

</code>
/*********************************/
This program should read the log book from a file "opened for reading using buffered I/O":
Now I would like to add some details to it:
Add --> From To Distance Date, add a trip from "FROM" to "TO" with a given "DISTANCE" kilometres.
DEL --> Remove an edge from "FROM" to "TO". Print an error message if one or both of "FROM" or "TO" dont exist.
EXIT --> exit the program
SUMMARY --> Print a summary of all the trips so far, including the number of trips, the total number of km travelled, the avarge trip length, and the standard deviation of trip lengths.

The output for this log data should be:
Number of trips:
Total kilometres:
Average trip length:
Standard deviation: which is a measure of how spread out a distribution is. The standard deviation 's' is simply the square root of the variance, ie s=sqrt(s^2).

This is how the program is now running:
example of input:
Name-Startkm-endkm-date      -location
Bob  23000  23100 18/01/2004  NY
Tom  23100  23250 19/02/2001  London
Ann  23250  23280 20/03/2003  Berlin
Ann  23500  23550 22/06/2003  NY

The output after pressing control d:
Number of trips:        4
Total kilometres:     330
Average trip length:   82.5

This is what the output should add after average trip length
Standard deviation:    53.77

And if the user wants to add or delete some details or print summary (INPUT = prompt from the program):

INPUT: del  Berlin NY
INPUT: add Berlin NY 100 23/03/2003
INPUT: summary
Number of trips:        4
Total kilometres:     380
Average trip length:   95
Standard deviation:    49.33

Any idea? :)
0
 
LVL 20

Expert Comment

by:jmcg
ID: 10194641
Nothing has happened on this question in more than 9 months. It's time for cleanup!

My recommendation, which I will post in the Cleanup topic area, is to
accept answer by adg (or delete as homework).

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

jmcg
EE Cleanup Volunteer
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
Suggested Courses

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question