Thursday, September 25, 2014

Anatomy of a Program That Stores Five Integers Using Linked Lists and Prints Them Out

#include <stdio.h>
#include <stdlib.h> //For malloc function
struct cell
{
    int value;
    struct cell* next;
};
typedef struct cell node;
void addAtBeginning(node*,node*);
int main()
{
    node * head = NULL;    //Signifies the end of the list
 
   
  
    puts("Please specify how many numbers you will enter.");
    int amount = 0;
    int counter = 0;
   
    scanf("%d", &amount); //Enters 5
    for(counter = 0; counter < amount; counter++) //While counter < 5
    {
        puts("Please enter a number.");
        node * temp = NULL; //Creates a temporary node to hold each number
        temp = malloc(sizeof(node)); //Allocates space for each node
        scanf("%d", &(temp->value));// The -> gives us the value and the
                                                       //external & gives us the address of that value
                                                     
        addAtBeginning(head, temp);//Gives the top node and the node to be added
        head = temp; //Makes the new node the top node
    }
    node * temp = head; //Creates a temporary node (so we dont change the
                                      //value  by accident

    while(temp!=NULL) //While we're not at the end of the list:
    {   
        printf("%d", temp->value); //Print the value of the current node
        temp=temp->next;             //moves the iteration through to the next node
    }
   


}
void addAtBeginning(node *atFront, node *nodeToAdd)
{
    nodeToAdd->next=atFront; //Links the NEW top node to the former top node
}

Tuesday, September 23, 2014

A Dive Into fgets and scanf

We all know strings are basically arrays of characters, right? What I wasn't sure of was what would happen if I tried to input a string that was larger than the size of the char array that will hold it. Will the array be resized? I knew that probably wouldn't happen because C doesnt seem to like the idea of resizing arrays. So, I assumed that the string input would somehow be truncated.
Here is my original code:

#include <stdio.h>
int main()
{
    puts("Please enter a number.");
    int number = 0;
    scanf("%d", &number);
    puts("Please enter a string.");
    char sentence[number];
    scanf("%s", &sentence);
    printf("%s", sentence);   

}


It seems to work when i try it, but everyone is saying that scanf() isn't really secure, so I chose to replace it with fgets():

#include <stdio.h>
int main()
{
    puts("Please enter a number.");
    int number = 0;
    scanf("%d", &number);
    puts("Please enter a string.");
    char sentence[number];
    fgets(sentence,number, stdin);
    printf("%s", sentence);   

}
But this gave me the following output:

Please enter a number.
2
Please enter a string.

The program had ended without my entering the requested string. From my code above, fgets() should've at least allowed me to enter a single letter, right? The maximum number of characters to be copied into sentence would be 1. Huh.
After doing a bit of googling, I find a satisfactory answer as to why this is happening: http://cboard.cprogramming.com/c-programming/96983-why-scanf-dont-working.html

After I enter 2 in the above example, stdin should look like the following:
[2][\n][][][][][]
scanf() reads the 2 and puts it in number, without doing anything to the trailing '\n', so stdin looks like:
[\n][][][][][]
And then fgets() comes along, sees the '\n' in stdin (and assumes the user has typed something) and according to this,
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
So sentence should at least look like this:
[\n][]
So what do we do? Why, we remove the extra '\n' before fgets() trips over it!

#include <stdio.h>



int main()

{
    puts("Please enter a number.");
    int number = 0;
    scanf("%d", &number);
    char ch;
    ch = fgetc(stdin);

   
    puts("Please enter a string.");
    char sentence[number];
   
   
    fgets(sentence,number, stdin);
   
    printf("%s\n", sentence);   

}
So stdin is effectively cleared and we can continue with our little experiment:

Please enter a number.
2
Please enter a string.
hello
h

Remember, fgets can only read a maximum of two characters into the string. In this case,'h' and '\n'. "But where's the new line?" From what I can gather, fgets() automatically appends a '\0' to the end of the string, which essentially shows where the string ends.

#include <stdio.h>



int main()
{
    puts("Please enter a number.");
    int number = 0;
    scanf("%d", &number);
    char ch;
    ch = fgetc(stdin);
   
    puts("Please enter a string.");
    char sentence[number];
  
    fgets(sentence,number, stdin);
   
    printf("%s", sentence);   
    if (sentence[number-1] == '\0')
    {
        puts("The string is null-terminated.");
    }
   
}

I get the following:

Please enter a number.
2
Please enter a string.
helllo
hThe string is null-terminated.





So, it seems fgets does that job for us. Let's test to see if scanf does the same:

//fgets(sentence,number, stdin);
    scanf("%s", &sentence);
    printf("%s", sentence);   
    if (sentence[number-1] == '\0')
    {
        puts("The string is null-terminated.");
    }

