Sunday 8 December 2013

Detect Key-Press Without Pausing Program Execution: kbhit()

kbhit() allows us to keep the program going as it looks for a keypress.

getch(), getche() and getchar() all let us accept keyboard input, but the program will pause while it waits for that key hit.

kbhit() can be used effectively with if/else to get the keyhit without pausing the program. That's what I used for the snake game in my previous post. It let me keep the snake going as it was also 'keyboard aware' at the same time. You have to include conio.h to use kbhit().

The comments in the program will help explain it better:

#include <stdio.h>
#include <conio.h>

int main()
{
    char c='N'; //N is assigned to c

    for(;;) //infinite loop
    {
        printf("%c\t",c); //N is printed over and over
        if(kbhit()) //until a key is hit, the keyvalue is stored in the buffer
        {
            c=getch(); //c is fed the value from the buffer. The program does not pause here
            printf("%c",c); //print the key
            break; //break the loop
        }
    }
    getch(); //yes, the program does pause here.
    return 0;
}

Saturday 30 November 2013

The Old Snake Game

This is actually an edited post. Been thinking of posting 4 times at least, in a month. I didn't want November to slip by, so I quickly posted a random song on the last night of November, to save the spot.

Anyway, this is a crude recreation of the old snake game. The game was invented by Scott McCarthy and was first published in 1976.

I'm still working on the database for the doctor. Hit some glitches that have been giving me sleepless nights. So I decided to take a break and try to write the snake game we used to play on our B&W Nokias.

The fact that the food may appear within the body of the snake sometimes is NOT A BUG, it's sheer laziness.
Besides that it's sure to have some bugs, I haven't played it much, if you find some let me know in the comments section.

I have set the variable 'speed' to 5000 (If you copy paste this into C:B, it should be line 14). Decreasing this number will speed the game up, increasing this will slow the game down.

If you don't already have the include file myconstdwin.h, click HERE to find out how to create it yourself.

The snake is controlled with the arrow keys, hitting Esc will exit the game or if you say 'No' to "Play Again?".

If you are new to earth, welcome to the planet and here are the game instructions :P
The objective of the game is to "eat" as many of the food as you can without hitting the borders, and without crashing into your own body as you coil around. 'Eating', here, means crashing head-long into the food, the snake will keep moving in the direction you point it in.
When you eat one, another piece of food appears in a random spot. Every piece of food you eat increases the snakes length.

Nothing else I can think of saying, so here's the code:


#include <myconstdwin.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

void time_seed(void); //seed randomizer from the clock
int random(int range); //this generates a random number. The "range" is how big you want the number to be
int get_key(void); //detect keys

void draw_box(void);
void food(int x,int y); //displays food
void snake(int *sxt,int *syt,int *sxh,int *syh); //sxt= snake x coordinate of tail

int pause,direction=3; //direction, counting from left, clockwise: left=1,up=2,right=3,down=4
int len=2,speed=5000,redo=0; //len (length of snake is actually 3 in the beginning, but we are counting from 0.

int main(void)
{
    int i,sx[500],sy[500],key,points=0;
    /**co-ordinates sx[0],sy[0] will always be the tail, sx[len],sy[len] the head**/
    sx[0]=23,sx[1]=24,sx[2]=25,sy[0]=7,sy[1]=7,sy[2]=7;
    int foodx,foody;
    int again=1,game;
    char c;

    while(again)
    {

        system("cls");
        gotoxy(1,17);
        printf("Points: %i",points);
        game=1;
        draw_box();
        /**Snake**/
        for(i=0;i<len;++i)
        {
            gotoxy(sx[i],sy[0]);
            printf("%c",15);
        }

        time_seed();
        foodx=random(43);
        foody=random(14);

        food(foodx+1,foody+1);

        while(game)
        {
            if(sx[len]==foodx+1 && sy[len]==foody+1) //if the head and food are at the same spot
            {
                food(foodx+1,foody+1);
                printf("\b \b%c",15);
                /**create new food**/
                time_seed(); //seed randomizer with clock
                foodx=random(43); //create a random number range upto 43
                foody=random(13); //create a random number range 13

                food(foodx+1,foody+1); //the +1 prevent the food from appearing at the lines
                len++; //increase length
                if(direction==1 || direction==3)
                {
                    if(direction==1)
                        sx[len]=sx[len-1]-1;
                    else if(direction==3)
                        sx[len]=sx[len-1]+1;

                    sy[len]=sy[len-1];
                }
                else
                {
                    if(direction==2)
                        sy[len]=sy[len-1]-1;
                    else if(direction==4)
                        sy[len]=sy[len-1]+1;
                    sx[len]=sx[len-1];
                }
                points+=10;
                gotoxy(1,17);
                printf("Points: %i",points);
            }

            snake(&sx[0],&sy[0],&sx[len],&sy[len]);

            if(redo==1)
            {
                /**if the food appears within the snakes body, the next line prevents the food
                   from disappearing when the snake has finished passing through it**/
                food(foodx+1,foody+1);

                for(i=0;i<len-1;i++)
                {
                    if((sx[len]==sx[i] && sy[len]==sy[i]) || (sx[len]==46) || (sy[len]==15) || (sx[len]==0) || (sy[len]==0))
                    {
                        gotoxy(19,17);
                        printf("OOPS!!! Play Again(Y/N): ");
                        while(1)
                        {
                            c=toupper(getch());
                            if(c=='N')
                            {
                                game=0;
                                again=0;
                                system("cls");
                                break;
                            }
                            else if(c=='Y')
                            {
                                game=0;
                                len=2,redo=0,points=0;
                                sx[0]=23,sx[1]=24,sx[2]=25,sy[0]=7,sy[1]=7,sy[2]=7;
                                direction=3;
                                break;
                            }
                        }
                        break;
                    }
                }

                for(i=0;i<len;i++)
                {
                    sx[i]=sx[1+i];
                    sy[i]=sy[1+i];
                }

                if(direction==1) //going left
                {
                    sy[len]=sy[len-1];
                    sx[len]--;
                }
                else if(direction==2) //going up
                {
                    sy[len]--;
                }
                else if(direction==3) //going right
                {
                    sy[len]=sy[len-1];
                    sx[len]++;
                }
                else if(direction==4) //going down.
                {
                    sy[len]++;
                }
                redo=0;
            }

            if(kbhit())
            {
                key=get_key();

                if(key==584) //up
                {
                    if(direction==1 || direction==3)
                    {
                        direction=2;
                    }
                }
                else if(key==592) //down
                {
                    if(direction==1 || direction==3)
                    {
                        direction=4;
                    }
                }
                else if(key==587) //left
                {
                    if(direction==2 || direction==4)
                    {
                        direction=1;
                    }
                }
                else if(key==589) //right
                {
                    if(direction==2 || direction==4)
                    {
                        direction=3;
                    }
                }
                else if(key==27) //esc
                {
                    exit(0);
                }
            }
        }
    }

    return 0;
}

