C++ Code Sample
This program is from my "Fundamentals of C++" coding class.
It models a social network, in which you can add users, create connections, perform queries on your social network, determine relationship features, and make friend suggestions.
For the sake of length, the linked header files containing custom C++ classes are shown after the main Network file.
Throughout this assignment, I learned how to:
- Use breadth-first search to find a shortest path in a graph
- Implement a simple friend suggestion algorithm
- Create my own C++ classes and learn the syntax of defining data members
and methods
- Use File I/O and stringstreams to read/write text files containing structured
data (records)
- Understand the abstract representation of graphs (vertices=Users,
edges=Friend connections)
Main File
#include "network.h"
#include "user.h"
#include <iomanip>
using namespace std;
int main(int argc, char *argv[]){
Network network;
network.read_friends(argv[1]);
bool running = true;
while(running){
int choice;
cin>>choice;
//add user to the Network
if(choice == 1){
string name, fname, lname;
int year, zip;
cin>>fname>>lname>>year>>zip;
name = fname + " " + lname;
network.add_user(name, year, zip);
}
//add connection between 2 users
if(choice == 2){
string name1, name2, fname1, fname2, lname1, lname2;
cin>>fname1>>lname1>>fname2>>lname2;
name1 = fname1+" "+lname1;
name2 = fname2+" "+lname2;
network.add_connection(name1, name2);
}
//remove connection between 2 users
if(choice == 3){
string name1, name2, fname1, fname2, lname1, lname2;
cin>>fname1>>lname1>>fname2>>lname2;
name1 = fname1+" "+lname1;
name2 = fname2+" "+lname2;
network.remove_connection(name1, name2);
}
//print out network
if(choice == 4){
//header of table
cout<<"ID"<<setw(15)<<"Name"<<setw(8)<<"Year"<<setw(10)<<"Zip"<<endl;
//table styling
for(int i=0; i<36; i++){
cout<<"=";
}
cout<<endl;
int lines = network.users.size();
for(int i=0; i<lines; i++){
cout<<network.get_id(network.users[i].get_name())<<"."<<setw(15);
cout<<network.users[i].get_name()<<setw(8);
cout<<network.users[i].get_year()<<setw(10);
cout<<network.users[i].get_zip();
cout<<endl;
}
}
//print out a user's friend Network
if(choice == 5){
string fname, lname, name;
cin>>fname>>lname;
name = fname+" "+lname;
int index;
for(int i=0; i<network.users.size(); i++){
if(network.users[i].get_name() == name){
index = i;
}
}
//header of table
cout<<"ID"<<setw(15)<<"Name"<<setw(8)<<"Year"
<<setw(10)<<"Zip"<<endl;
//table styling
for(int i=0; i<36; i++){
cout<<"=";
}
cout<<endl;
for(int i=0; i<network.users[index].friends.size(); i++){
//get friend id
int friendid = network.users[index].friends[i];
//print friends
cout<<friendid<<"."<<setw(15);
cout<<network.users[friendid].get_name()<<setw(8);
cout<<network.users[friendid].get_year()<<setw(10);
cout<<network.users[friendid].get_zip();
cout<<endl;
}
}
if(choice == 6){
char filename[50];
cin >> filename;
network.write_friends(filename);
}
// compute the shortest relational distance between two users using Breadth-First Search
if(choice == 7){
//get name ids
string name1, name2, fname1, fname2, lname1, lname2;
cin>>fname1>>lname1>>fname2>>lname2;
name1 = fname1+" "+lname1;
name2 = fname2+" "+lname2;
int id1, id2;
if(name1 == name2){
cout<<"Distance: 0"<<endl;
cout<<name1;
continue;
}
for(int i=0; i<network.users.size(); i++){
if(network.users[i].get_name() == name1){
id1 = i;
}
if(network.users[i].get_name() == name2){
id2 = i;
}
}
if(id1 == id2){
cout<<"Distance: 0"< path = network.shortest_path(id1, id2);
if(path.empty()){
cout<<"None";
continue;
}
else{
cout<<"Distance: "<<path.size()-1<<endl;
}
for(int i=0; i<path.size(); i++){
//if not last person, print names and arrows
if(i != path.size()-1){
//if last person, print just name
cout<<network.users[path[i]].get_name()<<" -> ";
}
else{
cout<<network.users[path[i]].get_name();
}
}
}
if(choice == 8){
vector<vector<int> > groups = network.groups();
for(int i=0; i<groups.size(); i++){
cout<<"Set "<<i+1<<" => ";
//print names for group
for(int j=0; j<groups[i].size(); j++){
if(j != groups[i].size() -1){
cout<<network.users[groups[i][j]].get_name()<<", ";
}
else{
cout<<network.users[groups[i][j]].get_name()<<endl;
}
}
}
}
if(choice == 9){
string fname, lname, name;
cin>>fname>>lname;
name = fname+" "+lname;
int index;
int defaultScore = -1;
int* score = &defaultScore;
for(int i=0; i<network.users.size(); i++){
if(network.users[i].get_name() == name){
index = i;
}
}
vector<int> suggestions = network.suggest_friends(index, *score);
//print out
cout<<"The suggested friend(s) is/are:"<<endl;
if(suggestions.size() == 0){
cout<<"None";
}
else{
for(int i=0; i<suggestions.size(); i++){
//get name
cout<<"\t"<<network.users[suggestions[i]].get_name();
cout<<" Score: "<<*score<<endl;
}
}
}
if(choice != 1 && choice != 2 && choice != 3 &&
choice != 4 && choice != 5 && choice != 6 && choice != 7
&& choice != 8 && choice != 9){
running = false;
}
}
return 0;
}
network.h
#ifndef NETWORK_H
#define NETWORK_H
#include "user.h"
#include "delist.h"
class Network {
public:
Network();
~Network();
int read_friends(const char *filename);
int write_friends(const char *filename);
void add_user(std::string username, int yr, int zipcode);
int add_connection(std::string name1, std::string name2);
int remove_connection(std::string name1, std::string name2);
int get_id(std::string username);
std::vector<User> users;
std::vector<int> shortest_path(int from, int to);
std::vector<std::vector<int> > groups();
std::vector<int> suggest_friends(int who, int& score);
private:
};
#endif
network.cpp
#include "network.h"
#include "delist.cpp"
using namespace std;
Network::Network() {
}
Network::~Network() {
}
int Network::read_friends(const char *filename){
//open file
ifstream ifile(filename);
//if open fails, return -1
if(!ifile){
cout<<"Couldn't open file.";
return -1;
}
//get number of users in txt
int numUsers;
ifile>>numUsers;
//cycle through all the users
for(int i=0; i<numUsers; i++){
int id, year, zip, friendID;
int numfriends = 0;
string name, fname, lname, friendids;
//get user id
ifile>>id;
// first getline consumes that garbage newline
getline(ifile, name);
// second getline actually reads in the whole name
//get username
getline(ifile, name);
stringstream ss(name);
ss>>fname>>lname;
name = fname + " " + lname;
//get year and zip
ifile>>year;
ifile>>zip;
//get string of friend ids
getline(ifile, friendids);
getline(ifile, friendids);
//make user
User* temp = new User(name, year, zip);
//get num friends
stringstream stream(friendids);
int n;
while(stream>>n){
numfriends++;
}
//add friends to this user
stringstream again(friendids);
for(int j=0; j<numfriends; j++){
again>>friendID;
temp -> add_friend(friendID);
}
//assign id
temp->add_id(id);
//add user to vector
users.push_back(*temp);
delete temp;
}
return 0;
}
int Network::write_friends(const char *filename)
{
//create output file
ofstream ofile(filename);
//write num of users
ofile<<users.size();
ofile<<endl;
//loop through users and write
for(int i=0; i<users.size(); i++){
ofile<<i<<endl;
ofile<<'\t'<<users[i].get_name()<<endl;
ofile<<'\t'<<users[i].get_year()<<endl;
ofile<<'\t'<<users[i].get_zip()<<endl;
ofile<<'\t';
for(int j=0; j<users[i].friends.size(); j++){
ofile<<users[i].friends[j]<<" ";
}
ofile<<endl;
}
return 0;
}
void Network::add_user(std::string username, int yr, int zipcode){
//create new user
User* temp = new User(username, yr, zipcode);
//add id
temp->add_id(users.size());
//add to users vector
users.push_back(*temp);
delete temp;
}
int Network::add_connection(std::string name1, std::string name2){
int id1 = -1;
int id2 = -1;
for(int i=0; i<users.size(); i++){
if(users[i].get_name() == name1){
id1 = i;
}
if(users[i].get_name() == name2){
id2 = i;
}
}
if(id1 == -1){
cout<<"Invalid user(s).";
return -1;
}
if(id2 == -1){
cout<<"Invalid user(s).";
return -1;
}
//add friends
users[id1].add_friend(id2);
users[id2].add_friend(id1);
return 0;
}
int Network::remove_connection(std::string name1, std::string name2){
int id1 = -1;
int id2 = -1;
for(int i=0; i<users.size(); i++){
if(users[i].get_name() == name1){
id1 = i;
}
if(users[i].get_name() == name2){
id2 = i;
}
}
if(id1 == -1){
cout<<"Invalid user(s).";
return -1;
}
if(id2 == -1){
cout<<"Invalid user(s).";
return -1;
}
//delete friends
users[id1].delete_friend(id2);
users[id2].delete_friend(id1);
return 0;
}
int Network::get_id(std::string username){
for(int i=0; i<users.size(); i++){
if(users[i].get_name() == username){
return i;
}
}
cout<<"Invalid user.";
return -1;
}
vector<int> Network::shortest_path(int from, int to){
vector<int> depth;
//set depth to -1 for all
for(int i=0; i<users.size(); i++){
depth.push_back(-1);
}
//create list and add 1st vertex
DEList list;
list.push_front(from);
depth[from] = 0;
//BFS algorithm
while(!list.empty()){
int x;
x = list.front();
list.pop_front();
int numFriends = users[x].friends.size();
for(int i=0; i<numFriends; i++){
int friendID = users[x].friends[i];
if(depth[friendID] == -1){
list.push_back(friendID);
//set predecessor id
users[friendID].predecessor = x;
depth[friendID] = depth[x] + 1;
}
}
}
//return empty vector if no path exists
if(depth[to] == -1){
vector<int> empty;
return empty;
}
vector<int> path1;
path1.push_back(to);
int pred = users[to].predecessor;
for(int i=0; i<depth[to]-1; i++){
//add predecessor to vector
path1.push_back(pred);
//set new predecessor id value
pred = users[pred].predecessor;
}
path1.push_back(from);
//change order of vector
vector<int> pathFinal;
for(int i=path1.size()-1; i>=0; i--){
pathFinal.push_back(path1[i]);
}
return pathFinal;
}
vector<vector<int> > Network::groups(){
vector<vector<int> > total;
//BFS
vector<bool> visited;
//set depth to -1 for all
for(int i=0; i<users.size(); i++){
visited.push_back(false);
}
//create list and add 1st vertex
DEList list;
list.push_front(0);
bool allVisited = false;
//BFS algorithm
while(!allVisited){
//create vector of group
vector<bool> newGroup;
for(int i=0; i<users.size(); i++){
newGroup.push_back(false);
}
while(!list.empty()){
int x;
x = list.front();
//visited current user
newGroup[x] = true;
visited[x] = true;
list.pop_front();
int numFriends = users[x].friends.size();
for(int i=0; i<numFriends; i++){
int friendID = users[x].friends[i];
if(visited[friendID] == false){
list.push_back(friendID);
newGroup[friendID] = true;
visited[friendID] = true;
}
}
}
//check for non-visited users
int falseID = -1;
bool noFalses = true;
for(int i=0; i<users.size(); i++){
if(visited[i] == false){
if(falseID == -1){
falseID = i;
}
noFalses = false;
}
}
if(falseID != -1){
list.push_front(falseID);
}
//create group and then add it to group of vecs
vector<int> group;
for(int i=0; i<users.size(); i++){
if(newGroup[i] == true){
group.push_back(i);
}
}
total.push_back(group);
allVisited = noFalses;
}
return total;
}
vector<int> Network::suggest_friends(int who, int& score)
{
//BFS Search
vector<int> suggestions;
vector<int> scores;
for(int i=0; i<users.size(); i++){
scores.push_back(0);
}
//go through all of user's friends
for(int i=0; i<users[who].friends.size(); i++)
{
int friendID = users[who].friends[i];
int numMutual = users[friendID].friends.size();
for(int j=0; j<numMutual; j++)
{
//if ID is who, skip
if(users[friendID].friends[j] == who)
{
continue;
}
//check if curr is already friend of who
bool alreadyFriend = false;
for(int z=0; z<users[who].friends.size(); z++){
if(users[friendID].friends[j] == users[who].friends[z]){
alreadyFriend = true;
}
}
//add point to mutual friend
if(!alreadyFriend){
int mutualID = users[friendID].friends[j];
scores[mutualID]++;
}
}
}
// return scores;
int max = 0;
for(int i=0; i<scores.size(); i++){
if(scores[i] > max){
max = scores[i];
}
}
if(max > 0){
score = max;
//add all the max score users
for(int i=0; i<scores.size(); i++){
if(scores[i] == max){
suggestions.push_back(i);
}
}
}
else{
score = -1;
}
return suggestions;
}
user.h
#ifndef USER_H
#define USER_H
#include
#include
#include
#include
#include
class User {
public:
User(std::string username, int yr, int zipCode);
void add_friend(int id);
void delete_friend(int id);
void add_id(int id);
int get_year();
int get_zip();
std::vector friends;
int depth;
int predecessor;
int ID;
std::string get_name();
private:
int year;
int zip;
std::string name;
};
#endif
user.cpp
#include "user.h"
using namespace std;
//initialize
User::User(string username, int yr, int zipCode){
name = username;
year = yr;
zip = zipCode;
}
void User::add_friend(int id){
bool present = false;
for(int i=0; i<friends.size(); i++){
if(friends[i] == id){
present = true;
}
}
if(present != true){
friends.push_back(id);
}
}
void User::delete_friend(int id){
for(int i=0; i<friends.size(); i++)
{
if(friends[i] == id){
friends.erase(friends.begin()+i);
}
}
}
void User::add_id(int id){
ID = id;
}
int User::get_zip(){
return zip;
}
int User::get_year(){
return year;
}
string User::get_name(){
return name;
}