Thread: Compressing Code?

  1. #1
    Registered User SCRIPT_KITTEH's Avatar
    Join Date
    Apr 2013
    Posts
    74

    Question Compressing Code?

    Hi folks,

    I'm still trying to master the basics of C & have just written by far the longest program that I've ever written. To most people here it probably isn't that long, but to me it is You see, a lot of the programs I've written are conversion programs (fahrenheit > celcius, bits > Bytes, etc...). So I was thinking, rather than having to remember what I named each of these programs when I want to call them up in the terminal, I could make a program that combines them all, by asking the user what type of conversion they want to do, and then have the program branch off into said type of conversion using the "switch" thing.

    I got my program to work just how I want it to, and it even accounts for bad user input , but I'm wondering if there's a way to like, compress it to improve readability. Right now I only have comments in the code to deal with that, but maybe there's a way to put the code into each case into a function or something?

    Here is the program:

    Code:
    //
    // conversion.c
    //
    // all in one conversion program
    //
    // copyright 2013, script_kitteh
    //
    
    #include <stdio.h>
    
    int main () {
    
        int     conversion_type;            // variables seperated on different lines by category for clarity 
        int     fahr, cel;
        int     b, mb, kb, Byte, kB, mB, gB;
        int     miles, kilometers;
        char     term;
    
        printf ( " \nWhat type of conversion would you like to do? ");
        printf ( "\n\n1. Fahrenheit > Celcius" );
        printf ( "\n2. Celcius > Fahrenheit" );
        printf ( "\n3. bits > Bytes" );                    // programs 3-5 do not allow for negative integers.
        printf ( "\n4. Miles > Kilometers" );
        printf ( "\n5. Kilometers > Miles\n\n");
        
        if ( scanf ( "%i%c", &conversion_type, &term ) != 2 || term != '\n' ) {            // program terminates here if anything other than 1-5 is entered.
            printf ( "\nPlease enter a number, 1-5.\n" );
        }
        else {
            
            switch ( conversion_type ) {
            
                case 1:        // Fahrenheit > Celcius                                     
                    printf ( "\nWhat degree Fahrenheit do you want to know in Celcius?  ");
                    
                    if ( scanf ( "%i%c", &fahr, &term ) !=2 || term != '\n' ) {
                        printf ( "\nThis program requires that you enter an integer.\n" );
                    }
                    else {
                            cel = ( fahr-32 ) / 1.8;
                            printf ( "\n%i degrees Fahrenheit is %i degrees Celcius.\n", fahr, cel );
                    }
                break;
        
                case 2:        // Celcius > Fahrenheit
                    printf ( "\nWhat degrees Celcius do you want to know in Fahrenheit? " );
                    
                    if ( scanf ( "%i%c", &cel, &term ) !=2 || term != '\n' ) {
                        printf ( "\nThis program requires that you enter an integer.\n" );
                    }
                        else {
                        fahr = cel * 1.8 + 32;
                            printf ( "\n%i degrees Celcius is %i degrees Fahrenheit.\n", cel, fahr );
                        }
                break;
        
                case 3:        // bits > Bytes (assumes input is in megabits, as this is most commonly used in advetisements for isp speeds) 
                    printf ( "\nHow many mb do you need converted? " );
    
                            if ( scanf ( "%i%c", &mb, &term ) != 2 || term != '\n' ||  mb < 0 ) {
                                    printf ( "\nThis program requires that you enter a positive integer.\n" );
                            }
                            else {
                                    kb = mb * 1024;
                                    b = kb * 1024;
                                    Byte = b / 8;
                                    kB = Byte / 1024;
                                    mB = kB / 1024;
                                    gB = mb / 1024;
    
                                    if ( kB < 1024 ) {
                            printf ( "\n%i mbps is %i kBps\n", mb, kB );
                        }
                                    else {
                                        printf ( "\n%i mbps  is %i mBps\n", mb, mB );
                                    }
                            }
                break;
        
                case 4:        // Miles > Kilometers
                    printf ( "\nHow many miles do you want to know in kilometers? " );
    
                    if ( scanf ( "%i%c", &miles, &term ) != 2 || term != '\n' || miles < 0 )  {
                        printf ( "\nThis program requires that ou enter a positive integer.\n" );
                    }
                    else {
                        kilometers = miles * 1.6;
                        printf ( "\n%i miles is %i kilometers.\n", miles, kilometers );
                    }
                break;
        
                case 5:     // Kilometers > Miles
                    printf ( "\nHow many kilometers do you want to know in miles? " );
                
                    if ( scanf ( "%i%c", &kilometers, &term ) != 2 || term != '\n' || kilometers < 0 ) {
                        printf ( "\nThis program requires that you enter a positive integer.\n" );
                    }
                    else {
                        miles = kilometers * .6;
                        printf ( "\n%i kilometers is %i miles.\n", kilometers, miles );
                    }
                break;
                // No default case because the surrounding if statement already takes care of bad input.
            }    
            
        }
    
        printf ( "\n" );
        return 0;
    
    }

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    You want a conceptual jump, where a char variable (perhaps) is made in just one line of code, regardless of it's eventual type.

    Instead of 3, 4, or 5 lines of code to get users input, you have just one, probably in a function just for getting users input. Think of your variables for this, like a spoon. You don't have a different spoon for every type of soup - you just use the same spoon, over and over.

    And of course, a new variable to hold all the output, regardless of choices the user makes. Again, a single function for all output.

    Perhaps one more function for all the computations. Let's say you have a function compute(). One parameter for that function, would be the users choice, so compute(parameter1) could be the users choice of what he/she wants to convert.

    Perhaps the call compute(1) means convert Fahrenheit to Celsius.
    Another parameter to compute() might be a string to hold the result of all the computations.

    You see where I'm going with this - a function with a different passed parameter value, can do wildly different things - and it can all go into a single answer string.

    I like your switch statement, but instead of doing all the computations in a series of somewhat repetitive lines of code, call one function, with different parameters.

    It's time to start using functions, and that's a real strong step up in your programming.

    Congrats on your indentation - lovely. No "break" is needed after your last case statement, since there is nothing left to be skipped over.
    Last edited by Adak; 05-25-2013 at 09:15 PM.

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    505
    So you now want to move to writing programs in a way that scales up, rather than naively.
    What's a conversion? It consists of a function which takes a value in one unit and returns it in another, the name of the source units, and the name of the destination units. The function is normally of the form
    ( x - base) * scale + newbase, but it might not be, converting from monthly to annual interest rates is exponential, for example.

    C allows you to specify a function by pointer. Our functions all take a real and return another real, so the format is double function(double x); (If a unit is bits or another integer, we just make sure the double is always an integer).

    Now we can put this information into a structure

    Code:
    typedef struct
    {
       char *unitsto;
       char *unitsfrom;
       double (*fptr)(double x);
    } CONVERSION;
    Now we write as many conversion functions as we want, and put them into a big array. Keep track of the total number of functions you have and #define it as NFUNCTIONS.

    Now, instead of switching, we index into the array, get the unit names to construct the appropriate message, and call the function indirectly.

    So you start with five conversion functions. Then you can just add them to the list. That's all you need to change in the program.

    So you start by going through the list from i = 0 to i = NFUNCTIONS -1, printing out the menu. Get the choice from the user, check it is in range. Then print out a message in the form, "Enter your value in %s\n", table[index].unitsfrom. Get the value, do the conversion, and use the same trick to print out the result.
    (Use %g for a nice human-readable output. If you want to be really fancy, you can put the format string in the table).
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    Registered User SCRIPT_KITTEH's Avatar
    Join Date
    Apr 2013
    Posts
    74
    Hi Adak, Thanks so much for your response!

    Quote Originally Posted by Adak View Post
    You want a conceptual jump, where a char variable (perhaps) is made in just one line of code, regardless of it's eventual type.

    Instead of 3, 4, or 5 lines of code to get users input, you have just one, probably in a function just for getting users input. Think of your variables for this, like a spoon. You don't have a different spoon for every type of soup - you just use the same spoon, over and over.

    And of course, a new variable to hold all the output, regardless of choices the user makes. Again, a single function for all output.

    Perhaps one more function for all the computations. Let's say you have a function compute(). One parameter for that function, would be the users choice, so compute(parameter1) could be the users choice of what he/she wants to convert.

    Perhaps the call compute(1) means convert Fahrenheit to Celsius.
    Another parameter to compute() might be a string to hold the result of all the computations.
    Ohh, so in a program like this you're saying the bulk of the code could be simplified into perhaps 3 functions? Like, "function getinput(), function compute(), function output(), or something? I like your spoon analogy. So it's like we only need one function per type of thing I want to do.

    Quote Originally Posted by Adak View Post
    You see where I'm going with this - a function with a different passed parameter value, can do wildly different things - and it can all go into a single answer string.
    I think so. I'm barely familiar with functions via the C tutorial on this site, but I think I get what you're saying.

    Quote Originally Posted by Adak View Post
    I like your switch statement, but instead of doing all the computations in a series of somewhat repetitive lines of code, call one function, with different parameters.

    It's time to start using functions, and that's a real strong step up in your programming.

    Congrats on your indentation - lovely. No "break" is needed after your last case statement, since there is nothing left to be skipped over.
    Thanks for the encouragement and kind words!

  5. #5
    Registered User SCRIPT_KITTEH's Avatar
    Join Date
    Apr 2013
    Posts
    74
    Thanks for your response, Malcom!

    Quote Originally Posted by Malcolm McLean View Post
    So you now want to move to writing programs in a way that scales up, rather than naively.
    I'm not sure what you mean by scales up

    Quote Originally Posted by Malcolm McLean View Post
    What's a conversion? It consists of a function which takes a value in one unit and returns it in another, the name of the source units, and the name of the destination units. The function is normally of the form
    ( x - base) * scale + newbase, but it might not be, converting from monthly to annual interest rates is exponential, for example.

    C allows you to specify a function by pointer. Our functions all take a real and return another real, so the format is double function(double x); (If a unit is bits or another integer, we just make sure the double is always an integer).

    Now we can put this information into a structure

    Code:
    typedef struct
    {
       char *unitsto;
       char *unitsfrom;
       double (*fptr)(double x);
    } CONVERSION;
    Now we write as many conversion functions as we want, and put them into a big array. Keep track of the total number of functions you have and #define it as NFUNCTIONS.

    Now, instead of switching, we index into the array, get the unit names to construct the appropriate message, and call the function indirectly.

    So you start with five conversion functions. Then you can just add them to the list. That's all you need to change in the program.

    So you start by going through the list from i = 0 to i = NFUNCTIONS -1, printing out the menu. Get the choice from the user, check it is in range. Then print out a message in the form, "Enter your value in %s\n", table[index].unitsfrom. Get the value, do the conversion, and use the same trick to print out the result.
    (Use %g for a nice human-readable output. If you want to be really fancy, you can put the format string in the table).
    I'm embarrassed to say that I did not comprehend much of that, but I appreciate your feedback very much nonetheless & I think once I finish the next part of the C tutorial on this site (pointers, structures, arrays, strings), then maybe I can come back to your comment and have a better understanding I think I'm good for now with learning about making decisions with if/else, switch, and conditional operators, so I'm going to start trying to learn about pointers, structures, arrays & strings now.

  6. #6
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by SCRIPT_KITTEH View Post
    Thanks for your response, Malcom!



    I'm not sure what you mean by scales up



    I'm embarrassed to say that I did not comprehend much of that, but I appreciate your feedback very much nonetheless & I think once I finish the next part of the C tutorial on this site (pointers, structures, arrays, strings), then maybe I can come back to your comment and have a better understanding I think I'm good for now with learning about making decisions with if/else, switch, and conditional operators, so I'm going to start trying to learn about pointers, structures, arrays & strings now.
    Pointers, structures and arrays all work together.
    If you ask "what is C?", a good answer would be "it's the language that allows you to operate directly on memory buffers by means of pointers". Pointers are the soul of C.
    When you've learnt about them, you'll see how we can rewrite your program to operate on any conversion function we can supply, rather than hardcoding the list of allowed conversions.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Who could help me about compressing voice?
    By leetow2003 in forum Windows Programming
    Replies: 5
    Last Post: 12-24-2011, 05:50 AM
  2. Compressing problem
    By Stenland in forum C Programming
    Replies: 7
    Last Post: 10-22-2009, 05:02 PM
  3. Compressing
    By C_ntua in forum C Programming
    Replies: 2
    Last Post: 07-17-2008, 06:01 AM
  4. compressing a buffer
    By steve1_rm in forum C Programming
    Replies: 5
    Last Post: 02-29-2008, 02:19 PM
  5. help with compressing images
    By dragunov in forum C Programming
    Replies: 8
    Last Post: 08-31-2007, 05:52 AM