void food(int x,int y)
{
    gotoxy(x,y);
    printf("%c",219);
}

void snake(int *sxt,int *syt,int *sxh,int *syh)
{
    pause++;

    if(pause==speed) //this controls game speed
    {
        redo=1;
        gotoxy(*sxt,*syt);
        printf(" ");
        gotoxy(*sxh,*syh);
        printf("%c",15);

        pause=0;
    }
}

void draw_box(void)
{
    int i;

    /**Draw Box**/
    gotoxy(0,0);
    printf("%c",218);
    for(i=0;i<45;i++)
    {
        printf("%c",196);
    }
    printf("%c",191);
    for(i=0;i<15;i++)
    {
        gotoxy(0,1+i);
        printf("%c",179);
        gotoxy(46,1+i);
        printf("%c",179);
    }
    gotoxy(0,15);
    printf("%c",192);
    for(i=0;i<45;i++)
    {
        printf("%c",196);
    }
    printf("%c",217);
}

int random(int range)
{
    int y;
    y=rand()%range;
    return(y);
}

void time_seed(void)
{
    srand((unsigned)time(NULL));
}

int get_key()
{
    int c=getch();
    switch(c)
    {
      case 0:   return getch()+256;
      case 224: return getch()+512;
    }
    return c;
}

Monday 25 November 2013

Sort 5 Names According To The First Character

This was a LOT harder than I thought it would be.

I want to be able to sort a list of names. I have been trying to do this and this is possibly the hardest problem I've had to solve.

I have heard of functions that can sort stuff for you, maybe library functions or maybe functions off of the internet, but I was adamant on writing my own with no help.

It took me a couple of days to get this right. Even then, it can only compare the first characters and sort accordingly.

If I can muster up the courage I'll try to make it so that it can sort the rest of the letters too; 'dictionary entry' like. But for now, this will have to do, because it represents a lot of hard work for me :).

It accepts 5 names and sorts them according to the first character. There is no check to ensure small letters or big letters, so THE PROGRAM WILL ALWAYS CONSIDER SMALL LETTERS TO BE HIGHER THAN BIG LETTERS: Eg. 'banana' will figure as higher than 'Zebra', so on the list 'banana' will be below 'Zebra', because to the program, small letter 'b' is larger than big letter 'Z'.

#include <stdio.h>
#include <strings.h>

int main()
{
    int a,b=0,found=0;;
    char names1[5][21],names2[5][21],sorted[5][21];

    printf("Enter 5 names:\n");
    for(a=0;a<5;a++)
    {
        gets(names1[a]);
    }

    /**Make a copy of the original array so as not to lose
    the original input order**/
    for(a=0;a<5;a++)
    {
        strcpy(names2[a],names1[a]);
    }

    /**Sort Here**/
    while(b<5)
    {
        for(a=b;a+1<5;a++)
        {
            if(names1[b][0]>names1[a+1][0])
            {
                strcpy(sorted[b],names1[a+1]); //copy the smaller in order into sorted.
                strcpy(names1[a+1],names1[b]); //copy what was being compared into the one already saved in sorted
                strcpy(names1[b],sorted[b]); //start comparing the smaller one
                found=1; //so that we know a smaller character has been found
            }
        }

        if(found==0) //nothing was found
        {
            strcpy(sorted[b],names1[b]); //what was being compared is the smallest, copy into sorted
        }
        b++; //go on to the next item
        found=0; //reset found
    }

    system("cls");

    for(a=0;a<5;a++)
    {
        printf("\n%s\t%s",names2[a],sorted[a]);
    }
    return 0;
}


Thursday 21 November 2013

Programmers & Programming Windows (Contains no code)

In my C learning crusade, I have traveled at light speeds across many forums, write-ups and e-books (Well, the loading takes a while though considering my internet speed, but the data is still sent at light speed anyways, no matter how small the chunks are). I have lurked in the shadows, reading, scrolling, judging lines and lines of text; I have chuckled, smirked and been relieved many a time.

I have come to the one, inevitable, conclusion: Programmers are dicks!

Not all of them, but many of them. A lot of them take the "If I tell you everything, you'll never learn" thing too far. No, nobody has ever done that to me. As far as I can remember, the only post I made in a public forum regarding programming was at the Code Blocks forums asking about a feature which was promptly resolved in their nightly releases. I only judge what I read...hehe!

Sometimes, even a simple question like "How do I draw a circle?" is responded with "How much are you paying?".

Well, it only strengthens my resolve to be nice. If I ever get to the level of expertise where I am able to help out people, I will go out of my way to be nice & will never be the first one to cast the first crap.


