Tuesday, May 10, 2011

SystemH - iPhone Application

For my final project in Software Engineering class, I've opted to develop an iPhone app for the Team Hawaii Solar Decathlon project.

The app will provide an interface to the Home Management System, which we developed as a semester-long project in our software engineering class. This blog post will document the weeklong project process.

I've had a little iOS experience during my internship with Ikayzo, Inc., but for the most part, I'll be learning as I go.

Day 1 (Monday, May 9):
The iPhone must communicate via XML with the backend to the Home Management System (HMS). So I looked up a few XML parsers for iOS and found the following useful articles:
Seems like for now, we'll try gdataxml for the simple reason that the iPhone needs to be able to both read and write xml data to the backend system.

The app will request data from the HMS via a GET request, and send commands to the HMS via a HTTP PUT command.

Downloaded the entire HMS project from the Google Project Hosting site, and examined the backend system and house simulator to get a better understanding of how the systems work in their current final state.

Time spent: 2 hrs

Day 2 (Tuesday May 10):
Started reading the following book and started doing some iOS tutorials. I plan to take about 3-6 hours doing tutorials to familiarize myself with how to setup different screens and support navigation through an app.
There are a few things that I need to be able to do in order to complete the project:
  • connect to a URI
  • parse and write XML
  • get XML data and put XML data to a given URI
  • have multiple screens/views
  • navigate easily and naturally between the views
  • be able to include images and other items in the app
  • allow the user to enter in an ip address or base URI
  • store user settings
Tutorial 1: Button interactivity. Did a short tutorial on how to make buttons interact with text on the screen. This should be useful since there will be buttons on the app that should display a response message when pressed.


Tutorial 2: More interactivity. This tutorial goes over the following controls: segmented controls, switches, and sliders. It also dealt with modal windows (alerts and action sheets).


Total Time: 4 hrs

I think at this point the main thing I need to worry about is navigation within the app. That and XML parsing.

TOTAL TIME SPENT ON PROJECT SO FAR: ~22 hrs

Day 5 (Friday May 10):
Blogger went under for maintenance yesterday and somehow purged about two days worth of writing. Oh well, no harm done :)

So this is where I stand now:
  • Can parse XML from the backend system
  • Have implemented a navigational bar as well as a tab bar
  • Finished Energy calculation
  • Have tested an HTTP PUT request to change the Aquaponics temperature successfully
  • Have implemented AJAX-type updating to live update every N seconds
The image below is a good indicator for how far I've gotten:


Still to do:
  • I'm still having a great deal of trouble putting sliders inside of cells within UITableView. This, however, can probably wait until version 2.0. Tables are nice and great to look at but I need to really read up on custom cell subclassing first.
  • Might be good to implement some sort of timestamp to read what time the last update was.
  • User settings (host URL or IP), time interval to update
  • Slider controls to send a command to the HMS.
  • Error catching for when a connection is lost or when there's a parsing error.
I've about 4 hours left. I think it'd be reasonable to expect the timestamp implementation as well as the slider controls for at least the HVAC system. I have a feeling lighting will be neglected.

Time spent: 4 hours

Just made a wiki page for the app on Google Projects.

I'm also gonna take a quick stab at showing a timestamp at the bottom of each screen to show the last updated time.

Done for today. This week. 7:39pm. 2 more hours in the bag.

-------------------------------
Total Time Spent: 28 hrs










Saturday, April 2, 2011

A06. Persistency

I finally had a chance to finish the integration of Wicket, Berkeley DB, and Restlet. For this assignment, we were tasked with the following two items:

  • Create a secondary index on the timestamp field
  • Provide a web page that will allow the user to get and store data

Some background:
This is a database of contacts, which includes the following fields:

  1. Unique identifier (user-entered)
  2. Name (first, last)
  3. Information (text field)

My understanding of REST, two months later:
When REST was first introduced to us, along with the MVC (model view controller) architecture, I didn't really understand how prevalent both of these ideas were out in the wild. But now that I'm interning at a web development company, and learning Ruby on Rails, it's become apparent that there's no avoiding either of these ideas.

At my internship, we have interface designers and web developers. And I can fully appreciate the MVC model for web development, because it allows the developers to worry ONLY about scripting and writing code to get the inputs and outputs to work, while the designers can focus on making the website pretty. It's a really nice way to separate effort, where doing something on one end has minimal if any impact on the other end.

