Hi there
When I input locations from a txt file I am getting a peculiar error where it seems to miss off the first entry, yet add a garbage entry to the end of the link list (it is designed to take the name, latitude and longitude for each location you will notice). I imagine this to be an issue with where it starts collecting the inputs and where it stops but I cant find the error!! It reads the first line correctly but then skips to the next before adding it because during testing for the bug it had no record of the first location Lisbon though whilst stepping into the method call it was reading it. Very bizarre but hopefully someone knows the issue. Here is firstly my header file:
#include <string>
struct locationNode
{
char nodeCityName [35];
double nodeLati;
double nodeLongi;
locationNode* Next;
void CorrectCase() // Correct upper and lower case letters of input
{
int MAX_SIZE = 35;
int firstLetVal = this->nodeCityName[0], letVal;
int n = 1; // variable for name index from second letter onwards
if((this->nodeCityName[0] >90) && (this->nodeCityName[0] < 123)) // First letter is lower case
{
firstLetVal = firstLetVal - 32; // Capitalise first letter
this->nodeCityName[0] = firstLetVal;
}
while(n <= MAX_SIZE - 1)
{
if((this->nodeCityName[n] >= 65) && (this->nodeCityName[n] <= 90))
{
letVal = this->nodeCityName[n] + 32;
this->nodeCityName[n] = letVal;
}
n++;
}
//cityNameInput = this->nodeCityName;
}
};
class Locations
{
private:
int size;
public:
Locations(){
}; // constructor for the class
locationNode* Head;
//int Add(locationNode* Item);
};
And here is the file containing main:
// U08221.cpp : main project file.
#include "stdafx.h"
#include "Locations.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int n = 0,x, locationCount = 0, MAX_SIZE = 35;
string cityNameInput;
char targetCity[35];
bool acceptedInput = false, userInputReq = true, match = false, nodeExists = false;// note: addLocation(), set to true to enable user input as opposed to txt file
locationNode *start_ptr = NULL; // pointer to first entry in the list
locationNode *temp, *temp2; // Part is a pointer to a new locationNode we can assign changing value followed by a call to Add
locationNode *seek, *bridge;
void setElementsNull(char cityParam[])
{
int y=0, count =0;
while(cityParam[y] != NULL)
{
y++;
}
while(y < MAX_SIZE)
{
cityParam[y] = NULL;
y++;
}
}
void addLocation()
{
temp = new locationNode; // declare the space for a pointer item and assign a temporary pointer to it
if(!userInputReq) // bool that determines whether user input is required in adding the node to the list
{
cout << endl << "Enter the name of the location: ";
cin >> temp->nodeCityName;
temp->CorrectCase();
setElementsNull(temp->nodeCityName);
cout << endl << "Please enter the latitude value for this location: ";
cin >> temp->nodeLati;
cout << endl << "Please enter the longitude value for this location: ";
cin >> temp->nodeLongi;
cout << endl;
}
temp->Next = NULL; //set to NULL as when one is added it is currently the last in the list and so can not point to the next
if(start_ptr == NULL){ // if list is currently empty, start_ptr will point to this node
start_ptr = temp;
}
else
{ temp2 = start_ptr;
// We know this is not NULL - list not empty!
while (temp2->Next != NULL)
{
temp2 = temp2->Next; // Move to next link in chain until reach end of list
}
temp2->Next = temp;
}
++locationCount; // increment counter for number of records in list
if(!userInputReq){
cout << "Location sucessfully added to the database! There are " << locationCount << " location(s) stored" << endl;
}
}
void populateList(){
ifstream inputFile;
inputFile.open ("locations.txt", ios::in);
userInputReq = true;
temp = new locationNode; // declare the space for a pointer item and assign a temporary pointer to it
do
{
inputFile.get(temp->nodeCityName, 35, ' ');
setElementsNull(temp->nodeCityName);
inputFile >> temp->nodeLati;
inputFile >> temp->nodeLongi;
setElementsNull(temp->nodeCityName);
if(temp->nodeCityName[0] == 10) //remove linefeed from input
{
for(int i = 0; temp->nodeCityName[i] != NULL; i++)
{
temp->nodeCityName[i] = temp->nodeCityName[i + 1];
}
}
addLocation();
}
while(!inputFile.eof());
userInputReq = false;
cout << "Successful!" << endl << "List contains: " << locationCount << " entries" << endl;
cout << endl;
inputFile.close();
}
bool nodeExistTest(char targetCity[]) // see if entry is present in the database
{
match = false;
seek = start_ptr;
int letters = 0, letters2 = 0, x = 0, y = 0;
while(targetCity[y] != NULL)
{
letters2++;
y++;
}
while(x <= locationCount) // locationCount is number of entries currently in list
{
y=0, letters = 0;
while(seek->nodeCityName[y] != NULL) // count letters in the current name
{
letters++;
y++;
}
if(letters == letters2) // same amount of letters in the name
{
y = 0;
while(y <= letters) // compare each letter against one another
{
if(targetCity[y] == seek->nodeCityName[y])
{
match = true;
y++;
}
else
{
match = false;
y = letters + 1; // no match, terminate comparison
}
}
}
if(match)
{
x = locationCount + 1; //found match so terminate loop
}
else{
if(seek->Next != NULL)
{
bridge = seek;
seek = seek->Next;
x++;
}
else
{
x = locationCount + 1; // end of list so terminate loop
}
}
}
return match;
}
void deleteRecord() // complete this
{
int junction = 0;
locationNode *place;
cout << "Enter the name of the city you wish to remove" << endl;
cin >> targetCity;
setElementsNull(targetCity);
if(nodeExistTest(targetCity)) //if this node does exist
{
if(seek == start_ptr) // if it is the first in the list
{
junction = 1;
}
if(seek != start_ptr && seek->Next == NULL) // if it is last in the list
{
junction = 2;
}
switch(junction) // will alter list accordingly dependant on where the searched for link is
{
case 1:
start_ptr = start_ptr->Next;
delete seek;
--locationCount;
break;
case 2:
place = seek;
seek = bridge;
delete place;
--locationCount;
break;
default:
bridge->Next = seek->Next;
delete seek;
--locationCount;
break;
}
}
else
{ cout << targetCity << "That entry does not currently exist" << endl << endl << endl;
}
}
void searchDatabase()
{
char choice;
cout << "Enter search term..." << endl;
cin >> targetCity;
if(nodeExistTest(targetCity))
{
cout << "Entry: " << endl << endl;
}
else
{
cout << "Sorry, that city is not currently present in the list." << endl << "Would you like to add this city now Y/N?" << endl;
cin >> choice;
/*while(choice != ('Y' || 'N'))
{
cout << "Please enter a valid choice..." << endl;
cin >> choice;
}*/
switch(choice)
{
case 'Y':
addLocation();
break;
case 'N':
break;
default :
cout << "Invalid choice" << endl;
break;
}
}
}
void printDatabase()
{
temp = start_ptr; // set temp to the start of the list
do
{ if (temp == NULL)
{
cout << "You have reached the end of the database" << endl;
}
else
{ // Display details for what temp points to at that stage
cout << "Location : " << temp->nodeCityName << endl;
cout << "Latitude : " << temp->nodeLati << endl;
cout << "Longitude : " << temp->nodeLongi << endl;
cout << endl;
// Move on to next locationNode if one exists
temp = temp->Next;
}
}
while (temp != NULL);
}
void nameValidation(string name)
{
n = 0; // start from first letter
x = name.size();
while(!acceptedInput)
{
if((name[n] >= 65) && (name[n] <= 122)) // is in the range of letters
{
while(n <= x - 1)
{
while((name[n] >=91) && (name[n] <=97)) // ERROR!!
{
cout << "Please enter a valid city name" << endl;
cin >> name;
}
n++;
}
}
else {
cout << "Please enter a valid city name" << endl;
cin >> name;
}
if(n <= x - 1)
{
acceptedInput = true;
}
}
cityNameInput = name;
}
int main(array<System::String ^> ^args)
{
//main contains test calls to functions at present
cout << "Populating list...";
populateList();
printDatabase();
deleteRecord();
printDatabase();
cin >> cityNameInput;
}
The text file contains this (ignore the names, they are just for testing!!):
Lisbon 45 47
Fattah 45 47
Darius 42 49
Peter 45 27
Sarah 85 97
Michelle 45 47
John 25 67
Colin 35 87
Shiron 40 57
George 34 45
Sean 22 33
The output omits Lisbon, but adds on a garbage entry with nonsense values. Any ideas why? Thank you in advance.