In other news:
I have been trying hard to understand Programming Windows by Charles Petzold. This is supposedly THE book to learn Windows Programming. But it is beyond my comprehension. It was written for people who can speak 'tech' much better than I do.
Not to be undone, I e-mailed Dan Gookin. Gookin is the author of 'C For Dummies' and a host of other books. If I'm not mistaken, it was his book "DOS for Dummies" that birthed the whole "For Dummies" series. Legend.
I asked him if he could do a book on Windows Programming for laymen...well...for 'Dummies', in his unmistakable, humorous and understandable style. It would help someone like me, who wants to learn, but have no good resource or teacher, to get started.
He was very kind and forwarded my e-mail to his publisher to see if they were willing to accommodate a new book.
The publisher's money making instincts did a quick calculation and the returns didn't seem appealing, so they refused. Not their fault, profit is what they are in the business for, they are not a charity. They already did some books on it and those never sold well.

Mr. Gookin told me he is swamped with work at the moment but he will try to introduce a new segment in his blog to introduce us to Windows Programming very soon. Apparently Programming Windows by Charles Petzold is the only book on Windows Programming he has ever bought. And he uses Java to program Windows.
Regardless, I am very eagerly looking forward to his posts on the subject. His C Programming blog is a goldmine. Check this out: A few days back, I dusted off my old book on games programming Game Programming On PC by Diana Gruber. I cannot use the book to program games because the code will not work on Windows 7 (Which is what I use), but I thought maybe I can pick up a few things from scanning the code (FYI, I didn't learn anything, not because the book is hard, but because I'm too dumb). There is a part where she says about a memory location "There is something in there, I don't know what it is, but there is something" (may not be the exact words, but it was the same idea). This was written in the early 90's so she very likely has learnt what is in there since.
I KNEW WHAT WAS THERE....yup I did! I had picked it up from Gookin's blog. :) Knowing is always an ego boost.

If you want to follow his blog here it is: http://www.c-for-dummies.com/cfordummies/
Go there and click on "C Blog" on the left pane.

See you soon.

Getting File Path From The User/Adding User Entered String As Part Of A Longer String

Here is a program to get a text file path and name from the user. These are then saved as a single string into another char variable. Then the file is opened and displayed.


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

int main()
{
    char path[100],fname[100],complete[200],ch;
    FILE *fp;

    printf("Please enter the path to the text file (eg: c:\\users\\johnsmith\\: ");
    gets(path);
    printf("Enter the name of the file (eg:MyText.txt): ");
    gets(fname);

    sprintf(complete,"%s%s",path,fname); //this works exactly like printf, except the output is sent to the 'complete' variable.

    fp=fopen(complete,"r");
    if(fp==NULL)
    {
        printf("Cannot open file. Sorry :(");
        getch();
        exit(0);
    }

    while(ch!=EOF)
    {
        ch=fgetc(fp);
        printf("%c",ch);
    }
    fclose(fp);

    return 0;
}


Sprintf is important to me because I need it to run user defined commands in the DOS command line. Eg:
If I want to delete a file the user names, I prompt for the file and get its name:

printf("Enter filename: ");
gets(filename); //assume the user enters 'MyFile.exe'

sprintf(command,"delete %s",filename);

If the user entered 'MyFile.exe', the variable 'command' now contains the string 'delete MyFile.exe'. Now I can delete this file by saying:
system(command);

It comes in really handy sometimes.

Tuesday 29 October 2013

Hide/Resize TEXT Cursor

Although I doubt I'll be doing this much longer, right now I'm writing drop-down menus, keyboard navigation menus, highlight/de-highlight selections all in the console window. Suppose the user is going to select one out of three items using the arrow keys. S/He has the options on the screen and one of them is highlighted, but there's a blinking cursor in one part of the screen :(
Although it means nothing because we have deactivated most of the keys on the keyboard, it's distracting.
Also if the user is scrolling through many pages of text, they can see flashes of the cursor as it clears the screen and as the new text is written.

So, how do we hide the cursor?

If we want to hide or re-size the text cursor in the console window, we will have to look at Windows programming.

I've put them in 2 functions. The first function (cursor_hide) hides the cursor, the second one (cursor_show) brings it back.

You will notice that the functions also allow you to change the cursor size. A minimum of 10, which is the old blinking line, to a maximum of 100, which is a blinking box. I used a global variable x. Changing its value changes the cursor size. If you do not foresee having to change the cursor size within the course of your program, just set it directly- like so: ConCurInf.dwSize=10;

Here is the code.


#include <windows.h>
#include <stdio.h>
#include <conio.h>

void cursor(void);
void cursor1(void);
int x=10;

void cursor_hide(void);
void cursor_show(void);

int main()
{
    cursor_hide();
    printf("Cursor Gone\n");
    getch();
    cursor_show();
    printf("Cursor Back\n");
    getch();
    x=100;
    cursor_show();
    printf("Cursor big. (Upto 100)\n");
    getch();
    x=10;
    cursor_show();
    printf("Cursor Small. (Downto 10)\n");
    getch();
    return 0;
}

void cursor_hide(void)
{
    HANDLE hOut;
    CONSOLE_CURSOR_INFO ConCurInf;

    hOut=GetStdHandle(STD_OUTPUT_HANDLE);

    ConCurInf.dwSize=x;
    ConCurInf.bVisible=FALSE;

    SetConsoleCursorInfo(hOut, &ConCurInf);
}

void cursor_show(void)
{
    HANDLE hOut;
    CONSOLE_CURSOR_INFO ConCurInf;
    hOut=GetStdHandle(STD_OUTPUT_HANDLE);

    ConCurInf.dwSize=x;
    ConCurInf.bVisible=TRUE;

    SetConsoleCursorInfo(hOut, &ConCurInf);
}

Monday 28 October 2013

Basic Encryption/Decryption Of Your Data

If I am on a computer frequented by others and I have a personal file on there, I'll change it's name including the extension, or just leave it without an extension.
Eg. if I have a file 'Porn.Jpg', I'll rename it to 'Language.dll' or 'winhelp', so someone who sees that file usually will not wonder about it, because it looks like an official Windows file.
I used to use batch files to do this for multiple files.....good old DOS.

/*"But I do not see my file extensions :(". Open 'My Computer'>Alt+t>Folder Options>View>Uncheck 'Hide Extensions For Known File Types'>Ok. You will now be able to see your extensions. Check it back to undo this.*/