REST, on the other hand, keeps popping up. Rails supposedly is a RESTful architecture. There are usually no absolute URI's defined, and URI's are created on the fly for the most part, depending on what resource or object from the database that you want to view. I'm still a little fuzzy on how machines talk to other machines via REST, but the entire concept of representations and XML really helped me understand things better when I started my internship. Everything it seems has an XML style hierarchy structure when sending information back and forth between systems.

Kata 1: Create a Secondary Key called Timestamp
This was relatively easy, since I already had experience doing this for the Solar Decathlon project I had been working on, which incorporates a BerkeleyDB backend with a Wicket frontend and Restlet simulator. I happened to work on the BerkeleyDB portion of the project for the first project milestone, so this wasn't a stretch at all.

Duration: 1 hr

Kata 2: Creating a Form Page using Restlet, Wicket, and BerkeleyDB
This was a little more difficult, because it had been so long since I worked on Restlet. So I had to re-watch some of the screencasts by my Software Engineering professor. I also had to go and review some of the Restlet code I had written before to re-acquaint myself with things.

Once I had completed the exercise (screenshots are shown below), I wanted to make sure that I could build two .jar files (one for the contact server and one for the webpage interface client) via Ant. This actually almost took as long as the exercise itself, due to some directory renaming issues.

Duration: 3 hrs + 2hrs to get both the client and server .jar files to work and build via Ant

Screen Shots of the finished Kata:

Screenshot 1: Storing a Contact into the Database
Screenshot 2: The confirmation that the contact has been added
Screenshot 3: Retrieving a record via its unique ID

Download the Eclipse Project: HERE




Tuesday, February 8, 2011

A07. API Design for iHale

I always had a general idea of what APIs were, but the latest module on API design really helped to define what exactly they are for me. First and foremost, I didn't even know what the acronym stood for: Application Programming Interface. I really just saw APIs (most specifically the Java API in particular) as a toolset that I could easily call upon to do magic for me. I never gave it too much thought as to where the magic came from.


After watching Joshua Bloch (of Google fame) give this presentation on good API design, I have a much better understanding of the steps and thought process that goes into designing an API.

Things I've learned about API development:
  • if in doubt, leave it out; it's always easier to add to an API than to remove something from one. This is what's known as the pain of deprecation.

  • naming conventions in API implementation should be really straightforward; you ought to be able to read an API without too much documentation (should read almost like prose)

  • the planning of API's are of extreme importance. A good API can be a godsend of efficiency to a company and a poor one can be a total disaster, and impossible to overcome.

We have started upon our own API development with regard to the Solar Decathlon Team Hawaii project.

The Solar House being built by the University of Hawaii Team is made up of several subsystems (Aquaponics, HVAC, Lighting, etc.), all of which will feed information from sensors to an intermediary system named iHale. iHale is based on the REST architecture and is the backend system that allows for the exchange of information between the house subsystems and client applications (mobile browsers, desktop apps, etc.).

Here's a diagram of the iHale system and how it interacts with other systems within the house:

Team Name: Nai'a (Dolphin)
REST API: Here
Java API: Here


Looking back:
The hardest thing I think was grappling with the magnitude of the entire project and completely understanding the requirements. The option of sending commands to the house subsystems also complicated things to a small extent. Prior projects had basically involved tweaking existing mockup eclipse projects, but this project involved applying the previous three modules to create our own structure.

This did, however, give me much more insight into how API development progresses, and how you try to not only code to get things done, but for the most flexibility and understandability in the future. I think I have a much clearer understanding of REST now that we have concrete resources (the sensors and database objects) and verbs (getting the data from the sensors and pushing commands to the house subsystems).

Also, in an attempt to streamline the API, we did not include a database to hold a record of actions committed by the home user. We were unsure how this data would be used; we can definitely see a use for historical state data, but the added functionality and overhead of adding another database table didn't seem to be worthwhile. If the need comes up, the system has the flexibility to add this if necessary.


Thursday, January 27, 2011

A06. BerkeleyDB code katas

REST as I know it now: After reading (and re-reading) some articles on REST, this is what I've gathered. From the first article, I finally understand that REST allows us to do away with static html pages. Instead, resources are given addresses and the representation (displaying or giving information from the server to client) that is chosen is based on the address requested. This address in the case of the WWW is the URI.

