Hey everyone, apologies for not posting anything these last few days! Other classes got pretty homework-y, social obligations, and I discovered this new thing called reddit that I started browsing (usually anime, compsci, or anything I want to know more about - so many firsthand experiences out there in just about anything).
In lieu of an updated program on here I would like to explain my currect (mini?) dilemma regarding CS.
So last week I had my C++ midterm in the lab, lab computers only, 2 hrs, print it out using that barely-funded campus card. Now what really peeves me is that my campus is one of the many that utilize Windows for just about every CS lab. Only one lab has a dual boot Mac/Linux setup for anyone to use, and - this is the weird part - I never see them turned on, and if they are it's usually on the Mac boot, leaving the IT guy to clean out all the incriminating history. (people leave too quickly to log out?) During homework lab, I do the best I can to output a working program by the end of lab, using my favorite portable netbook running Xubuntu linux. Everyone else either uses the vanilla lab PCs with Visual Studio (3 different years installed - wth?), their own Windows with VS, or their fancy Macbooks which I guess are running xCode, NetBeans, or Eclipse. I wear, I'm the only one running any form of Linux, it's really sad. At least no one is staring at me like I'm an alien (thanks reddit), frankly because in my opinion they don't care what I'm running as long as I don't freak out over the code not working 5 minutes before it's due.
So why did I freak out over the midterm? These were programs I had done before and knew the functions to work with in order to output the results. It was being forced into an environment that I was entirely unfamiliar with that made things go downhill for me during the exam. Visual Studio was being totally unhelpful, would compile but not run my programs due to some default header file native only to VS that I never saw before. I longed to ssh into the campus's sole Linux server to compile my code from Notepad++, however being a wuss, I feared potential reprecussions from using a web browser to look up how to compile a program remotely, as obviously no web-searches were allowed for an exam. So I felt incredibly handicapped and depressed listening to the other students clacking away at 150wpm on their workstations, clearly competent with VS's style because, that's what they used throughout the intro course and the last 5 projects. To compound my embarrassment I really cannot touch type, having hen-pecked my way through high school by getting all my typing done at home in privacy. By the time it came to print, I was a wreck internally. I longed for the familiarity of g++ and the terminal as I reluctantly turned in my psuedo-programs hoping for 1 pt of efforts.
This literal complete turnaround in my experience with programming (before I had been getting high scores on nearly every homework) caused me to think about OS use within comp sci. Is it "normal" to utilize Windows everywhere, even within (what I supposed to be) the supposedly neutral CS field? (I swear they have some big-bucks contract with Microsoft! Mac and Linux machines are almost non-existent, save for the Macs people bring as personal toys) For a programmer, isn't relying on the Windows-style of doing things a bit like what all the other majors are doing? and then there's the people who will readily whip out their iPhones if no lab is assigned, leaving the lab PCs designated as the workplace. For CS, I believe that every technology should be explored regardless of who makes it (eventually, being on the "outside" of everything all the time feels isolating, at least that's what I'm feeling), and one shouldn't be favored for the other. Windows (and Pepsi) currently have a huge monopoly at my uni, and unfortunately for the Mac/independent Linux users, programming and hunting down a Coke have become much harder than necessary to achieve.
Tuesday, March 10, 2015
Saturday, March 7, 2015
Post #6 - Random numbers
I usually end up being behind a post if I have homework or other life stuff going on that needs to get done, so here's a program that was going to be posted yesterday.
Using the libraries cstdlib for the srand() and rand() functions, and ctime for the time() function, the program displays a random year within the range 1985 - 2015. The range limit is achieved by setting the random year to display equal to the remainder of the randomly generated number divided by 31, resulting in an integer between 0 and 30 (the computer counts starting from 0, not starting from 1, so in our counting style 0-30 would be 1-31).
We want the difference of the years (2015 - 1985 = 30) plus the starting year (1985) to be the range of the random year, but if 30 was used as the divisor, the range would be one year off from 2015 (since in computer numbers, (0 + 29) = 1-30, it would count from (0 + 1985) to (29 + 1985) which is 1985 - 2014). The off-by-one error can be fixed, because another 1 was not added to 30 to account for 2015 as one of the years, just change 30 to 31, thus raising the range to 1-31 and including 2015 in the computer's random years selection.
This sounds confusing but try reading the 0 of the modulus (%) results as a 1, and adding 1 to every integer in the range including the last number. This kinda converts it to human-range starting with 1, and to convert back, subtract 1 from every number for counting from 0.
Here's the output:
This program randomly chooses a year between 1985 and 2015.
The random year is 1985
Using the libraries cstdlib for the srand() and rand() functions, and ctime for the time() function, the program displays a random year within the range 1985 - 2015. The range limit is achieved by setting the random year to display equal to the remainder of the randomly generated number divided by 31, resulting in an integer between 0 and 30 (the computer counts starting from 0, not starting from 1, so in our counting style 0-30 would be 1-31).
We want the difference of the years (2015 - 1985 = 30) plus the starting year (1985) to be the range of the random year, but if 30 was used as the divisor, the range would be one year off from 2015 (since in computer numbers, (0 + 29) = 1-30, it would count from (0 + 1985) to (29 + 1985) which is 1985 - 2014). The off-by-one error can be fixed, because another 1 was not added to 30 to account for 2015 as one of the years, just change 30 to 31, thus raising the range to 1-31 and including 2015 in the computer's random years selection.
This sounds confusing but try reading the 0 of the modulus (%) results as a 1, and adding 1 to every integer in the range including the last number. This kinda converts it to human-range starting with 1, and to convert back, subtract 1 from every number for counting from 0.
Here's the output:
This program randomly chooses a year between 1985 and 2015.
The random year is 1985
This program randomly chooses a year between 1985 and 2015.
The random year is 2000
This program randomly chooses a year between 1985 and 2015.
The random year is 2015
After re-running this one for a while, 2015 finally appeared (1/30% chance...) (thought something was wrong with my logic for a sec. turns out it just needed more chances to occur).
The off-by-one is easy to miss, so when in doubt, know that the computer almost always starts counting from 0 and a simple overlooked thing like adding 1 can cause the range to fall into place correctly.
Thursday, March 5, 2015
Post #5 - simple time conversion
Here's a simple program that converts an inputted time to 12-hr and 24-hr format. The user is supposed to enter the time in hours, minutes, and seconds as the time appears on his/her computer panel (keeping minutes and seconds separate - so 6:55 is entered as 6 hrs 50 min 5 sec).
#include <iostream>
using namespace std;
int main()
{ //Hours 0-24, Minutes and Seconds 0-60
int hours, minutes, seconds;
cout << "Please input current time in hours, minutes, & seconds: ";
cin >> hours >> minutes >> seconds;
if (minutes == 60)
{ hours = hours + 1;
minutes = 0;
}
if (seconds == 60)
{ minutes = minutes + 1;
seconds = 0;
}
if (hours < 12) //Convert it to 24-hr
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours + 12 << ":" << minutes << ":" << seconds;
}
else if (hours > 12) //Convert it to 12-hr
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours - 12 << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours << ":" << minutes << ":" << seconds;
}
else //Hour is 12:00 exactly
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours << ":" << minutes << ":" << seconds;
}
cout << endl;
return 0;
}
I tested some output with the hours that provide an overlap between 12 and 24 format, when the hour is 11, 12, or 1.
Entered 11 23 09
12-hour clock: 11:23:9
24-hour clock: 23:23:9
#include <iostream>
using namespace std;
int main()
{ //Hours 0-24, Minutes and Seconds 0-60
int hours, minutes, seconds;
cout << "Please input current time in hours, minutes, & seconds: ";
cin >> hours >> minutes >> seconds;
if (minutes == 60)
{ hours = hours + 1;
minutes = 0;
}
if (seconds == 60)
{ minutes = minutes + 1;
seconds = 0;
}
if (hours < 12) //Convert it to 24-hr
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours + 12 << ":" << minutes << ":" << seconds;
}
else if (hours > 12) //Convert it to 12-hr
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours - 12 << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours << ":" << minutes << ":" << seconds;
}
else //Hour is 12:00 exactly
{
cout << fixed << showpoint;
cout << "\n12-hour clock: " << hours << ":" << minutes << ":" << seconds;
cout << "\n24-hour clock: " << hours << ":" << minutes << ":" << seconds;
}
cout << endl;
return 0;
}
I tested some output with the hours that provide an overlap between 12 and 24 format, when the hour is 11, 12, or 1.
Entered 11 23 09
12-hour clock: 11:23:9
24-hour clock: 23:23:9
Entered 12 45 13
12-hour clock: 12:45:13
24-hour clock: 12:45:13
Entered 1 56 60
12-hour clock: 1:57:0
24-hour clock: 13:57:0
Note that if hours is 60 or minutes is 60, the next unit higher resets to 0. I wanted the program to print out leading zeroes or double zeroes to show this, but it only does trailing zeroes... need to find out how to print the leading ones too, so it will look better.
Wednesday, March 4, 2015
Post #4 - Functions!
Functions are quite fun (they do require getting used to remembering the prototype and function call, as well as the function itself) because they can drastically reduce the main section of a program to just a few statements, as the function calls do the work instead of the main program, allowing you to focus on other things in the program besides something simple like user input or output display. Functions also can help narrow down to one function's elements or operations instead of looking through the entire program for what caused the glitch.
An example - here is the program from before, except now everything is condensed into 3 functions corresponding to the 3 tasks of the program - (1) prompt for input, (2) display the input, (3) ask user to continue. Everything looks neater and easier to read! ^_^
Of course, for functions to work they need three presences in the program.
void UserInfo(string& a, string& b, string& c)
{
cout << "Enter your name: ";
getline(cin, a);
cout << "Enter your city: ";
getline(cin, b);
cout << "Enter your country: ";
getline(cin, c);
//Function call to DisplayInfo inside of function UserInfo
DisplayInfo(a, b, c);
}
An example - here is the program from before, except now everything is condensed into 3 functions corresponding to the 3 tasks of the program - (1) prompt for input, (2) display the input, (3) ask user to continue. Everything looks neater and easier to read! ^_^
Of course, for functions to work they need three presences in the program.
- The function prototype is seen by the compiler before main. It include the datatype the function will return to main (if no type is returned, void is used instead), the name of the function, and the datatypes of the variables the function will be receiving from main. The names do not have to match those within main and can be omitted, since it is the simplified form of the actual function which is added later. If the prototype is omitted, the compiler will not match the function call with the function definition, and will see the function call as undeclared and the program will not work.
- The function call is the only part of the function appearing in the program. Since its datatypes of its variables and its return type are already defined by the function definition and the prototype, they should not be included in the function call (over-definition). The variables passed to the function must use the names given in main, because the function will use the values in main for computations or to set values for them. Obviously these are necessary, without a function call your function doesn't do anything!
- The function definition comes either before or after main and is the primary body of the function. Here all the work the function does is clearly defined, and any result to be sent back to main is returned with return. If a result is expected to be returned, main should have a variable ready to store the returned result, or a cout statement displaying it in main. A function of type void can be displayed with cout but should not be assigned to a variable, since it is not a variable type. void is best used for functions that only assign or display values and do not do computations, like Display()or Input().
Following these three guidelines it's easy to write custom functions for a variety of computations. Functions can even be put inside other functions or called using a function (the latter does not work with void functions). In the above example, DisplayInfo could be put inside of UserInfo because they use the same strings as parameters and only differ in handling of the strings - one stores input while the other displays it.
void UserInfo(string& a, string& b, string& c)
{
cout << "Enter your name: ";
getline(cin, a);
cout << "Enter your city: ";
getline(cin, b);
cout << "Enter your country: ";
getline(cin, c);
//Function call to DisplayInfo inside of function UserInfo
DisplayInfo(a, b, c);
}
//DisplayInfo keeps its original code below, but can be omitted in main above since it is called here instead.
A note about & (passing by reference):
If & (ampersand) is placed at the end of the datatype, the variable can be externally modified by the function, a copy of the variable's location is not passed to the function as it is in passing by value (without a &). This shows why each string with & had its contents changed when data was input into each one using UserInfo(), the ampersand allowed data to be input directly into the strings passed from main, and they were then passed by value to DisplayInfo(), which displayed a copy of the strings (since it did not need to modify them). If no ampersand was included in the first function, DisplayInfo() would have been passed blank values, because passing by value does not change the values of the strings in main but the values of a copy of each string, which are held in different locations than those in main. In my opinion, if the values are going to be changed and used in main again, it's better to pass by reference to assign them their new values, and then pass them by value to not change what they were set to by the first function.
Post #3 - More on cin
Ok, so I wasn't able to get a post up yesterday because I had other obligations and there was no wi-fi where I was at, and I was too tired to start up a computer at 11PM when I had to get up early in the morning today. So here's a continuation post, even if it's not on the 3rd (which would have been a great way to track these, corresponding the day to the post and whatever. Post #4 will come right after this one, so getting back on track here lol.)
Where was that program at? Oh I was going to put in the city and country too. After testing it out from the previous post, it looks like I was a bit mixed up myself lol. getlines do work following each other; it's interchanging cin and getline that causes input skips (more on that below).
For instance I added additional input prompts to the last one, 3 getlines and 1 cin to show how this works:
With a do-while loop, the program continues to prompt the user to continue and repeats if 'y' for yes is entered (think videogame ending menus). Mine is a bit simplified - the logic behind getting it to continue on 'y', quit on 'n' but repeat the continue statement for any other letter is a bit tricky to implement, so for now it only looks for a 'y' to continue, any other letter causes it to quit.
do{ [...] cin >> confirm [...] }while(confirm == 'y' || confirm == 'Y');
The program continues as long as the user enters y or Y for confirm because of the loop's check condition - it "does" the code inside the loop "while" the condition remains true.
The highlighted cin.ignore(); is particularly important - without this, the program skips any input of the prompt at the beginning of the loop. Upon returning to the start of this loop with the name prompt, it will read the '\n' inside the input buffer instead. When a letter is entered for confirm through cin, the new line from the [Enter] key is added to the end of the char input. When the loop returns to the beginning, getline() reads the new line still held as input and interprets it as the user pressing the [Enter] without giving any input. To the tester, it looks like the program skipped the user's turn to input their name and went straight to the city prompt, because the program still has the leftover newline in the buffer from the end of the loop.
cin >> confirm;
cin.ignore();
To fix this, cin.ignore(); should be un-commented. cin.ignore() can work with several parameters (for example, cin.ignore(5) "ignores 5 characters", or cin.ignore(12, 'u') to "ignore 12 characters or until character 'u' is found"). However the default behavior of cin.ignore() - with nothing in the parentheses - is to skip the next immediate character in the buffer. If the user enters 'y', 'y' is stored in confirm, and the '\n' from the [Enter] is ignored. Since 'y' makes the loop true, the loop returns to the beginning, and since the input buffer has nothing in it after the ignored newline, the program will correctly prompt the user with a getline() for their name again without getting the newline unintentionally.
With this added, the program will now continue to prompt three times and display the inputs until the user enters anything other than 'y' or 'Y' at "Continue".
output without ignore:
Enter your name: Enter your city: Los angeles
Enter your country: California
Hi! My name is .
I live in Los angeles, California.
Continue? (Y/N): n
output with ignore:
Enter your name: Suika-chan
Enter your city: a tree
Enter your country: near Hakurei Shrine
Hi! My name is Suika-chan.
I live in a tree, near Hakurei Shrine.
Continue? (Y/N): n
Where was that program at? Oh I was going to put in the city and country too. After testing it out from the previous post, it looks like I was a bit mixed up myself lol. getlines do work following each other; it's interchanging cin and getline that causes input skips (more on that below).
For instance I added additional input prompts to the last one, 3 getlines and 1 cin to show how this works:
With a do-while loop, the program continues to prompt the user to continue and repeats if 'y' for yes is entered (think videogame ending menus). Mine is a bit simplified - the logic behind getting it to continue on 'y', quit on 'n' but repeat the continue statement for any other letter is a bit tricky to implement, so for now it only looks for a 'y' to continue, any other letter causes it to quit.
do{ [...] cin >> confirm [...] }while(confirm == 'y' || confirm == 'Y');
The program continues as long as the user enters y or Y for confirm because of the loop's check condition - it "does" the code inside the loop "while" the condition remains true.
The highlighted cin.ignore(); is particularly important - without this, the program skips any input of the prompt at the beginning of the loop. Upon returning to the start of this loop with the name prompt, it will read the '\n' inside the input buffer instead. When a letter is entered for confirm through cin, the new line from the [Enter] key is added to the end of the char input. When the loop returns to the beginning, getline() reads the new line still held as input and interprets it as the user pressing the [Enter] without giving any input. To the tester, it looks like the program skipped the user's turn to input their name and went straight to the city prompt, because the program still has the leftover newline in the buffer from the end of the loop.
cin >> confirm;
cin.ignore();
To fix this, cin.ignore(); should be un-commented. cin.ignore() can work with several parameters (for example, cin.ignore(5) "ignores 5 characters", or cin.ignore(12, 'u') to "ignore 12 characters or until character 'u' is found"). However the default behavior of cin.ignore() - with nothing in the parentheses - is to skip the next immediate character in the buffer. If the user enters 'y', 'y' is stored in confirm, and the '\n' from the [Enter] is ignored. Since 'y' makes the loop true, the loop returns to the beginning, and since the input buffer has nothing in it after the ignored newline, the program will correctly prompt the user with a getline() for their name again without getting the newline unintentionally.
With this added, the program will now continue to prompt three times and display the inputs until the user enters anything other than 'y' or 'Y' at "Continue".
output without ignore:
Enter your name: Enter your city: Los angeles
Enter your country: California
Hi! My name is .
I live in Los angeles, California.
Continue? (Y/N): n
output with ignore:
Enter your name: Suika-chan
Enter your city: a tree
Enter your country: near Hakurei Shrine
Hi! My name is Suika-chan.
I live in a tree, near Hakurei Shrine.
Continue? (Y/N): n
Monday, March 2, 2015
Post #2 - Last names
Images are now externally hosted on my imgur. please tell me if an image is unavailiable.
Here's a modification to the last one - what if the user wants to enter his/her last name too?
But entering a full name into the previous program results in an output problem - because cin is designed to stop when it reaches a whitespace in the input buffer, it places whatever string up until the whitespace into the variable, and leaves the rest in the input buffer. This can cause additional snafus as, when reading in multiple characters or strings, variables may not be given the full string that they are supposed to receive.
For example if I wanted to type out Have a nice day and display the entire line, there are a few options:
I would have to assign a variable to each word and show each string within a cout statement. However, since cin skips whitespace, the message all runs together.
cin >> part1 >> part2 >> part3 >> part4;
cout << part1 << part2 << part3 << part4;
The same output is also displayed when altering cout to be:
cout << part1 + part2 + part3 + part4;
in: Have a nice day
out: Haveaniceday
To fix the display, I could add spaces to the cout statement to make things look better.
cin >> part1 >> part2 >> part3 >> part4;
cout << part1 << " " << part2 << " " << part3 << " " << part4;
in: Have a nice day
out: Have a nice day
But this uses up more variables than necessary. To display everything at once using a single string variable, the full string also needs to be read into a single string variable.
We can use the function getline(a, b); to save the entire input read from a into the string variable b. getline picks up any whitespace it finds in the string, until it reaches the end of the string (marked invisibly by '\n' which is automatically appended to the end when the [Enter] key is pressed to submit the string). In most cases a will almost always be cin, as input is actually read into the standard input stream and then saved to b, an appropriate type variable, usually a string.
Now since cin is included within the getline function, the cin >> operator can be removed, since cin is already being called by the function.
getline(cin, name);
And to display the full input, just output the variable.
cout >> name;
The previous program with line 8 changed:
Here's the previous program's output when given two names:
Enter your name: Yukkuri Reimu
Hi! My name is Yukkuri.
Here's the modified version using getline, displaying both names.
Enter your name: Yukkuri Reimu
Hi! My name is Yukkuri Reimu.
For the next post, the program will read in a city and country along with the full name. This makes use of several getlines, which often run into problems with continued input. We'll see how the ignore member function can be used to keep input from becoming mixed up.
Here's a modification to the last one - what if the user wants to enter his/her last name too?
But entering a full name into the previous program results in an output problem - because cin is designed to stop when it reaches a whitespace in the input buffer, it places whatever string up until the whitespace into the variable, and leaves the rest in the input buffer. This can cause additional snafus as, when reading in multiple characters or strings, variables may not be given the full string that they are supposed to receive.
For example if I wanted to type out Have a nice day and display the entire line, there are a few options:
I would have to assign a variable to each word and show each string within a cout statement. However, since cin skips whitespace, the message all runs together.
cin >> part1 >> part2 >> part3 >> part4;
cout << part1 << part2 << part3 << part4;
The same output is also displayed when altering cout to be:
cout << part1 + part2 + part3 + part4;
in: Have a nice day
out: Haveaniceday
To fix the display, I could add spaces to the cout statement to make things look better.
cin >> part1 >> part2 >> part3 >> part4;
cout << part1 << " " << part2 << " " << part3 << " " << part4;
in: Have a nice day
out: Have a nice day
But this uses up more variables than necessary. To display everything at once using a single string variable, the full string also needs to be read into a single string variable.
We can use the function getline(a, b); to save the entire input read from a into the string variable b. getline picks up any whitespace it finds in the string, until it reaches the end of the string (marked invisibly by '\n' which is automatically appended to the end when the [Enter] key is pressed to submit the string). In most cases a will almost always be cin, as input is actually read into the standard input stream and then saved to b, an appropriate type variable, usually a string.
Now since cin is included within the getline function, the cin >> operator can be removed, since cin is already being called by the function.
getline(cin, name);
And to display the full input, just output the variable.
cout >> name;
The previous program with line 8 changed:
Here's the previous program's output when given two names:
Enter your name: Yukkuri Reimu
Hi! My name is Yukkuri.
Here's the modified version using getline, displaying both names.
Enter your name: Yukkuri Reimu
Hi! My name is Yukkuri Reimu.
For the next post, the program will read in a city and country along with the full name. This makes use of several getlines, which often run into problems with continued input. We'll see how the ignore member function can be used to keep input from becoming mixed up.
Sunday, March 1, 2015
Post #1 - Start of the journey
Edited this post for external image linking (take that, Picasa)
Hello everyone,
This is my first newbie programming blog. I hope to chronicle my progress in C++ coding while taking my university's programming courses.
To start off here is a program from when I was in my freshman class. It uses cin and cout to read in a name and display it.
sample output:
Enter your name: Reimu
Hi! My name is Reimu.
I may be posting on a daily basis. Depends on how much time I choose to blog here. Am working on a nice header picture for the blog as well.
Hello everyone,
This is my first newbie programming blog. I hope to chronicle my progress in C++ coding while taking my university's programming courses.
To start off here is a program from when I was in my freshman class. It uses cin and cout to read in a name and display it.
sample output:
Enter your name: Reimu
Hi! My name is Reimu.
I may be posting on a daily basis. Depends on how much time I choose to blog here. Am working on a nice header picture for the blog as well.
Subscribe to:
Posts (Atom)