Sometimes they may be notepad files that I do not want others to read. It may contain my financial information, my recent online transactions, some less important passwords - we need so many passwords these days, and we don't want to use the same one for everything. If someone figures out one password, they have access to everything.

Besides renaming the extension, we can also use something like the following program to 'encrypt' the file. Admittedly it is a weak encryption, but that's okay because it's not like our problem is an intelligence agency trying to decrypt our stuff. If you do have that problem, I'm sure you know of better ways to hide your data.
But please, do not save your online banking password, Credit Card numbers etc. like this. The REALLY important stuff you NEED to memorize.

This encryption adds 100 to the ASCII value of each character and writes it to file, so it looks like gibberish when opened in notepad. But you can use the program to read it. You can change the 100 to any number.

For this program to work it will create a folder called 'MyFolder' in your C drive with a file called 'MyFile.dll' in it when you run it for the first time.
But if it is encrypted, why make it a '.dll' extension? Well, so that no one deletes it for one and also now it is double encrypted!!! Yeahhhhhh <nods head slowly>!
Run the program, choose to Enter Text, View File or Exit. If you press 'e', you can enter the text you want to record encrypted. Press 'v' and you can see all entries. Press 'x' and the program exits.

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

void dc_dll(void);
void ec_dll(void);

FILE *fs,*ft;
char ch;

int main()
{
    char c,input[1000];

    fs=fopen("C:\\myfolder\\MyFile.dll","a");
    if(fs==NULL)
    {
        system("md c:\\MyFolder 2>nul");
        fs=fopen("c:\\myfolder\\MyFile.dll","w");
        if(fs==NULL)
        {
            printf("Cannot open C:\\MyFolder\\MyFile.dll. So bad :(");
            getch();
            exit(0);
        }
        fclose(fs);
        ec_dll();
    }
    else
    {
        fclose(fs);
    }
    printf("Enter Text, View File or Exit? (E/V/X)");
    while(1)
    {
        fflush(stdin);
        c=toupper(getch());
        if(c=='E')
        {
            printf("\nEnter text to save...\n");
            gets(input);
            dc_dll();
            fs=fopen("c:\\myfolder\\MyFile.dll","a");
            fprintf(fs,"%s\n\n",input);
            fclose(fs);
            ec_dll();
        }
        else if(c=='V')
        {
            printf("\n");
            dc_dll();
            fs=fopen("c:\\myfolder\\MyFile.dll","r");
            while(1)
            {
                ch=fgetc(fs);
                if(ch==EOF)
                {
                    break;
                }
                printf("%c",ch);
            }
            fclose(fs);
            ec_dll();
            printf("\nPress any key.....");
            getch();
        }
        else if(c=='X')
        {
            exit(0);
        }
        system("cls");
        printf("Enter Text, View File or Exit? (E/V/X)");
    }
    return 0;
}

void ec_dll(void)
{
    fs=fopen("c:\\MyFolder\\MyFile.dll","r");
    ft=fopen("c:\\MyFolder\\Data.temp","w");
    while(1)
    {
        ch=fgetc(fs);
        if(ch==EOF)
        {
            break;
        }
        fputc(ch+100,ft);

    }
    fclose(fs);
    fclose(ft);
    system("del c:\\MyFolder\\MyFile.dll");
    system("ren c:\\MyFolder\\Data.temp MyFile.dll");
}

void dc_dll(void)
{

    fs=fopen("c:\\MyFolder\\MyFile.dll","r");
    ft=fopen("c:\\MyFolder\\Data.temp","w");
    while(1)
    {
        ch=fgetc(fs);
        if(ch==EOF)
        {
            break;
        }
        fputc(ch-100,ft);

    }
    fclose(fs);
    fclose(ft);
    system("del c:\\MyFolder\\MyFile.dll");
    system("ren c:\\MyFolder\\Data.temp MyFile.dll");
}

Printing a String in Uppercase (No toupper)

This seems to be a common 'to do' exercise. When I first saw this question, I always felt it shouldn't be too hard to do. And it isn't.
I posted a program to do this using toupper() to 'UPPER-CASE' each individual character (Print a String All In Uppercase), this program does not use the toupper() function, at least not the lib function, it rather uses our own toupper code.
This program will accept a string, print each character individually, if any of the characters is lower-case 'a' to 'z' (ASCII character code 97 to 122), it will be printed as the same character, but in uppercase. How?
Well, the ASCII code for 'a' is 97 and the code for 'A' is 65 (97 minus 32), 'b', code is 98, 'B' code is 98-32 (66)...and so on.
When you subtract 32 from any lower case character, you will get its upper case equivalent. That is the key.
If the ASCII code for the user entered character falls within 97 to 122 ('a' to 'z'), 32 is subtracted from it for printing: printf("%c",input[x]-32);
If it isn't no action is taken and the character is printed 'as is'.

#include <stdio.h>

int main()
{
    char input[500];
    int x=0;

    printf("Enter your string: ");
    gets(input);

    for(;;)
    {
        if(input[x]>=97 && input[x]<=122)
        {
            printf("%c",input[x]-32);
        }
        else if(input[x]=='\0') //null
        {
            break;
        }
        else
        {
            printf("%c",input[x]);
        }
        x++;
    }
    return 0;
}

Saturday 19 October 2013

Write a Program to Reverse a 5 Digit Number (No Modulus)

I once posted a program to reverse a 5 digit number (Write A Program To Reverse The Number). It used the modulus operator to do the reversal. I mentioned that I had first written the program to do the reversal without using the modulus operator.

Well here's the program. This does not use the modulus operator. But Firrrssstttt...
The Logic:

Again, a 5 digit number is in the 10,000th unit (not hundred thousand and above or nine thousand nine hundred and ninty nine or below). So 

Divide any 5 digit number by 10,000 and you'll get the FIRST DIGIT<POINT>THE REMAINING FOUR NUMBERS. If we typecast this in an int, it is saved without the decimal places.