From the second article I gleaned that

Kata 1
The example system provides a single key for retrieval of a Contact: it's unique ID. For this Kata, you will first implement a secondary key for Contacts that consists of a timestamp represented as a long value. For example, (new Date()).getValue() returns the current time as a long value. This timestamp could mean a variety of things in practice, such as the time the contact was created, or the contact's birthday, etc., but we won't worry about that for now.

Write unit tests to make sure that your secondary index works correctly, and that in particular you can retrieve a set of Contacts whose timestamps fall within a specified range.

Once you have implemented the secondary index, extend the ContactClient system with two new commands:
get-timestamp: returns the Contact with the given timestamp, if such a Contact exists.
get-range: returns the set of Contacts with timestamps between two specified values.

The journey: --

Kata 2

The journey:

Kata 1 Duration:
Kata 2 Duration:

Total Duration:

Wednesday, January 26, 2011

A05. Restlet Code Katas Part II

Continuing with REST: We continued our journey through the REST architecture this week. I haven't had too much experience with XML, and it was interesting to see how Restlet and Java are used to generate and read XML documents in a similar fashion to Java property or configuration files. I'm still a little unclear on how REST interacts between servers; so far, what we've been working on has been an introduction (similar to learning Wicket) to the Restlet framework and familiarizing ourselves with how data is stored and retrieved. The one thing that I have been noticing is the reliance on the XML format. And this I think will be important in allowing data to flow between different computers or servers since it's a commonly accepted text format.

Kata 5:
Modify the system to support a new resource called "contacts" and its associated URL: http:///contactservice/contacts. This resource only supports the GET operation and when it is invoked, it returns an XML representation of all of the contacts in the system. To support the RESTful style of hypertextual links, your XML should look like the following:

http://host/contactservice/contact/ID
http://host/contactservice/contact/ID

The journey: What took the longest here was reading through the code to understand where to create functions in order to create the unique XML document required for the kata. Since there's a snapshot of the database available at any given time that returns a collection of the contacts, I used this collection to generate the necessary XML document.

Kata 6:
Now that you have a contacts resource, extend the command line client to support a "get-all" and "delete-all" operation.

The getall operation should invoke the GET contacts command to get the XML representation containing links to all the contacts, then extract the URL of each contact and perform a GET to retrieve its representation. Then print out the contact info associated with that URL (I.e. first name, last name, info).

The delete-all operation should use the GET contacts command to get the XML representation containing links to all of the contacts, then extract the URLs, then call DELETE to delete them.

The journey: The most difficult part about this kata was the parsing of the XML file that was generated in the previous kata. I also had to change the client resource each time I looped through the XML file in order to grab the contact information for the "get-all" command. It seems that there should be perhaps an easier way to do this rather than creating a new client object each time I want to go to a new URI.

Kata 7
Finally, extend the Contact resource to include a telephone number. The telephone number must contain only numbers and the "-" character. When clients do a PUT of a Contact representation in XML format, the server must check that the telephone number field has the correct format and set the Status field to indicate an error if the telephone number is incorrectly formatted. Write unit tests to check both valid and invalid PUTs of your enhanced Contact resource.

The journey: this was the easiest of the three katas, mostly because I'm fairly familiar with the source files and setup of the contact service system. It was simple to add another field to house the telephone number. Regular expressions seemed like the way to go as far as limiting the input of the telephone numbers to valid formats. So after looking up the java implementation of regular expressions and coming up with the following reg ex:

(\\d+)( \\- (\\d+) ) *

This was probably the portion that took the longest time since I had to do a quick refresher on regular expressions.


Kata 5 Time Duration: 2 hrs
Kata 6 Time Duration: 2 hrs
Kata 7 Time Duration: 1.5hrs

Total Time: 5.5 hrs

Wednesday, January 19, 2011

A02: Technical Blog - My Microsoft Interview Experience

This past Tuesday (Jan 18) I interviewed with Microsoft in Redmond, which is very close to Seattle. I interviewed for a Software Developer Engineer in Test (SDET) Summer Internship. It was, to say the least, a very humbling experience. The interviews were tough but I did learn a lot. Here's a rundown of my day:

9:00am - Arrive at Microsoft building 111. This is the interviewee lobby and there's all sorts of cool stuff in here, from an Xbox 360 complete with Rockband drum set, to a Microsoft Surface touch-table, which is basically a large horizontal touchscreen that allows you to play games and pull up information using natural gestures.

9:15am - Meet with recruiter. Very friendly lady who gave me a rundown on what my day would be like: 2 interviews, lunch, followed by more interviews - ranging anywhere from 3-5 interviews total. She also explained to me about the Microsoft shuttle service. The Microsoft Campus is enormous, and Microsoft has an entire fleet of Priuses and vans that shuttle people (especially interviewees) from building to building. See, the interviewers don't come to you. You actually go to their offices. The recruiter also gave me a few tips: 1 - talk through your code so the interviewers can see your thought process. 2 - ask clarifying questions to make sure you understand what the interviewer is asking of you.

10:00am - Interview 1: Microsoft Office (Ahmad). While chatting, he asked me what my favorite/least favorite software program was. I answered Adobe Photoshop. I listed a few things I liked/disliked. I also made sure to mention a program from the MS Office suite as well (I really like the Office suite). I also commented that I wished that MS would setup something like Google Docs, a free, online cloud application to allow users to edit Office Documents real-time simultaneously. Mistake. MS already has this feature. Lesson: Make sure you do your research if you are going to talk about a particular product.

We chatted more, and then he asked me to code on his whiteboard. Problem: write the code to remove a node from a linked list. Method Signature: remove (int position). I was, to say the least, very nervous at this point. This was definitely a problem I was familiar with, but It took me a little while to get though the jitters and settle down, but as I was thinking through the process, I made sure to keep talking about the steps I was taking to generate my code. I also made sure to ask a lot of questions about the type of input and output to make sure I understood the problem.