The above code gives me:

Please enter a number.
2   
Please enter a string.
helllo 
helllo


So scanf does no bounds checking and allows me to write 6 characters into a 2 character array. What rule are we violating here?

Ari's answer at http://stackoverflow.com/questions/11455302/where-c-really-stores-a-string-if-the-char-array-that-stores-it-is-smaller-tha
gives us a nice diagram to work with: 
Bytes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Before |-----name1 array-------| |--- other data-| After Q w e r t y u i o p \0 |-er data-|

As outlined in the above diagram, scanf allows you to overwrite data from other variables in memory (BTW this is called a buffer overflow.)
Let's try this example: 
#include <stdio.h>



int main()
{
    puts("Please enter a number.");
    int number = 0;
    scanf("%d", &number);
    char ch;
    ch = fgetc(stdin);
   
    puts("Please enter a string.");
    char sentence[number];
    int y = 1;
   
    //fgets(sentence,number, stdin);
    scanf("%s", &sentence);
    printf("%s", sentence);   
   
//    if (sentence[number-1] == '\0')
//    {
//        puts("The string is null-terminated.");
//    }

    printf("%d", y); //Supposed to print 1
}

I get the following:

Please enter a number.
2
Please enter a string.
HELOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Segmentation fault (core dumped)
 
So clearly scanf replaced some data in memory, causing this segmentation fault. Remember, I had mentioned above that scanf() isn't secure. This is clearly why.
Alright, so scanf has the potential to overwrite memory, so what can we do about it? We can specify the maximum amount of characters that the user can input. pb2q from Stack Overflow explains it as follows:
If you must use scanf then I believe that the best that you can do is use the width specifier with something like: "%31s", as you've already mentioned, then use strlen to check the length of the input, and discard the string and report an error if the input is longer than your limit.
Or possibly skip the strlen by additionally using an %n in your format string, e.g. "%31s%n".
A format string using something like %[^\n] in place of %s simply instructs the function to continue reading until a newline, consuming other whitespace characters along the way. This is useful if you want to allow the input to include whitespace characters.
Review the docs for scanf (here's a copy of the man page).
 

Tuesday, June 17, 2014

Copy.com - Cloud Storage and Sharing Platform by Barracuda Networks



Have you ever wanted to sync all your online files to all your devices? Do you have  Windows, Linux or Mac OS-X computers that need to share files regardless of the underlying operating system? Do you want to share files from your PC to your Android, iOS device or Windows Phone? If so, Copy.com might be what you're looking for. Sure, Dropbox offers free storage up to 2GB but Copy.com gives you up to 20GB and that's not even counting the extra 5GB you get for referring your friends!
 Once you upload a file to your Copy account, it is automatically downloaded on every computer that has the app connected to your account. So if you want to quickly send a piece of code to your home computer from work, just upload it to your account and Copy will download the file(s) onto your home computer the next time it turns on.

Copy Referral Link

Sunday, June 15, 2014

My First Dive at Making a C++ Calculator

Ever since I started C++, I've wanted to make my own calculator in C++. One that allows you to enter expressions and can use operator precedence (BOMBDAS) to arrive at a correct answer. Over the past few days, I've been working on a calculator called CPP-Calc. It's a start, I guess. The code looks kind of ugly at best, but it's easy to compile because everything is in a single file called main.cpp. Maybe that's what makes ti so ugly, but I'll eventually get around to correcting that :). Also, as users on Code Review pointed out, there are several problems with my code.
It works, but its design is a bit lack luster. Firstly, it seems to be nowhere near as simple as it could have been (I've been told I could have used a recursive descent parser or the shunting yard algorithm) and the code just seems jumbled. I think the algorithm I used is okay, though. It allows me to make use of stacks, vectors, string methods (eg. replace() ), pointers and doubles. I'll need to implement a better design though. Some member variables aren't private, some variables are unused and it just looks cramped. 
I ought to point out the problems I'm facing with the use of doubles. Being floating point numbers, doubles will only allow the calculator to give the a certain degree of accuracy up to a point. Maybe I'll be able to use some sort of other datatype, but for now, I'll concentrate on the design.
Greetings to all who have read the article and I welcome your reviews on my program :
http://codereview.stackexchange.com/questions/54273/simple-c-calculator-which-follows-bomdas-rules

If you'd like to download/examine my program more closely, use this: Download

Thursday, January 30, 2014

Useful Links

Android Users

Root
If you've so far been unable to root your device using other programs, then I suggest you give this one a try: 
Easy Android Rooter
If it says the device has been rooted but other root testers don't, just press the root again button.
Students
A link to a useful post about cramming
Cramming Guide