Eg: Let us assume the user enters 12345 or 23456
1) 12345/10000= 1.2345 (Send the 1.2345 as an int and not a float, it is seen as 1)
2) 23456/10000= 2.3456 (Send the 2.3456 as an int and not a float, and it is seen as a 2)
We do this by typecasting the result:
float result; //result is now a float.
result=(int)12345/10000; //result now holds 1. The .2345 is ignored
result=(int)23456/10000; //result now holds 2. The .3456 is ignored.
Without typecasting (the 'int' in the braces after the 'equals' sign) the results into an int, 'result' would have held 1.2345 and 2.3456 respectively.
So, we now have the first digit.

If we Divide the original the original input by 1000, we get FIRST 2 DIGITS<POINT>REMAINING THREE NUMBERS. As before, typecast this into an int and the decimal places are ignored.
1) 12345/1000=12.345 (typecasted into 12)
2) 23456/1000=23.456(typecasted into 23)
Subtract the typecasted result by the first digit multiplied by 10, and you have the second digit.
1) 12-(1*10) = 12-10 = 2 (Second digit)
2) 23-(2*10) = 23-20 = 3 (Second Digit)

If we Divide the original the original input by 100, we get FIRST 3 DIGITS<POINT>REMAINING TWO NUMBERS. Typecast this into an int and the decimal places are ignored.
1)12345/100=123.45 (typecasted into 123)
2)23456/100=234.56 (typecasted into 234)
Subtract the typecasted result by the first digit multiplied by 100, and you have the SECOND AND THIRD digits.
1)123-(1*100) = 123-100 = 23 (Second and third digits)
2)123-(2*100) = 234-200 = 34 (Second and third digits)
Subtract the result by the second digit multiplied by 10, and you have the THIRD DIGIT.

Just follow this through. With every new digit, the subtracting digit gains a new zero. I won't explain every digit. You'll get the flow from the program.
It's a lot easier to figure out the logic than try to memorize it. Once you get it, it's pretty easy. I wish my math teacher could see me doing these stuff.....

As before, the program displays the result as a series of 5 numbers and then as a single number. Enter 10000 and look at its reversal to see the difference.