I was able to complete the coding problem, and as we went through my solution, which I decided to code in Java (they leave the language up to you), it appeared that I had covered all the cases, with the exception of one or two, which I can't recall at the moment. He did offer me the suggestion that I could've inserted a while loop to test for a position index that was too large (I tested for this inside of one of my for loops, which wasn't as efficient).

Then we got to the testing portion of the interview. Since I was applying for a position as a Software Tester, he asked me to test the sorting function in MS Excel. I started by saying I'd test integers and decimal numbers (positive and negative), and strings, and a combination of numbers and strings. He asked me how I would test performance and security. I had to clarify a bit on the security question. He elaborated that I needed to think of cases where user input or action might make the system crash (e.g., inputting too long of a string to sort, too much data, etc).

He also brought up that I needed to consider accessibility concerns as well. So a few things that I didn't test for that I should've: security, performance, and accessibility. All of the interviewers talk to each other over the course of the day, so they want to see if you've been able to apply the things that they've suggested to you.

11:00am - Interview 2: Microsoft Office (Ziesha)
From there I was greeted by the next interviewer, a young programmer with a Ph.D. in security protocol, who had been there for three years with Microsoft.

He first asked me how I would test the MS Office ribbon (the set of tabs at the top of every office application containing functions specific to the application). I gave a few test scenarios, like opening up a few instances of the application to ensure that each ribbon acts independently, and some accessibility tests for the blind and so forth.

He then asked me to design an ATM machine with a few new features. The most innovative idea, which I don't even think was that novel, was to attach some sort of entertainment (e.g., scrolling marquee or TV screen) to the machine to allow people waiting to occupy their time/attention with. We then went over how I would test a normal ATM machine (hardware and software).

By this time, I was itching to start coding. I'm not the best person when it comes to coding while someone is watching over your shoulder, so I wanted to have enough time for me to think things through. The problem, however, wasn't that bad: Code how you would find whether a linked list is cyclic or not. I was able to do this without too much trouble. He then asked me if this would work for a doubly linked list as well. I went into some detail as to how I would modify my code, and then later found out that it would've worked without modification (my idea of a doubly linked list was a little off).

12:00pm - At this point, it was time for lunch. Ziesha
- how to improve
- healthy food in cafeteria
- nice talk; enjoyable

1:00pm - Interview 3: Microsoft Exchange (Ravi)
- given an input:
- output word1,word2
- should've asked for unicode/ASCII; I assumed ASCII right off the bat
- asked more questions
-

2:00pm - Meet with recruiter
- asked for details on interviews
- talked about MS perception and how things are changing

Lessons Learned:
  • Learn C# - A lot of Microsoft's products are written using C#. They expect you to learn the language before coming to their offices if you are offered an internship or job.
  • Practice coding simple structures and concepts - getting comfortable with coding even the simplest of structures, such as linked lists and string manipulation; libraries may provide this functionality, but the coding habits and skills you develop while doing these exercises is very important.
  • Practice coding on a whiteboard.
  • Try to think of all possible exceptions
Final Thoughts:
  • Microsoft employees are very loyal to the company
  • These guys are really really smart
  • This was my first technical interview, and it was a very good learning experience for me.




Sunday, January 16, 2011

A04. Reslet Code Katas


We (ICS414) have started to use Restlet, which is a java framework that will allow us to familiarize ourselves with the REST methodology.

What is REST?
I myself still am a little unclear on the uses and applications of REST, but I'm sure that as the semester progresses, it will become clearer. As I understand things, REST is a way for web servers to talk to one another and it facilitates more computer-to-computer interaction. One of the main pillars of REST that we've been examining in class is the use of representations of data. Rather than having static html code, a client can request a representation of some data. Perhaps that data will be displayed in text. Another client may request the data as a chart. Either way, the data is unaffected by these representation requests.

There are a few main components that comprise the REST architecture:
  • Resources - these are 'things' like data or images
  • Unique URIs (Uniform Resource Identifier) - this is the address or location of the resources
  • Representations - this is how resources are displayed or presented to the user. External users may not manipulate or change resources, but they can alter the way these resources are represented.
  • Verbs - actions one can perform on resources. E.g., GET (asks for a representation of a resource) and PUT (adds or updates a resource).

RESTLET

Our intro to Restlet included the following four code katas:

  • Kata 1: Add three new resources called "hour", "minute", and "second" that return the current hour, minute and second (include unit tests).

    Experience: this was a very basic exercise that I was able to complete fairly quickly. It mostly involved copying packages and refactoring the names to match the new unit of time that needed to be displayed.

    Duration: 30 min
  • Kata 2: By default, Restlet logs data about each request to the command line using the Java Logging API. Read a tutorial (and/or google) to get familiar with the API, then do the following: define a ~/.dateservice/logging.properties file that enables the user to specify (among other things) that the logging information should go to a file, not the command line tell the restlet-dateservice application to read and use the logging properties file in ~/.dateservice/logging.properties

    Experience: This was a little more challenging, since this is the first extensive use of logging that I've dealt with. After finding out how to use System.getProperty() to retrieve the home directory, however, the rest of the time was spent researching how to get the logging service to output to a file rather than the command line. I was able to read through a few logging configuration files and extract the necessary properties.

    Duration: 3 hours

  • Kata 3: The current restlet-dateservice system performs no authentication. Check the user guide (and/or google) for guidance, then implement HTTP Basic authentication for all the resources in the restlet-dateservice system. To simplify things, all resources should be available as long as the requesting system uses HTTP Basic authentication and passes the username "guest" and password "pw". (You can hardcode that password into both the client and server sides of the system if you like.)

    Experience: I was able to find a fairly comprehensive tutorial for HTTP basic authentication with Restlet on StackOverflow: Click Here. This was pretty straightforward as far as adding authentication to each resource and then adding in the client-side hard-coded password/username combination to allow for the JUnit tests to pass. I initially tried to use the Restlet tutorial on access control, but due to lack of a comprehensive example, it wasn't very helpful.

    Duration: 2 hrs

  • Kata 4: create a new client for the DateService server that is a web application using Wicket rather than a command line application. The web application should bring up a single page with a single form that requests what aspect of the date (year, month, day, hour, minute second) the user desires. When the user submits the form, the web application uses Restlet to obtain the appropriate information from the DateService server, then presents the results to the user in the page.

  • Experience: This was by far the most time-intensive of the katas. I first had to figure out that to get Wicket to interact with the Restlet server, I had to make an instance of a Jetty web server from last semester. Then, using the code from the Restlet client, this allowed my Wicket page to access and display the information as specified. I also need to brush up on my Wicket, and I wanted to better understand using form buttons to update a label, so I had to do some additional reading. In the end, I think I have a better grasp of how servers can talk to one another. Where one server can grab data from another server and display it using whatever framework is requested. For this particular exercise, we knew that Restlet was framework being run on the source server, so it made it easy to request data using Restlet type commands. It'll be interesting to see if the framework must be known or if there's some generic/standard interface that most servers use to communicate information between one another.

    Duration: 5 hrs
TOTAL DURATION:
10.5 hrs

Distribution file (.zip): Click Here

Friday, January 14, 2011

String Manipulation Exercises

Some string manipulations I've been working on (Language: C)
  • Reversing a String
  • Removing Spaces from a String
  • Reversing Words in a String


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

#define MAX_LEN 100

/**
* String Manipulation Exercises
*
* @author Kevin Leong
* @date January 11, 2011
*/
int main (char argc, char* argv[]) {

// Initialize string to hold user input
char myString[MAX_LEN] = {0};

// Prompt for user input
printf("Please enter a string (100 character max: ");

// Read in user input
if (fgets(myString, MAX_LEN, stdin) == NULL) {
perror
("Error reading user input");
}

// If the last character of the string is a new line
// character, then remove it from the string.
int last = strlen(myString) - 1;
if (myString[last] == '\n') {
myString[last]
= '\0';
}

// Copy user entered string to allow the functions to
// independently manipulate it
int len = strlen(myString);

char myStringReverse[len];
char myStringRemoveSpaces[len];
char myStringReverseWords[len];

strcpy(myStringReverse, myString);
strcpy(myStringRemoveSpaces, myString);
strcpy(myStringReverseWords, myString);


// Reverse the characters in place
reverse_string(myStringReverse);
remove_spaces(myStringRemoveSpaces);
reverse_words(myStringReverseWords);

// Print manipulated strings
puts(myStringReverse);
puts(myStringRemoveSpaces);
puts(myStringReverseWords);

} // End Main

/**
* Reverses a string in place.
*
* @param s - string to reverse
*/
void reverse_string (char s[]) {
// Get string length
int len = strlen(s);

// If string is of length 0 or 1, then no reversing necessary
if (len > 1) {
// Loop variable
int i;

// Temporary placeholder for swapped elements
char temp;

// Go through string and swap characters
for (i = 0; i < (len / 2); i++) {
// End is equally distant from the end of the string
// as i is from the beginning
int end = len - 1 - i;

// Swap characters at i and end indexes
temp = s[i];
s[i] = s[end];
s[end] = temp;

} // End For loop
} // End If
} // End Reverse String Method

/**
* Removes spaces from a given string.
*
* @param s - string to remove spaces from
*/
void remove_spaces (char * s) {
// Counter to track number of spaces so far
int numSpaces = 0;

// String length
int len = strlen(s);

// Loop variable
int i;

// Loop thru string
for (i = 0; i <= len; i++) {

// If the current position is a space, then increment
// space counter
if (s[i] == ' ') {
numSpaces
++;
}

// If current position is not a space and there exist
// spaces in the string
else if (numSpaces != 0) {

// Move the element to the left. The amount of positions
// it's moved is dependent on how many spaces have been
// discovered.
s[i - numSpaces] = s[i];
}
}
// End For Loop

} // End Remove Spaces Method

/**
* Reverses the words in a string.
*
* @param s - string to manipulate
*/
void reverse_words (char * s) {
// Length of String
int stringLen = strlen(s);

// Loop index
int i;

// Index to track progress
int k = stringLen;

// New string holding reversed words
char newString[stringLen];
newString[stringLen] = '\0';

// Loop through string and replace all spaces with terminating 0s
for (i = 0; i < stringLen; i++) {
if (s[i] == ' ') {
s[i]
= '\0';
}
}
// End For Loop

// Length of current word
int wordLen;

// Restart loop variable
i = 0;

// Reverse the order of the words
while (i < stringLen) {

// Length of current word
wordLen = strlen(&amp;s[i]);

// Go backwards on new string
k -= wordLen;

// Loop variable
int j;

// Copy word into new string
for (j = 0; j < wordLen; j++ ) {
newString[k + j]
= s[i + j];
}

// Go forward on original string
i += wordLen;

// If there's a terminating zero and it's not the end
// of the string, then put a space in the new string
while ((i < stringLen) &amp;&amp; (s[i] == '\0')) {
i
++;
k--;
newString[k] = ' ';
}
// End While Loop

} // End While Loop

// Copy manipulated string back to original string
strcpy(s, newString);

} // End Reverse Words Method