How do I implement a while loop to this function - c++

I am working on a school project where we will make a contact book. In one of the functions, it must find contacts using the first name.
The error that occurs is that it only shows one contact in the vector. I want all contacts with the same name to be displayed.
How do I implement a loop or counter (i++) so that it includes all contacts with the same name and not just take the first index?
Im new to C++ and appreciate all help :)
My function:
int findTargetFirstName(vector<Kontaktbok>& bok, string target) {
for (int i = 0; i < bok.size(); i++)
if (bok[i].fnamn == target) return i;
return -1;
void search(vector<Kontaktbok>& bok) {
if (bok.size() > 0) {
string firstname;
cout << "First name of the contact: ";
getline(cin, firstname);
int pos = findTargetFirstName(bok, firstname);
cout << "Firstname, Lastname, Address, Pnummer, E-post, Telefonnummer" << endl;
if (pos>=0) {
cout << left;
cout << setw(10) << bok[pos].fnamn << left
<< setw(15) << bok[pos].enamn << left
<< setw(20) << bok[pos].adress << left
<< setw(15) << bok[pos].pnummer <<left
<< setw(25) << bok[pos].epost <<left
<< setw(15) << bok[pos].telnummer << left << endl;
}
cout << "********************************************************************************" << endl;
}
}

One way is adding a parameter to determine which element to start from.
int findTargetFirstName(vector<Kontaktbok>& bok, string target, int start = 0) {
for (int i = start; i < bok.size(); i++)
if (bok[i].fnamn == target) return i;
return -1;
}
void search(vector<Kontaktbok>& bok) {
if(bok.size() > 0) {
string firstname;
cout << "First name of the contact: ";
getline(cin, firstname);
int pos = findTargetFirstName(bok, firstname);
cout << "Firstname, Lastname, Address, Pnummer, E-post, Telefonnummer" << endl;
while (pos>=0){ // change if to while
cout << left;
cout << setw(10) << bok[pos].fnamn << left
<< setw(15) << bok[pos].enamn << left
<< setw(20) << bok[pos].adress << left
<< setw(15) << bok[pos].pnummer <<left
<< setw(25) << bok[pos].epost <<left
<< setw(15) << bok[pos].telnummer << left << endl;
pos = findTargetFirstName(bok, firstname, pos + 1); // search for next contact
}
cout << "********************************************************************************" << endl;
}
}
Another way is having the function findTargetFirstName return a vector of contacts that meets the condition.
vector<int> findTargetFirstName(vector<Kontaktbok>& bok, string target) {
vector<int> ret;
for (int i = start; i < bok.size(); i++)
if (bok[i].fnamn == target) ret.push_back(i);
return ret;
}
void search(vector<Kontaktbok>& bok) {
if(bok.size() > 0) {
string firstname;
cout << "First name of the contact: ";
getline(cin, firstname);
vector<int> poses = findTargetFirstName(bok, firstname); // change type and variable
cout << "Firstname, Lastname, Address, Pnummer, E-post, Telefonnummer" << endl;
for (int pos : poses){ // change if to range-based for
cout << left;
cout << setw(10) << bok[pos].fnamn << left
<< setw(15) << bok[pos].enamn << left
<< setw(20) << bok[pos].adress << left
<< setw(15) << bok[pos].pnummer <<left
<< setw(25) << bok[pos].epost <<left
<< setw(15) << bok[pos].telnummer << left << endl;
}
cout << "********************************************************************************" << endl;
}
}

Related

Cannot edit data stored in a linked list's node using setter

My Node class:
class Node {
private:
int orderId; //unique for each node
Cake cake;
Customer customerInfo;
Node* next;
public:
Node() {
orderId = 0;
next = NULL;
}
Node(int id, Cake ck, Customer c) {
orderId = id;
cake = ck;
customerInfo = c;
}
int getOrderId() {
return orderId;
}
Cake getCake() {
return cake;
}
Customer getCustomerInfo() {
return customerInfo;
}
Node* getNext() {
return next;
}
void setOrderId(int id) {
orderId = id;
}
void setCake(Cake ck) {
cake = ck;
}
void setCustomerInfo(Customer c) {
customerInfo = c;
}
void setNext(Node* n) {
next = n;
}
};
My Cake class:
class Cake {
private:
string code;
string flavour;
double weight;
double unitPrice;
int qty;
public:
Cake() {
code = "";
flavour = "";
weight = 0.0;
unitPrice = 0.0;
qty = 0;
}
Cake(string c, string f, double w, double p, int q) {
code = c;
flavour = f;
weight = w;
unitPrice = p;
qty = q;
}
string getCode() {
return code;
}
...other getters
void setCode(string c) {
code = c;
}
...other setters
};
Function to edit a node:
void editOrder(SinglyLinkedList* s)
{
int orderId, editOption, cakeOption, weightOption, qty, flavourOption;
char next = '\0';
bool isEmpty;
//prompt for order id
cout << "Enter ID of order to be edited: ";
cin >> orderId;
//check if order exists
if (s->checkNodeExist(orderId) != NULL) {
Node* nodeTemp = s->checkNodeExist(orderId);
do {
//ask which aspect to edit
cout << "Which aspect do you want to edit?" << endl;
cout << left << setw(9) << "OPTION" << setw(15) << "ASPECT" << endl;
cout << "----------------------------" << endl << endl;
cout << left << setw(9) << "1" << setw(15) << "Code / Cake Type" << endl;
cout << left << setw(9) << "2" << setw(15) << "Flavour" << endl;
cout << left << setw(9) << "3" << setw(15) << "Weight" << endl;
cout << left << setw(9) << "4" << setw(15) << "Quantity" << endl << endl;
cout << "Enter option: ";
cin >> editOption;
switch (editOption) {
case 1:
//display cake choices & prompt for cake choice
cout << "Choose a type of cake." << endl << endl;
cout << left << setw(9) << "OPTION" << setw(15) << "CAKE" << setw(4) << "CODE" << endl;
cout << "----------------------------" << endl;
cout << left << setw(9) << "1" << setw(15) << "Pound Cake" << setw(4) << "CK01" << endl;
cout << left << setw(9) << "2" << setw(15) << "Sponge Cake" << setw(4) << "CK02" << endl;
cout << left << setw(9) << "3" << setw(15) << "Genoise Cake" << setw(4) << "CK03" << endl;
cout << left << setw(9) << "4" << setw(15) << "Layer Cake" << setw(4) << "CK04" << endl;
cout << left << setw(9) << "5" << setw(15) << "Icing Cake" << setw(4) << "CK05" << endl;
cout << left << setw(9) << "6" << setw(15) << "Cheese Cake" << setw(4) << "CK06" << endl << endl;
cout << "Enter option: ";
cin >> cakeOption;
switch (cakeOption)
{
case 1:
(*nodeTemp).getCake().setCode("CK01"); //FAIL TO UPDATE THE "CODE" USING SETTER
break;
For example, the targeted node has a cake object with code "CK02", but now I want it to set it into "CK01" using setter. But I just can't figure out why the setter function isn't working?
PS. just started learning linked list and pointers in C++ so please be easy on me. Any help is greatly appreciated...thanks:D
It's because your getCake method returns a copy of the cake in your Node object. Your setter then changes the copy, but this leaves the original unchanged.
Simple fix is to make your getter return a reference
Cake& getCake() {
return cake;
}
Now getCake returns a reference to the cake in the node, not a copy of it.

Sorting names in an array variable inside a structure alphabetically

I'm making this student record program that my prof asked us to do. It keeps saying cannot convert 'StudRec' to 'StudRec' in assignment and sometimes it says cannot convert char* to const char*. StudRec is my struct variable and this is the function that should sort the recorded names alphabetically.
void sort_name(StudRec name[], StudRec temp[], int studcount)
{
if (studcount > 0)
{
for (int i=0; i<studcount; i++)
{
for (int j=studcount; j<=i; j++)
{
if(strcmp(name[j].nm, name[j+1].nm) > 0)
{
temp=name[j];
name[j]= name[j+1];
name[j+1]= temp;
}
}
}
cout << "\t| |\t\t\t The records have been sorted alphabetically by name.\n";
}
else
{
cout << "\t| |\t\t\t There is no current record to sort by name.\n\n";
}
}
Ok, assuming that the StudRec has all necessary operations (assignment, default constructor, etc.), you don't need to pass an array of temp values:
void sort_name(StudRec name[], int studcount)
{
StudRec temp;
// ...
}
That should fix one issue: you are trying to assign an element to the whole array:
temp=name[j];
Even better would be to define temp right where you use it:
const StudRec temp = name[j];
Anyway, I guess you are trying to implement a BubbleSort, and your implementation is incorrect because of the indexing. Should be:
for (int i = 1; i < studcount; ++i)
for (int j = 0; j < studcount - i; ++j)
This is the code in the fGrade function:
void fGrade(StudRec rec[], int studcount)
{
string id;
if (studcount > 0)
{
cout << "\n\n\t| |\t\t =====================================================\n";
cout << "\t| |\t\t\t\t STUDENT'S FINAL GRADE \n";
cout << "\t| |\t\t =====================================================\n\n";;
check: cout << "\n\t| |\t\t\t Enter student's ID Number: ";
cin >> id;
int index = search(rec, id, studcount);
if (index != -1 && studcount > 0)
{
rec[index].fgrd = (((rec[index].quiz / 150) * 100) * 0.2) + (((rec[index].hw / 20) * 100) * 0.1) + (((rec[index].midT / 100) * 100) * 0.15)
+ (((rec[index].fExam / 100) * 100) * 0.15) + (((rec[index].acts / 150) * 100) * 0.25) + (((rec[index].proj / 100) * 100) * 0.15);
cout << left << setw(10) << "\n ID No." << setw(30) << "NAME" << setw(15) << "FINAL GRADE" << setw(10) << "REMARKS";
cout << "\n ------------------------------------------------------------\n";
cout << " " << left << setw(8) << rec[index].id << setw(30) << rec[index].nm << setw(15) << fixed << setprecision(2) << rec[index].fgrd;
if (rec[index].fgrd >= 75 && rec[index].fgrd <= 100)
{
cout << setw(10) << "Passed\n\n";
}
else if (rec[index].fgrd < 75)
{
cout << setw(10) << "Failed\n\n";
}
}
else
{
cout << "\t| |\t\t\t This record does not exist. Check your ID and try again.";
goto check;
}
}
else
{
cout << "\t| |\t\t\t There is no current record to calculate a final grade.\n\n";
return;
}
}
and this is the code for the view_rec function:
void view_rec(StudRec rec[], int studcount)
{
if (studcount > 0)
{
cout << "\n\n\t| |\t\t ===================================================\n";
cout << "\t| |\t\t\t\t VIEW STUDENT RECORD \n";
cout << "\t| |\t\t ===================================================\n\n";
int i=0;
cout << "\n\t| |\t\t " << left << setw(10) << "ID" << setw(30) << "NAME" << setw(7) << "SEX" << setw(10) << "QUIZ";
cout << setw(14)<< "ASSIGNMENT" << setw(11) << "MIDTERM" << setw(14) << "FINAL EXAM" << setw(12) << "ACTIVITY";
cout << setw(11)<< "PROJECT" << setw(9) << "TOTAL\n";
cout << "\t| |\t\t " << "----------------------------------------------------------------------------------------------------------------------------\n\n";
while(i <= studcount)
{
if(rec[i].id != "")
{
cout << "\t| |\t\t " << left << setw(10) << rec[i].id << setw(30) << rec[i].nm << setw(7) << rec[i].sex;
cout << setw(10) << rec[i].quiz << setw(14) << rec[i].hw << setw(11) << rec[i].midT;
cout << setw(14) << rec[i].fExam << setw(12) << rec[i].acts << setw(11) << rec[i].proj << setw(9) << rec[i].total;
cout << endl << endl;
}
i+=1;
}
}
else
{
cout << "\t| |\t\t\t There is no current record to view.\n\n";
return;
}
}

C++ not getting all lines from .txt file when tokenising

I am trying to read in my text file that contains book list.
However, when I output the file that I read in, I found there is some left out.
I'm wondering if the problem is happening when I try to tokenise the file.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <string>
#include <conio.h>
#include <cctype>
using namespace std;
typedef struct
{
int shelf;
int level;
} LOCATION_TYPE;
typedef struct
{
char isbn[14];
char author[40];
char title[40];
char publisher[40];
int year;
char genre[20];
char price[10];
char quantity[3];
LOCATION_TYPE location;
} BOOK_TYPE;
void menu();
void list(BOOK_TYPE book[], int total_book);
void search(BOOK_TYPE students[], int total_student);
int main(void)
{
BOOK_TYPE book[100];
ifstream input("booklist.txt"); // read input from a text file.
if (!input) // check error.
{
cout << "Error opening file.\n";
exit(100); // testing if the text file is connected
}
else
{
char delim[] = ",";
char temp[100];
int index = -1, choice;
input.getline(temp, 100, '\n');
while(input)
{
char* token = strtok(temp, delim);
strcpy(book[++index].isbn, token);
strcpy(book[index].author, strtok(NULL, delim));
strcpy(book[index].title, strtok(NULL, delim));
strcpy(book[index].publisher, strtok(NULL, delim));
book[index].year = atoi(strtok(NULL, delim));
strcpy(book[index].price, strtok(NULL, delim));
strcpy(book[index].quantity, strtok(NULL, delim));
book[index].location.shelf = atoi(strtok(NULL, delim));
book[index].location.level = atoi(strtok(NULL, delim));
strcpy(book[index].genre, strtok(NULL, delim));
// clear unwanted whitespace
if (input.peek() == '\n')
input.ignore(256, '\n');
// read next number
input.getline(temp, 100, '\n');
//token = strtok(book[++index], delim);
}
input.close();
system("cls");
menu();
cin >> choice;
while (choice != 0)
{
if (choice == 1)
{
list(book, index);
}
else if (choice == 2)
{
search(book, index);
}
else
{
system("cls");
cout << "Invalid input. Please key in number 0-4.\n";
system("pause");
}
system("cls");
menu();
cin >> choice;
}
}
return 0;
}
void menu()
{
cout << "UNDERGROUND BOOKS" << endl;
cout << "1. List all books record" << endl;
cout << "2. Search books" << endl;
cout << "3. Add books" << endl;
cout << "4. Delete books" << endl;
cout << "0. Exit" << endl;
cout << "What would you like to do?" << endl;
}
void list(BOOK_TYPE book[], int total_book)
{
system("cls");
for (int i = 0; i < total_book; i++)
{
cout << left << setw(15) << "ISBN" << setw(20) << "Author" << setw(35) << "Title"
<< setw(25) << "Publisher" << setw(7) << "Year" << setw(15) << "Genre"
<< setw(4) << "Qty" << setw(6) << "Price" << endl;
cout << "________________________________________________________________________________________________________________________________\n" << endl;
cout << left << setw(15) << book[i].isbn
<< setw(20) << book[i].author
<< setw(35) << book[i].title
<< setw(25) << book[i].publisher
<< setw(7) << book[i].year
<< setw(15) << book[i].genre
<< setw(4) << book[i].quantity
<< setw(6) << book[i].price << endl << endl
<< "(Located at shelf " << book[i].location.shelf << " level " << book[i].location.level << ")" << endl << endl;
cout << "________________________________________________________________________________________________________________________________" << endl;
}
system("pause");
}
void search(BOOK_TYPE book[], int total_book)
{
char keyword[55];
char* substring;
char tempKeyword[20];
system("cls");
// Prompt and get keyword to search student
cout << "Enter ISBN, book title or author name to search: ";
while (getchar() != '\n');
cin.getline(keyword, 55);
for (int i = 0; i < (int)strlen(keyword); i++)
{
keyword[i] = toupper(keyword[i]); //capitalize all of the character
}
for (int i = 0; i < total_book; i++)
{
substring = strstr(book[i].isbn, keyword);
if (substring)
{
cout << left << setw(15) << "ISBN" << setw(20) << "Author" << setw(35) << "Title"
<< setw(25) << "Publisher" << setw(7) << "Year" << setw(15) << "Genre"
<< setw(4) << "Qty" << setw(6) << "Price" << endl;
cout << "________________________________________________________________________________________________________________________________\n" << endl;
cout << left << setw(15) << book[i].isbn
<< setw(20) << book[i].author
<< setw(35) << book[i].title
<< setw(25) << book[i].publisher
<< setw(7) << book[i].year
<< setw(15) << book[i].genre
<< setw(4) << book[i].quantity
<< setw(6) << book[i].price << endl << endl
<< "(Located at shelf " << book[i].location.shelf << " level " << book[i].location.level << ")" << endl << endl;
cout << "________________________________________________________________________________________________________________________________" << endl;
}
else if (strstr(book[i].author, keyword) != 0)
{
cout << left << setw(15) << "ISBN" << setw(20) << "Author" << setw(35) << "Title"
<< setw(25) << "Publisher" << setw(7) << "Year" << setw(15) << "Genre"
<< setw(4) << "Qty" << setw(6) << "Price" << endl;
cout << "________________________________________________________________________________________________________________________________\n" << endl;
cout << left << setw(15) << book[i].isbn
<< setw(20) << book[i].author
<< setw(35) << book[i].title
<< setw(25) << book[i].publisher
<< setw(7) << book[i].year
<< setw(15) << book[i].genre
<< setw(4) << book[i].quantity
<< setw(6) << book[i].price << endl << endl
<< "(Located at shelf " << book[i].location.shelf << " level " << book[i].location.level << ")" << endl << endl;
cout << "________________________________________________________________________________________________________________________________" << endl;
}
}
system("pause");
}
Here is my book list I'm having in text file:
9781785785719,Yasha Levine,Surveillance Valley,Icon Books,2019,57.95,3,1,1,Political Science
9780241976630,John Maeda,How to Speak Machine,Portfolio UK,2019,89.95,2,1,1,Non-Fiction
9781119055808,Andre De Vries,R For Dummies,John Wiley,2015,107.77,4,1,2,Design
9780062018205,Dan Ariely,Predictably Irrational,Harper Collins,2010,39.90,2,1,1,Legal opinion
9780008327613,John Waish,The Globalist,Harper Collins,2019,109.90,2,1,1,Non-Fiction
9780525538349,John Doerr,Measure What Matters,Penguin LCC,2018,86.95,2,1,2,Management
9780807092156,Viktor Frankl,Man's Search for Meaning,Random House,2019,49.90,3,1,3,Biography
9780809875214,John Wick,The Assasinate of a Gang,Tree Production,2014,39.00,4,2,2,Fiction
9788373191723,J.R.R Tolkien,The Lord of the Rings,Allen & Unwin,1954,120.45,6,3,1,Fantasy Adventure
9783791535661,Lewis Carroll,Alice's Adventure in Wonderland,Macmillan,1865,100.25,5,3,2,Fantasy Fiction
9781517322977,Mikhail Bulgakov,The Master and Margarita,Penguin Books,1967,125.00,7,3,3,Romance Novel
9780676516197,Vladmir Nabokov,Lolita,Olympia Press,1955,98.25,3,3,1,Tragicomedy
9781095627242,Anna Sewell,Black Beauty,The Jarrold Group,1877,60.25,2,3,2,Fiction Novel
9788497592581,Umberto Eco,The Name of the Rose,Bompiani,1980,45.65,7,1,3,Historical Fiction
9780545790352,J.K.Rowling,Harry Potter and the Sorcerer's Stone,Arthur A. Levine,2015,44.87,1,3,1
I manage to only output until John Wick (8th line from text file) when user prompt "1" at the menu to show book list.

How to move back and forth in array list C++?

So I want to search my array for my data and move back and forth, so this is what i came up with, however this isn't working, can there be a better way to do this ? I tried to google some tips however I wasn't finding a suitable way to do this...
Can binary search be used to do this same thing ?
struct student
{
int stid = NULL;
char stname[15] = "NULL";
int grades = NULL;
string date = NULL;
};
int main()
{
int choose = 0;
int stid = 0;
int array = 1;
struct student s[1] = { 001, "Sara", "123456", "Canada", "02/01/2019" };
while (choose != 4)
{
cout << "1. Add\n";
cout << "2. View\n";
cout << "3. Search\n";
cout << "4. Quit\n";
cin >> choose;
if (choose == 3)
{
cout << "How would you like to find the Student Details?" << endl;
cout << "1 - By student id " << endl;
int choice = 0;
cin >> choice;
if (choice == 1)
{
cout << "Student ID: ";
cin >> stid;
for (int i = 0; i < array; i++)
{
if (s[i].stid == stid)
{
cout << "ID: " << s[i].stid << "\n";
cout << "Name: " << s[i].stname << "\n";
cout << "Grades: " << s[i].grades << "\n";
cout << "Date joined school: " << s[i].date<< "\n";
while (true)
{
cout << "Which record do you wish to see?" << endl;
cout << " 1 : Forth " << endl;
cout << " 2 : Back " << endl;
int choice = 0;
cin >> choice;
if (choice == 1)
{
stid = stid + 1;
for (int i = 0; i == stid; i++)
{
if (s[i].stid == stid)
{
cout << "ID: " << s[i].stid << "\n";
cout << "Name: " << s[i].stname << "\n";
cout << "Grades: " << s[i].grades << "\n";
cout << "Date joined school: " << s[i].date<< "\n";
}
}
}
else if (choice == 2)
{
stid = stid - 1;
for (int i = 0; i == stid; i++)
{
if (s[i].stid == stid)
{
cout << "ID: " << s[i].stid << "\n";
cout << "Name: " << s[i].stname << "\n";
cout << "Grades: " << s[i].grades << "\n";
cout << "Date joined school: " << s[i].date<< "\n";
}
}
}
Thank you for helping.

C++: Append string to output of first and last array index in loop

I tried to word the title as best as I could. Here I have a function that indexes through two parallel arrays and then outputs them with some formatting.
void outputTable(string salsa_jars[], int jars_sold[], int index[])
{
int totalSold = 0;
cout << setw(8) << "\nSalsa type sells: " << endl
<< "-------------------------------" << endl;
for(int i = 0; i <= (SALSA_TYPES-1); i++)
{
totalSold += jars_sold[index[i]];
cout << setw(15) << left << salsa_jars[index[i]]
<< setw(15) << right << jars_sold[index[i]] << endl;
}
cout << "-------------------------------" << endl
<< "Total sales: " << setw(17) << totalSold << endl;
}
What I'm trying to achieve is to add a string to the first and last outputs of the array. Below is my attempt.
void outputTable(string salsa_jars[], int jars_sold[], int index[])
{
int totalSold = 0;
cout << setw(8) << "\nSalsa type sells: " << endl
<< "-------------------------------" << endl;
for(int i=0;i<=(SALSA_TYPES-1);i++)
{
if(i == 0){
cout << setw(7) << left << salsa_jars[index[i]]
<< "(Highest)" << setw(14) << right
<< jars_sold[index[i]] << endl;
}
else if (i == (SALSA_TYPES-1)){
cout << setw(7) << left << salsa_jars[index[i]]
<< "(Lowest)" << setw(15) << right
<< jars_sold[index[i]] << endl;
}
else{
totalSold += jars_sold[index[i]];
cout << setw(15) << left << salsa_jars[index[i]]
<< setw(15) << right << jars_sold[index[i]] << endl;
}
}
cout << "-------------------------------" << endl
<< "Total sales: " << setw(17) << totalSold << endl;
}
But the code seems redundant, and I couldn't think of any other way to do it. If anyone has any pointers, I would appreciate it. Thanks.
Just prepare appropriate title for entry, and use common logic for displaying it:
for(int i=0;i<=(SALSA_TYPES-1);i++)
{
string title = toString(salsa_jars[index[i]]);
if(i == 0){
title += " (Highest)";
}
else if (i == (SALSA_TYPES-1)){
title += " (Lowest)";
}
totalSold += jars_sold[index[i]];
cout << setw(15) << left << title
<< setw(15) << right << jars_sold[index[i]] << endl;
}
}