/*Reverse A 5 Digit Number!*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>


int main()
{

    int state,rev_num,z;
    float a,b,c,d,e,x,y;

    puts("Enter a five digit number (Cannot start with zero): ");
    scanf("%f",&x);

    if(x>9999 && x<100000) //Check that the entered number is a valid input
    {
        y=x; //make sure the original input is saved in x.

        a=(int)y/10000; //(First Digit)
        printf("%.0f\n",a);

        b=(int)y/1000-(a*10); //Second
        printf("%.0f\n",b);

        c=(int)y/100-(a*100);
        c=(int)c-(b*10);     //Third
        printf("%.0f\n",c);

        d=(int)y/10-(a*1000);
        d=(int)d-(b*100);
        d=(int)d-(c*10); //Fourth
        printf("%.0f\n",d);

        e=(int)y-(a*10000);
        e=(int)e-(b*1000);
        e=(int)e-(c*100);
        e=(int)e-(d*10);//Fifth
        printf("%.0f\n",e);

        printf("%.0f%.0f%.0f%.0f%.0f\n",e,d,c,b,a); //print as a series of digits.
        rev_num=(e*10000)+(d*1000)+(c*100)+(b*10)+a; //find the reverse number as a single integer
        z=(a*10000)+(b*1000)+(c*100)+(d*10)+e; //Find the original input for the heck of it although it is saved in x & y
        printf("Reverse of %i=%i",z,rev_num);

        return 0;
    }
    else //if user hasn't entered a valid input, tell 'em, exit.
    {
        printf("Invalid input!\n");
        getch();
        exit(0);
    }
}

Thursday 17 October 2013

A Mini Drop Down Menu

Well 164 lines of code for something this simple......ah that's life!
It looks awfully messy, but I tried to comment most of the lines to explain what they do. So if you copy and paste this into C::B, it should look readable.

It demonstrates the creation of a drop down menu from which the user can select any one of the 5 items: Cans, Boxes, Pieces, Bottles, Strips with the arrow key.

Gotoxy, SetColorAndBackground (requires THIS header file) and the get_key functions are dreadfully fun to play with.
The integer y tracks where the highlight is as usual. If you haven't done something like this already, give it a shot. It can be fun.

The Down arrow key highlights the next item, the Enter key selects the current highlighted item, the Esc key exits the program.
With a bit more effort, the drop down menu can be made to appear like a solid box if you are willing to set a different background colour for the items in it instead of the surrounding black. But you must erase it's trails after the selection. I didn't do it to keep the program shorter.




Program:

#include <myconstdwin.h>

int get_key(void);

int main()
{
    int loop1=1,loop2=1,key,y=0; //loop 1 & 2 contain the while loops, key gets the keypress, y tracks highlight.

    system("cls"); //clear the screen
    gotoxy(0,0);
    printf("Select one item:");
    gotoxy(0,2);
    printf("This line is just here to demonstrate it's reappearing illusion");
    SetColorAndBackground(15,9); //white text, blue background makes it look like it's highlighted
    gotoxy(19,0); //int y is set to 0 because the highlight is originally at cans, located at zero
    printf("Cans   ");
    SetColorAndBackground(8,0); //the down symbol after cans makes it "pretty". Print it "de-highlighted"
    printf("%c",31);
    gotoxy(26,0); //send the cursor over the down symbol while waiting for user keypress
    while(loop1) //start first loop waiting for user to press down
    {
        key=get_key();
        if(key==592 || key==584) //When user hits down a "drop down" appears with can still highlighted.
        {
            gotoxy(19,1);
            printf("Boxes  "); //The spaces after the items make the dropdown look even. Remove them if you don't believe me
            gotoxy(19,2);
            printf("Pieces ");
            gotoxy(19,3);
            printf("Bottles");
            gotoxy(19,4);
            printf("Strips ");
            gotoxy(26,0);
            while(loop2) //with the "drop down" activated, we wait for user to select an item.
            {
                key=get_key();
                if(key==592) //User Hits Down
                {
                    if(y==0) //user hits down when can is highlighted
                    {
                        gotoxy(19,0);
                        printf("Cans   "); //print this "unhighlighted"
                        SetColorAndBackground(15,9); //bring in the highlighting colours
                        gotoxy(19,1); //Move to where Boxes is to be printed
                        printf("Boxes  "); //print "Boxes" highlighted
                        SetColorAndBackground(8,0); //set colour back to normal.
                        y++; //increase y by 1 because we moved up one.
                        gotoxy(26,0); //always move the cursor to where the down symbol is.
                    }
                    else if(y==1) //user hits down when Boxes is highlighted.
                    {
                        gotoxy(19,1);
                        printf("Boxes  "); //print this "unhighlighted"
                        SetColorAndBackground(15,9); //bring in the highlighting colours
                        gotoxy(19,2); //Move to where Pieces is to be printed
                        printf("Pieces "); //print this highlighted
                        SetColorAndBackground(8,0); //set colour back to normal.
                        y++; //increase y by 1 because we moved up one.
                        gotoxy(26,0); //always move the cursor to where the down symbol is.
                    }
                    else if(y==2) //user hits down when Pieces is highlighted.
                    {
                        gotoxy(19,2);
                        printf("Pieces "); //print this "unhighlighted"
                        SetColorAndBackground(15,9); //bring in the highlighting colours
                        gotoxy(19,3); //Move to where Bottles is to be printed
                        printf("Bottles"); //print this highlighted
                        SetColorAndBackground(8,0); //set colour back to normal.
                        y++; //increase y by 1 because we moved up one.
                        gotoxy(26,0); //always move the cursor to where the down symbol is.
                    }
                    else if(y==3) //user hits down when Bottles is highlighted.
                    {
                        gotoxy(19,3);
                        printf("Bottles"); //print this "unhighlighted"
                        SetColorAndBackground(15,9); //bring in the highlighting colours
                        gotoxy(19,4); //Move to where Strips is to be printed
                        printf("Strips "); //print this highlighted
                        SetColorAndBackground(8,0); //set colour back to normal.
                        y++; //increase y by 1 because we moved up one.
                        gotoxy(26,0); //always move the cursor to where the down symbol is.
                    }
                    else if(y==4) //user hits down when Strips is highlighted.
                    {
                        gotoxy(19,4);
                        printf("Strips "); //print this "unhighlighted"
                        SetColorAndBackground(15,9); //bring in the highlighting colours
                        gotoxy(19,0); //Move to where Cans is to be printed
                        printf("Cans   "); //print this highlighted
                        SetColorAndBackground(8,0); //set colour back to normal.
                        y=0; //Y BECOMES 0 BECAUSE WE HAVE MOVED FROM THE LAST ITEM "STRIPS" TO THE FIRST ITEM "CAN"
                        gotoxy(26,0); //always move the cursor to where the down symbol is.
                    }
                }
                else if(key==13) //What ever is highlighted (remember int y is tracking it), user hits enter
                {
                    if(y==0) //Cans
                    {
                        gotoxy(0,1);
                        printf("You have selected \"Cans\". Thank you!");
                    }
                    else if(y==1) //Boxes, pieces, bottles,strips
                    {
                        gotoxy(0,1);
                        printf("You have selected \"Boxes\". Thank you!");
                    }
                    else if(y==2) //Pieces, bottles,strips
                    {
                        gotoxy(0,1);
                        printf("You have selected \"Pieces\". Thank you!");
                    }
                    else if(y==3) //Bottles,strips
                    {
                        gotoxy(0,1);
                        printf("You have selected \"Bottles\". Thank you!");
                    }
                    else if(y==4) //Strips
                    {
                        gotoxy(0,1);
                        printf("You have selected \"Strips\". Thank you!");
                    }
                    /*reprint the broken line. Also make the "Bottles" & "Strips" below it disappear*/
                    gotoxy(0,2);
                    printf("This line is just here to demonstrate it's reappearing illusion");
                    gotoxy(19,3);
                    printf("             ");
                    gotoxy(19,4);
                    printf("             ");
                    gotoxy(26,0); //always move the cursor to where the down symbol is.
                    getch();
                    /*make "you have selected" disappear*/
                    gotoxy(0,1);
                    printf("                                                  ");
                    y=0; //set y back to zero because we are starting over from "Cans"
                    gotoxy(26,0); //always move the cursor to where the down symbol is.
                    loop2=0; //break the second loop so that the whole menu appears when user hits down again
                }
                else if(key==27) //escape key
                {
                    system("cls"); //clear screen
                    exit(0); //exit program
                }
            }
            loop2=1; //make sure this loop starts again
        }
        else if(key==27) //escape key
        {
            system("cls"); //clear screen
            exit(0); //exit the program
        }
    }
}

int get_key(void)
{
    int c = getch();
    switch (c)
    {
      case 0:   return getch()+256;
      case 224: return getch()+512;
    }
    return c;
}



Sunday 13 October 2013

New Project

When our neighbourhood clinic opened, my friend and I went and fixed up their computer systems. It wasn't anything fancy, just hooking up the printer and setting up Excel for data management (Patients data, number of checkups etc.). The doctor is a neighbour and we call him "Odi" (Elder Brother).

He once told me about a software one of the major Hospitals in the city was using. He was impressed by one of the features of the software that the doctors could see the pharmaceutical supplies available in the pharmacy on their office computer. It also tells them when supplies were low. But it was extremely expensive and required special technicians to install (yup, sounds expensive).

I told him about the program I made for my friend's shop, but it was missing the networking feature. He asked me if i could make him a program that will allow him to see the supplies available in his pharmacy from his cabin computer. For some reason, I thought it would require network programming which I could't do, so I told him no.
Recently I figured out that I don't need to network program. All I need is a windows network and I can Read and Write from one location. I told him a couple of days back that it is possible, and I could write him a program that can do those things for him.

