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;
}


Sunday 8 September 2013

Print A String All In Uppercase

I like the for(x=0;(char1[x]=getchar())!='\n';x++); line. That's why I'm posting it.

This program is from Programming With C by Byron S. Gottfried.
It displays a user entered string in uppercase.
for(x=0;(char1[x]=getchar())!='\n';x++); accepts the user entered characters saving it in char1[0],[1],[2] and so on until the user hits enter ('\n').

Then the string is displayed character by character. Each character is 'upper-cased', so to speak, by the toupper() function before it is displayed.

#include <stdio.h>

main()

{
    char char1[100];
    int x,y;

    printf("Enter a length of string: ");

    for(x=0;(char1[x]=getchar())!='\n';x++);

    y=x;

    
    for(x=0;x<y;x++)
    {
        putchar(toupper(char1[x]));
    }

}

Monday 2 September 2013

A Few Things About The Scanf Function.

Programming With C by Byron S. Gottfried is a wonderful book. I was avoiding this book because it felt too formal, and it just seemed so outdated....with stuff like "A 256kb micro computer(Also Called Personal Computer) is commonly....". I also hadn't gotten over the feeling that I would not understand the material presented. But when I started reading it it is really good. I can understand most of it now since I believe my introduction to C phase is complete.
Leafing through it, I believe I also spied an example file compress program near the end, though I'm not sure if that is what it is.
Because this book is written as a textbook, it packs a lot more information in fewer pages. Here are some of the interesting things I learnt about scanf().

Consider this program:

#include <stdio.h>

main()
{
    char str1[50];

    printf("Enter a string of ONLY NUMBERS: ");
    scanf("%[ 1234567890]",str1);

    printf("%s",str1);
}

This program will prompt you to enter numbers. As long as you enter numbers, all is well and it is faithfully saved in the string variable str1, but as soon as you enter something other than a number, scanf stops reading your input and assigns whatever numbers you may have entered to str1.
This is because the characters within the [] are the only ones accepted. There is also a space in there so you can enter something like "192 168 1 1" and it will get assigned and displayed.

But if you enter "156 A132 M56", only 156[space] will be assigned to str1.
I don't see any reason why we would use this, but we never know.

scanf does not recognize spaces by default. Say:

#include <stdio.h>

main()
{
    char str1[50];

    printf("Enter a string: ");
    scanf("%s",str1);

    printf("%s",str1);
}

Would run like this:

Although I entered "Sagacious Tien", it only accepted Sagacious and when it saw the white space, it ended it's read.
The obvious and, I suppose, better way to have the full name assigned to str1 is to use gets(str1), but we can also do:

#include <stdio.h>

main()
{
    char str1[50];

    printf("Enter a string: ");
    scanf("%[^\n]",str1);

    printf("%s",str1);
}

the[^\n] tells scanf to not stop reading until it encounters the enter key (represented in C by '\n').

#include <stdio.h>

main()
{
    char str1[50];

    printf("Enter a string: ");
    scanf("%5s",str1);

    printf("%s",str1);
}

This tells scanf to only read 5 characters and ignore the rest. If you enter "1234567890............", str1 will be assigned "12345" and the rest of the input is ignored. Bounds Checking of sorts.




Sunday 1 September 2013

Sale Data Saved To Disk

I just noticed today that fwrite and fread is heck of a lot easier than using fprintf and fscanf. Dang! Wish I had known before.

Here is a program that stores or displays the Name, Amount Sold, Sale Price and the Date & Time for a particular sale.

NOTE: Even if you do not enter anything, if you run the program it will create a folder called "MyDaily" on your C Drive. Just FYI, so you know it's safe to delete and not one of those "*Maybe* an important system file" kind of file.

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

void date(char *da);
void times(char *da);

main()
{
    FILE *fp;
    char tm[30],dt[30],c;
    int rw;
    struct daily
    {
        char name[40];
        int NumberSold;
        double SalePrice;
        char time[50];
    };
    struct daily a;

    fp=fopen("C:\\MyDaily\\Sale.dat","rb"); //test to see if this file exists
    if(fp==NULL) //does not open, it possibly does not exist
    {
        /*create the "mydaily" directory, if it exists, the 2>nul prevents DOS from
        freaking out and displating a message like "folder exists"*/
        system("md C:\\MyDaily 2>nul");
        fp=fopen("C:\\MyDaily\\Sale.dat","wb"); //create the sale.dat file
        if(fp==NULL)
        {
            printf("Unable to create data file.");
            getch();
            exit(0);
        }
    }
    fclose(fp); //close the file in read or write mode

    printf("Do you want to read or write?(R/W)");
    c=toupper(getch(c));
    if(c=='R')
    {
        rw=1;
    }
    else if(c=='W')
    {
        rw=2;
    }

    while(rw==1)
    {
        fp=fopen("C:\\MyDaily\\Sale.dat","rb"); //open in read mode.

        if(fp==NULL)
        {
            printf("Cannot Open File1");
            exit(1);
        }
        while(fread(&a,sizeof(a),1,fp)==1)
        {
            printf("\n%s %i %.2wf %s",a.name,a.NumberSold,a.SalePrice,a.time);
        }
        break;
    }

    while(rw==2)
    {
        fp=fopen("C:\\MyDaily\\Sale.dat","ab"); //open in append mode.
        if(fp==NULL)
        {
            printf("Cannot Open File2");
            exit(2);
        }

        system("cls");
        /*clears the buffer of old values. Comment this out. Run the program, enter something
        when it asks if you want to enter another, say yes. You'll see why this is here*/
        fflush(stdin);
        printf("Enter Name Of Item: ");
        gets(a.name);
        printf("Enter Number Sold: ");
        scanf("%i",&a.NumberSold);
        printf("Enter Sale Price: ");
        scanf("%wf",&a.SalePrice);
        date(dt);
        times(tm);
        sprintf(a.time,"%s%s",dt,tm);
        fwrite(&a,sizeof(a),1,fp);
        printf("Enter Another?(Y/N): ");
        c=toupper(getch(c));
        if(c=='Y')
        {

        }
        else if(c=='N')
        {
            system("cls");
            break;
        }
    }
    fclose(fp);
    return 0;
}

void date(char *da) //Displays date when needed.
{
    time_t now;
    struct tm*d;
    char li[30],li1[30],*dt;

    time(&now);
    d=localtime(&now);
    strftime(li,30,"DT%d-%m-%y",d);
    dt=&li;
    while(*dt!='\0')
    {
        *da=*dt;
        da++;
        dt++;
    }
    *da='\0';
}

void times(char *t) //Displays Time when needed.
{
    int x;
    time_t now;
    struct tm*d;
    char li[30],li1[30],*tm;

    time(&now);
    d=localtime(&now);
    strftime(li1,30,"TM%H:%M:%S",d);
    tm=&li1;
    while(*tm!='\0')
    {
        *t=*tm;
        t++;
        tm++;
    }
    *t='\0';
}