I fix everybody's computers for free, as long as it doesn't require me to buy parts. He offered me money for the program, which I refused, as C is my hobby and I would enjoy doing it. He insists on paying me, so maybe if he does give me some I'll accept...my first paid programming project...
I've made sure to keep the expectations low ("It's going to be black and grey....it's not going to look very pretty"), he doesn't care, he just wants it to do what he requires. Good :)

So here's what I'm thinking the program will do:
1. Input, edit inventory.
2. Warning when stock reaches a predefined low.
3. Send the inventory to a text file (to print, transfer etc.).
4. One screen will be a static of current stock with a search field. The doctor can use this screen to view the pharmaceutical inventory.

Wish me luck.

Wednesday 9 October 2013

Display A File With Breaks/Pauses

Some real life obligations have been keeping me too busy to study more C programming. I knew this was coming.....lol.

Anyway, this program displays a file. Every 20 lines, it waits for a key press. To change the number of lines it pauses at, change the 20 in
if(lines%20==0 && lines!=0)
to any number.
Also, I used a file called "test.txt" ( fp=fopen("test.txt","r");). It may be changed to any file name.
Eg:
 fp=fopen("C:\\Users\\YOURUSERNAME\\desktop\\SomeDocument.txt","r");

Here's the program:

#include <stdio.h>
#include <conio.h>

int main()

{
    FILE *fp;
    char c;
    int lines=0;

    fp=fopen("test.txt","r");

    for(;;)
    {
        c=fgetc(fp);
        if(c==EOF)
        {
            break;
        }
        else if(c=='\n')
        {
            lines++;
        }

        if(lines%20==0 && lines!=0)

        {
            printf("%c",c);
            getch();
            lines++;
        }
        else
        {
            printf("%c",c);
        }
    }
    return 0;
}

Tuesday 1 October 2013

Count The Characters Of User Entered Text String

Just to bring my post count to 45. This counts the characters in a user entered string.

#include <stdio.h>
#include <strings.h>

int main()
{
    char word[1000];
    int i=0;

    printf("Enter text: ");
    gets(word);

    while(word[i]!='\0')
    {
        i++;
    }
    printf("Text is %i character/s long.",i);
    return 0;
}

Output Redirection: Send Your Results To A Text File

In the last post, we redirected input to come from a text file as opposed to coming from the keyboard. Using the text file from the last post, the output was:

Enter the numbers (any alphabet to calculate total): 
The total is 55

How about if we wanted to send the result (Output) to a text file?
Just like we discussed in the last post, The program (mine is named 'test.exe') and the text file ('AddThese.txt') are both in the same folder. To send the output to a text file, we will use the '>' redirection operator.

The command entered would be this:

test <addthese.txt >output.txt


Below is a breakdown of the above command:


test          : (This is the name of the program you wrote)
<addthese.txt : ( insert the data in addthese.txt into the program test.exe when it runs)
>output.txt   : (extract the output from the program test.exe to the text file output.txt)


After entering the command, you will have to press any key once (because of the getch() at the end of the program)
That should create a file called 'output.txt' in the same folder. If you open it in notepad, it will contain the text:

Enter the numbers (any alphabet to calculate total): 
The total is 55

Alright. That's all good. But I'd rather not have the "Enter the numbers (any alphabet to calculate total):" in the output file. We cold easily remove "printf("Enter the numbers (any alphabet to calculate total): \n");"  from the program itself, but then, if this were a useful program, this prompt will be expected by a user when trying to add numbers from the keyboard. If the user is not using redirection, they would be greeted by nothing but a blinking cursor.

Print the prompt as an error message, nobody but the computer and us would know it's being printed as an error. Also during redirection, the "error" message would be sent to the screen and not a file.

When I type 
printf("Enter the numbers (any alphabet to calculate total): \n");
in a program, it the same as typing:
fprintf(stdout,"Enter the numbers (any alphabet to calculate total): \n");

'stdout' means standard output. Change that to 'stderr' (standard error) and we have our program.

#include <stdio.h>
#include <conio.h>

int main()
{
    int x,y=0;

    fprintf(stderr,"Enter the numbers (any alphabet to calculate total): \n");

    //the next line will run as long as scanf is able to read one input
    while(scanf("%i,",&x)==1)
    {
        y=y+x;
    }
    printf("The total is %i",y);
    getch();
    return 0;

}


Redirection still shows the prompt, gets the input from 'AddThese.txt', adds them, sends it to file, waits for keypress, then ends.
I typed the output file (it can be opened in notepad too) and it contains the total. There we go......


Finally, what if I wanted to send the ERROR to file but not the output?

Command is:
test <addthese.txt 2>output.txt

Friday 27 September 2013

Input Redirection: Add the numbers in a text file


Suppose someone asks us to write a program to add some numbers. The numbers are given to us in a text file saved as so:

1,2,3,4,5,6,7,8,9,10

We could write a program to accept keyboard input that will accept the numbers one by one and finally display the result. These are just ten numbers.

Code:

#include <stdio.h>
#include <conio.h>

int main()
{
    int x,y=0;

    printf("Enter the numbers (any alphabet to calculate total): \n");

    //the next line will run as long as scanf is able to read one input
    while(scanf("%i,",&x)==1)
    {
        y=y+x;
    }
    printf("The total is %i",y);
    getch();
    return 0;
}


When we run the program, we can enter the numbers, pressing enter after each. When we enter an alphabet, it will display the total of the numbers entered.


How about if there were 50 or more numbers....it would get a bit taxing to enter the numbers one by one. .

Suppose the numbers are in a file called 'AddThese.txt'. We have a program that will accept keyboard input and display the sum total of the input numbers.
Since they are already typed out in a text file, we can inject the file into the program using the command line. We use the < 'redirection operator' I think they are called.

This command has to be executed from the DOS prompt. Both the program and the text file has to be in the same folder. My program 'Test.exe' and the text file 'AddThese.txt' (which contains the text 1,2,3,4,5,6,7,8,9,10) are both in the same folder (C:\Test\). If they are not, you have to include the complete path in the program parameter, like 'test <c:\users\JohnSmith\desktop\addthese.txt'.



All I did was run the program with the '<addthese.txt' added to the program name and it accepted the input from the text file and displayed the result.


P.S: I finally found 'The C Programming Language' by Kernighan & Ritchie on Amazon (My country's Amazon site, so I could actually order it without chopping off an arm and a leg to pay for it). It should reach me within the week. Although I doubt I'll understand it, I'm excited at the prospect of having it on my bookshelf...the MUST HAVE C BOOK...finally mine...Mua-ha-ha-ha-ha!

Saturday 14 September 2013

Search/Find Function To Find A String

This program assigns a structure with some random things we may find in a guy's den. Then we can enter a string. The program performs a search & find. If the string is found within the "Name" strings, it is displayed with the serial number.
This program uses strstr() to search for the user entered string among the already defined strings.

Sample:



Code:

#include <stdio.h>
#include <strings.h>

void find_item(char find_me[]);

struct items
{
    int slno;
    char name[40];
};
struct items a[10];

int main()
{
    int i;
    char input1[80];

    for(i=0;i<10;i++)
    {
        a[i].slno=i+1;
        switch(i)
        {
        case 0:
            strcpy(a[i].name,"Table");
            break;
        case 1:
            strcpy(a[i].name,"Chair");
            break;
        case 2:
            strcpy(a[i].name,"Whiskey");
            break;
        case 3:
            strcpy(a[i].name,"iPad");
            break;
        case 4:
            strcpy(a[i].name,"Home Gym");
            break;
        case 5:
            strcpy(a[i].name,"Guitar");
            break;
        case 6:
            strcpy(a[i].name,"Bill Reciepts");
            break;
        case 7:
            strcpy(a[i].name,"Watch");
            break;
        case 8:
            strcpy(a[i].name,"Sun-glasses");
            break;
        case 9:
            strcpy(a[i].name,"Cell Phone");
            break;
        }
    }

    while(1)
    {
        system("cls");
        printf("Find what? (END to end): ");
        fscanf(stdin,"%79s",input1);
        i=strcmp(input1,"END"); //if the user input END, i will recieve Zero as a return value.
        if(i==0)
        {
            exit(0);
        }
        find_item(input1);
    }
    return 0;
}

void find_item(char find_me[])
{
    int i,x=1;
    for(i=0;i<10;i++)
    {
        if(strstr(a[i].name,find_me)) //if the comparision turns up a result
        {
            printf("SlNo. %i %s\n",i+1,a[i].name);
            x=0;
        }
    }
    if(x==1)
    {
        printf("Not Found.");
    }
    getch();
}

Tuesday 10 September 2013

Reverse A String Using Recursion.

Okay here's a program that uses recursion (A function calling itself. In this case, the function reverse() runs, and calls itself).

I'm reading the book Programming With C by Byron S. Gottfried. It's hard to get into a book if a lot of the discussion is about stuff you know. But I'm picking up a lot of things from it.

I find it hard to think in recursion, but here's my attempt to explain how this program works.

First: The difference between getch(), getche() & getchar()
getch() - (Get Character?) Accepts a key-press and moves on.
getche() - (Get Character Echo?) Accepts a key-press, ECHOS (displays) it on the screen, moves on.
getchar() - (Get Character Return?) Accepts any number of key-presses, displays it on the                    screen. which is stored in a buffer (A space in memory) until user hits enter.                        The first key-press is returned. Suppose you enter "abcd" for c=getchar();                               and press enter, 'a' will be stored in c. but the 'bcd<enter key>' is                                         still in the buffer......just sitting there.

This program runs the "reverse()" function and comes to the line if((c=getchar())!='\n')reverse();
lets simplify that:

c=getchar();
if(c!='\n')
{
      reverse();
}

So getchar() waits, displaying whatever you type, waiting for you to press enter. The first character of whatever you enter will be assigned to c.
Say you enter "Guns" and hit enter. "G" is assigned to c ("uns<enter key>" is sitting in the buffer), then it checks if c is the enter key, no it's not, so it calls (runs) the reverse() function again WITHIN THE ONE ALREADY RUNNING. 
A new space in memory is created by 'char c'. The program encounters the if((c=getchar())!='\n')reverse(); line again. getchar() is fed "u" from the buffer. It checks if c is and enter key, nope, it's just a 'u', so it calls the reverse() function again WITHIN THE ONE RUNNING THAT IS WITHIN THE FIRST ONE THAT WAS RUN.
Yet again, as reverse() runs, it creates a new char c (same name, different space in memory), it is fed 'n'...
so on and so forth until c is finally fed the enter key '\n'.
Now when the condition is checked if(c!='\n') (if c is not equal to the enter key), but this time, c IS the enter key, so it goes on to the line putchar(c), displaying c which is an enter key in this instance, so you have a blank line (just as if you had hit enter when typing something).
Then THE LAST INSTANCE OF reverse() ends, and comes back to the previous instance which was paused at 

c=getchar();
if(c!='\n')
{
      reverse(); <-It had paused here, because it has called reverse()
}

Then it picks up from where it left off, going on to putchar(c) (this is the SECOND TO LAST instance where c was assigned "s", so you see an "s" on the screen. Then it ends, and the THIRD TO LAST instance picks up, putting c which in his case was assigned "n". When the entire thing unravels.......
You Enter:
Guns<Enter>
You get the output:
<Blank Line>
snuG

Sample:


Code:


#include <stdio.h>

main()
{
    void reverse(void);

    printf("Please enter a line of text.\n");
    reverse();
    return 0;
}

void reverse(void)
{
    char c;
    if((c=getchar())!='\n')reverse();
    putchar(c);
    return;
}