copy precedent value 2d dynamic array - c++

Hi I want to create a 2d growing dynamic array with use of char. The problem is that my function put all word in the same row. The dynamic allocation is not good but I don't know how to correct this.
void display(char** data, int length)
{
for (int i = 0; i < length; i++)
for (int j = 0; j < data[i][j] != '\0'; j++)
cout << data[i][j];
cout << endl;
}
void add(char** &data, int length, char* word)
{
if (length == 1)
{
data = new char* [length];
}
data[length-1] = new char[strlen(word)+1];
strcpy_s(*(data + length -1), strlen(word) + 1, word);
data[length - 1][strlen(word) + 1] = '\0';
}
int main()
{
char** data = NULL;
int choice = 0, length = 0; char name[80];
cout << "Enter your choice" << endl;
while (cin >> choice && choice != 3)
{
switch (choice)
{
case 0:
cout << "Enter name to add: " << endl;
cin.ignore(); cin.getline(name, 80);
length++;
add(data, length, name);
break;
}
cout << endl << "Enter your next choice: " << endl;
}
This is what is get
Enter your choice
0
Enter name to add:
jhon
jhon
Enter your next choice:
0
Enter name to add:
marc
jhonmarc

I'm pretty sure that instead of
if (length = 1)
you meant to write
if (length == 1)
In C++ = means assignment and == means equality.
Seems your code has other bugs though. You never grow the size of data. Do it the easy way and use std::vector<std::string>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> data;
int choice = 0, length = 0; std::string name;
cout << "Enter your choice" << endl;
while (cin >> choice && choice != 3)
{
switch (choice)
{
case 0:
cout << "Enter name to add: " << endl;
cin.ignore(); getline(cin, name); // read name
data.push_back(name); // add name to data
break;
}
cout << endl << "Enter your next choice: " << endl;
}
Problem solved.

Related

how to find a specific target in the array c++

The search function should get a value from the user to search for it, if the value is found, then it should print it out, and if not found it should print not found.
However, in my code every time I write the number that is in the array is gives me the false option although it is in the array stored.
`
#include <iostream>
using namespace std;
const int size = 100;
int partsmenu(int menu_option);
void readparts(char part_number[][10], double price[], char classification[], int& number_of_parts);
int search(char part_number[][10], char search_target[], int number_of_parts, double price[], char classification []);
void display_parts(char part_number[][10], double price[], char classification[], int& number_of_parts);
int main()
{
const int size = 100;
int menu_option=0, option, displaysearch;
char part_number[size][10];
double price[size];
char classification[size];
int number_of_parts = 0;
char search_target[size];
//using switch statment to make it look like a menu option
do {
switch (option = partsmenu(menu_option))
{
case 1:
readparts(part_number, price, classification, number_of_parts);
break;
case 2:
display_parts(part_number, price, classification, number_of_parts);
break;
case 3:
displaysearch = search(part_number, search_target, number_of_parts, price, classification);
break;
case 4:
break;
default:
cout << "Not valid..." << endl;
break;
}
cout << endl;
} while (option != 4);
return 0;
}
int partsmenu(int menu_option)
{
cout <<"1) Enter new part number\n2) View all part numbers\n3) Search for part\n4) Exit\n\nEnter an option: ";
cin >> menu_option;
return menu_option;
}
void readparts(char part_number[][10], double price[], char classification[], int& number_of_parts)
{
// using for loop to store part number, price, and classification in the array
int number;
cout << "Enter number of parts to add:";
cin >> number;
cout << endl;
int i;
for (i = number_of_parts; i < (number_of_parts+number); i++)
{
cout << "Enter part number: ";
cin >> part_number[i];
cout << "Enter price: ";
cin >> price[i];
cout << "Enter classificarion: ";
cin >> classification[i];
//using if statment to check for the classificarion
if (classification[i] == 'A' || classification[i] == 'B' || classification[i] == 'C')
cout << "";
else
{
cout << "Invalid case..." << endl;
cout << "Enter Valid class [A, B, C]: ";
cin >> classification[i];
cout << endl;
}
cout << endl;
}
number_of_parts = i;
}
int search(char part_number[][10], char search_target[], int number_of_parts, double price[], char classification[])
{
//searching for specific data
bool found = false;
int value;
cout << "Enter part number: ";
for (int j = 0; j < number_of_parts; j++)
{
cin >> search_target;
for (int i = 0; i < number_of_parts && found == false; i++)
{
if (part_number[i] == search_target)
found = true;
value = i;
}
}
if (found == true)
{
for (int i = 0; i < number_of_parts; i++)
{
cout << "Part ID\t\tPrice\t\tClass" << endl;
cout << " --------------------------------------------" << endl;
cout << part_number[value] << "\t\t" <<price[value]<< "\t\t" <<classification[value]<< endl;
}
}
else
{
cout << "No parts found..." << endl;
value = -1;
}
return value;
}
void display_parts(char part_number[][10], double price[], char classification[], int& number_of_parts)
{
// displaying the data
cout << "Part ID\t\tPrice\t\tClass" << endl;
cout << "--------------------------------------------" << endl;
for (int i = 0; i < number_of_parts; i++)
{
cout << part_number[i] << "\t\t" << price[i] << "\t\t" << classification[i] << endl;
}
cout << endl;
}
`
I am trying to find what is wrong with code but could not find any fault with it. Everything else works fine.
You compare C strings with strcmp not ==. Like this
if (strcmp(part_number[i], search_target) == 0)
If you use == then all you are comparing is the addresses of the strings, the addresses of two strings can be different even if the string contents are the same.
strcmp compares the actual characters in the strings, not the addresses. It returns 0 if the two strings are the same.

Call array storing string type from one while to another

How to fix the code? I can't use vectors. I need to be able to call the names for the courses from the first while to the second one and display them.
cout << "Please enter the number of classes"<< endl;//Number of classes for the while
cin >> nclass;
while (count <= nclass ) // while
{
//Information for the class
{
cout << "Please enter the course name for the class # "<< count << endl;
getline (cin, name);
string name;
string coursename[nclass];
for (int i = 0; i < nclass; i++) {
coursename[i] = name;
}
}
char choose;
cin >> choose;
while ( choose == 'B' || choose == 'b') {//Name the courses
for (int x = 0; x < nclass; x++){
cout << "Here is a list of all the courses: \n" << coursename[i] << endl;
}
return 0 ;
}
you are declaring coursename as local inside loop and then using it outside so you get a compile time error (coursename is undeclared identifier).
one question: what is the role of inner for-loop????!!!
you use a for loop inside while loop through which you are assigning all the elements the same value as the string name has!!!
so every time count increments the inner for loop assigns the new value of name after being assigned, to the all elements of coursename.
count is undefined! so declare it and initialize it to 1 or 0 and take this in mind.
you wrote to the outbounds of coursname: count <= nclss to correct it:
while(count < nclass)...
another important thing: clear the input buffer to make cin ready for the next input. with cin.ignore or sin.sync
cout << "Please enter the number of classes"<< endl;//Number of classes for the while
cin >> nclass;
string coursename[nclass];
int count = 0;
while (count < nclass ) // while
{
//Information for the class
string name;
cout << "Please enter the course name for the class # "<< count << endl;
cin.ignore(1, '\n');
getline (cin, name);
coursename[count] = name;
cin.ignore(1, '\n');
count++;
}
char choose;
cin >> choose;
while ( choose == 'B' || choose == 'b') {//Name the courses
for (int x = 0; x < nclass; x++){
cout << "Here is a list of all the courses: \n" << coursename[x] << endl;
}
This code works!
#include <iostream>
#include <string>
using namespace std;
int main()
{
int nclass = 0, count = 1, countn = 1;
string name[100];
cout << "Please enter the number of classes" << endl;
cin >> nclass;
while (count <= nclass) {
cout << "Please enter the course name for the class # " << count << endl;
cin >> name[count];
count++;
}
cout << "Here is a list of all the courses: " << endl;
while (countn <= nclass) {
cout << name[countn] << endl;
countn++;
}
return 0;
}
Note that gave the array "name" the size of 100. Nobody is going to have 100 classes! There is no need for the for loops. It is a good practice to initialize the count and the new count which is designated by countn. Why is my answer voted down when it works?

problems with conditional statement based off sizeof c++

I am new to c++ and and am working on a program that has is a simple dvd rental program. I am having issues with case 3 & 4 specifically. Maybe I am misunderstanding the purpose behind sizeof. What I am trying to have it do is tell if the char array is empty and if it is allow the user to check it out by putting their name in and if it is not available give them a response saying that it is not available. case 4 should do the opposite and allow them to check it in. Any suggestions would be greatly appreciated.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <limits>
using namespace std;
const int arrSize = 5;
struct dvdStruct //distance struct
{
int id;
char title[51] = { 0 };
char rating[5] = { 0 };
double price;
char borrower[51] = { 0 };
} dvd;
dvdStruct dvds[arrSize] = {};
int userSelection; //intput variable for main menu selection
int borrowId (0);
int borrowIdReturn(0);
//void initalize();
int main() {
int size(0);
dvds[0].id = 1;
dvds[1].id = 2;
dvds[2].id = 3;
dvds[3].id = 4;
dvds[4].id = 5;
strcpy(dvds[0].title, "Fast 1");
strcpy(dvds[1].title, "Fast 2");
strcpy(dvds[2].title, "Fast 3");
strcpy(dvds[3].title, "Fast 4");
strcpy(dvds[4].title, "Fast 5");
strcpy(dvds[0].rating, "PG - 13");
strcpy(dvds[1].rating, "PG - 13");
strcpy(dvds[2].rating, "PG - 13");
strcpy(dvds[3].rating, "PG - 13");
strcpy(dvds[4].rating, "PG - 13");
dvds[0].price = '19.1';
dvds[1].price = '19.2';
dvds[2].price = '19.3';
dvds[3].price = '19.4';
dvds[4].price = '19.5';
strcpy(dvds[0].borrower, "");
cout << strlen(dvds[0].borrower) << endl;
strcpy(dvds[1].borrower, "\0");
strcpy(dvds[2].borrower, "\0");
strcpy(dvds[3].borrower, "\0");
strcpy(dvds[4].borrower, "\0");
do {
cout << "1.Display All DVD’s" << endl << "2.Display DVD Detail" << endl << "3.Check Out a DVD" << endl << "4.Check In a DVD" << endl << "5.Exit" << endl;
cin >> userSelection; //Input from the user.
switch (userSelection)
{
case 1:
for (int i = 0; i < arrSize; i++)
{
std::cout << dvds[i].title << "' " << dvds[i].rating << " " << dvds[i].borrower << endl;
}
system("pause");
system("CLS");
break;
case 2:
int dvdNum;
cout << "Enter a DVD number:";
cin >> dvdNum;
std::cout << dvds[dvdNum - 1].title << "' " << dvds[dvdNum - 1].rating << endl;
system("pause");
system("CLS");
break;
case 3:
cout << "Enter and id:";
cin >> borrowId;
if (strlen(dvds[borrowId-1].borrower) == 0)
{
cout << "Enter your name: ";
cin >> dvds[borrowId-1].borrower;
}
else
{
cout << "This dvd is not available" << endl;
}
system("pause");
system("CLS");
break;
case 4:
cout << "Enter and id:";
cin >> borrowIdReturn;
if (strlen(dvds[borrowIdReturn - 1].borrower) == 0)
{
cout << "This dvd is available" << endl;
}
else
{
cout << "Your DVD has been returned " << endl;
strcpy(dvds[borrowIdReturn - 1].borrower, "\0");
}
system("pause");
system("CLS");
break;
case 5:
return 0;
break;
}
} while (userSelection == 1 || userSelection == 2 || userSelection == 3 || userSelection == 4);
}
sizeof() gives you the size of an object. The size of the object is always the same, no matter what's in the object. In fact, sizeof() is calculated at compile time, and its value could not be affected, in any way, by whatever happens at runtime.
C++ code should use std::string, instead of char arrays, in most cases. std::string's empty() method indicates whether the string is empty.
If you still insist on working with C-style char arrays, and C-style '\0' terminated strings, use the C strlen() function to check if the character array contains nothing but a leading '\0', indicating an empty string.

How do I permenantly delete a row of arrays and shift a row of arrays upwards?

I've been assigned by school to create an application that contains a book list with 20 different books in it and build a menu with following options:
(a) List – Display the list in tabular format. Each display should contain an appropriate heading and column captions;
(b) Search – Search for a book record in the list using the ISBN and print the full record for the book;
(c) Delete – Delete an existing book record from the list;
(d) Exit – Stop the program.
Here is the sample of my program:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
typedef struct
{
char code[50];
char author[50];
char name[50];
char edition[50];
char publish[50];
char price[50];
} BOOK_LIST;
void list (BOOK_LIST book[], int rows);
void showBook (BOOK_LIST book[], int rows);
void updateRecord (BOOK_LIST book[], int rows);
void advancedSearch (BOOK_LIST book[], int rows);
int deleteBook (BOOK_LIST book[], int rows);
int searchBook(BOOK_LIST book[], int rows);
int main()
{
ifstream inFile("list.txt");
if(!inFile)
cout << "Error opening input file\n";
else
{
BOOK_LIST books[50];
int index = -1, choice;
inFile.getline(books[++index].code, 50);
while(inFile)
{
if(inFile.peek() == '\n')
inFile.ignore(256, '\n');
inFile.getline(books[index].author, 50);
inFile.getline(books[index].name, 50);
inFile.getline(books[index].edition, 50);
inFile.getline(books[index].publish, 50);
inFile >> books[index].price;
// read next number
inFile >> books[++index].code;
}
inFile.close();
// menu starts
do
{
cout << "Do you want to:\n";
cout << "1. List all books\n";
cout << "2. Get details about a book\n";
cout << "3. Delete a book from the list\n";
cout << "4. Exit\n";
cout << "5. Advanced Search\n";
cout << "Enter choice: ";
cin >> choice;
switch (choice)
{
case 1 : list(books, index);
break;
case 2 : showBook(books, index);
break;
case 3 : updateRecord(books, index);
break;
case 5 : advancedSearch(books, index);
case 4 : break;
default: cout << "Invalid choice\n";
}
} while (choice != 4);
ofstream outFile("list.txt");
if(!outFile)
cout << "Error opening output file, records are not updated.\n";
else
{
for (int i = 0; i < index; i++)
{
outFile << books[i].code << endl;
outFile << books[i].author << endl;
outFile << books[i].name << endl;
outFile << books[i].edition << endl;
outFile << books[i].publish << endl;
outFile << books[i].price << endl;
}
outFile.close();
}
}
return 0;
}
void list(BOOK_LIST book[], int rows)
{
cout << fixed << setprecision(2);
cout << "ISBN\t Author BookName Edition\tPublisher\t Price\n";
for (int i = 0; i < rows; i++)
cout << book[i].code << "\t" << book[i].author << "\t"
<< book[i].name << "\t" << book[i].edition << "\t"
<< book[i].publish << "\t"
<< " " << book[i].price << endl;
return;
}
int searchBook(BOOK_LIST book[], int rows)
{
int i = 0;
bool found = false;
char code[50];
cout << "Enter an ISBN code of a book to search: ";
fflush(stdin);
cin.getline(code, 50);
while (i < rows && !found)
{
if (strcmp(code, book[i].code) == 0)
found = true;
else
i++;
}
if (found)
return i;
else
return -1;
}
void showBook(BOOK_LIST book[], int rows)
{
int pos = searchBook(book, rows);
if (pos != -1)
{
cout << "Author is " << book[pos].author << endl;
cout << "Book name is "<< book[pos].name << endl;
cout << book[pos].edition << " Edition" << endl;
cout << "The publisher of this book is " << book[pos].publish << endl;
cout << "Current price is " << book[pos].price << endl;
}
else
cout << "Product not found\n";
return;
}
void updateRecord(BOOK_LIST book[], int rows)
{
int pos = deleteBook(book, rows);
char code [50];
int i,j = 0;
for(i = 0; i < rows ; i++)
{
if(strcmp(code, book[i].code))
{
strcpy(book[j].code , book[i].code);
strcpy(book[j].author, book[i].author);
strcpy(book[j].name, book[i].name);
strcpy(book[j].edition, book[i].edition);
strcpy(book[j].publish, book[i].publish);
strcpy(book[j].price, book[i].price);
j++;
}//if
else
{
i++;
strcpy(book[j].code, book[i].code);
strcpy(book[j].author, book[i].author);
strcpy(book[j].name, book[i].name);
strcpy(book[j].edition, book[i].edition);
strcpy(book[j].publish, book[i].publish);
strcpy(book[j].price, book[i].price);
j++;
}//else
}//for
return;
}
int deleteBook (BOOK_LIST book[], int rows)
{
int i = 0;
bool found = false;
char code[50];
cout << "Enter an ISBN code of a book to delete: ";
fflush(stdin);
cin.getline(code, 50);
while (i < rows && !found)
{
if (strcmp(code, book[i].code) == 0)
found = true;
else
i++;
}
if (found)
return i;
else
return -1;
}
void advancedSearch (BOOK_LIST book[], int rows)
{
char advanced[50];
cout << "Please enter either the author's name or the book name to search: ";
fflush(stdin);
cin.getline(advanced, 50);
for(int i = 0; i < rows; i++)
{
if(strstr(book[i].author, advanced) || strstr(book[i].name, advanced))
{
cout << "ISBN is " << book[i].code << endl;
cout << "Author is " << book[i].author << endl;
cout << "Book name is " << book[i].name << endl;
cout << book[i].edition << " Edition" << endl;
cout << "Publisher is " << book[i].publish << endl;
cout << "Current price is " << book[i].price << endl;
}
}
return ;
}
The problem starts here:
When I want to permanently delete a whole row of book record. But the book record is still there after deleting.
First, this is my menu, then I press 1 to check the list for the IBSN. Then, I press 3 to proceed to the deleting part. At that time, I choose TheHost to delete. After the deleting, to ensure that I have deleted the chosen book, so I press 1 to check the list again, but unfortunately the book is still there:
If I am able to delete a book record, and how do I delete a record permanently? And after deleting a record, how do I move the remaining records upwards, so that it won't leave any empty row there?
The function for the deleting:
void updateRecord(BOOK_LIST book[], int rows)
{
int pos = deleteBook(book, rows);
char code [50];
int i,j = 0;
for(i = 0; i < rows ; i++)
{
if(strcmp(code, book[i].code))
{
strcpy(book[j].code , book[i].code);
strcpy(book[j].author, book[i].author);
strcpy(book[j].name, book[i].name);
strcpy(book[j].edition, book[i].edition);
strcpy(book[j].publish, book[i].publish);
strcpy(book[j].price, book[i].price);
j++;
}//if
else
{
i++;
strcpy(book[j].code, book[i].code);
strcpy(book[j].author, book[i].author);
strcpy(book[j].name, book[i].name);
strcpy(book[j].edition, book[i].edition);
strcpy(book[j].publish, book[i].publish);
strcpy(book[j].price, book[i].price);
j++;
}//else
}//for
return;
}
The Text file that I used in this program a.k.a the BOOK_LIST
I see (at least) two problems with your code around deleting a book.
in update_record you're using a char code[50] which is being used to compare with strcmp later on but is not initialized.
when you delete a book you should update your index which becomes rows in the update_record method. However index is passed to rows by value which means that even if you try running --rows; in update_record it won't decrement index. You'll need to pass it by reference for it to update index.
On a side note, I agree with comments regarding fixing your code to use vectors/maps & strings instead of simple arrays and char*.
But since you mentioned it was a school task I would guess you haven't reached that sort of material yet.
Good Luck.
The assignment most probably expects you to use std::list template rather than the classical C array. Insertion and deletion is natural for lists.
An alternative would be to use std:map using the ISBN as a key. ISBN is supposed to be globally unique.
Just to expand on my comment, here is one way to remove an element from an array.
Suppose we have an array of char called X, containing {'a', 'b', 'c', 'd', 'e', 'f'}, and we want to get rid of 'c'.
If we want to maintain the order of the remaining elements, then what we're aiming for is {'a', 'b', 'd', 'e', 'f'}. So we copy the 'd' into the 'c' place, the 'e' into the old 'd' place, and so on:
a b c d e f
a b d d e f
a b d e e f
a b d e f f
We can do this with code like
for(int k=2; k<5; ++k)
X[k] = X[k+1];
And what happens to that extra 'f' at the end? We could write some placeholder into that unwanted space, and then watch out for that placeholder for the rest of the run. Or, we could just stop using that space, and say that from now on we're considering an array of length 5. That extra 'f' will still be there, but for now we don't care about what exists past the end of our array.
(If we don't care about the order of the remaining elements, then we can make this a lot simpler.)
Remember, it's always easier to develop new functionality in isolation.
Once you have this working, you can apply it in your code and get a passing grade, but if you really want to learn something useful you should write a Book class.

C++ function putting garbage into array

Having trouble with this function, all works fine until the add, it inserts memory address into the array instead of the new ints:
bool reserveSeat(string name[], int reservation[][2], int &noPassengers)
{
bool reserve = false;
string searchName;
int row, seat, validRow, validSeat;
cout << "Please enter reservation name: ";
getline(cin, searchName);
cout << "Please enter a Row #: ";
cin >> row;
cout << "Please enter a Seat #: ";
cin >> seat;
cin.ignore(80, '\n');
validRow = validateSeat(row, '10');
validSeat = validateSeat(seat, '3');
for (int ctr = 0; ctr < noPassengers; ctr++) {
if (seat == reservation[ctr][1] && row == reservation[ctr][0]) {
break;
} else {
reserve = true;
noPassengers++;
name[noPassengers] = searchName;
reservation[noPassengers][0] = row;
reservation[noPassengers][1] = seat;
}
}
return reserve;
}
The function is called from main() via:
if ( reserveSeat(name, reservation, noPassengers) )
cout << "reservation made ";
else
cout << "reservation not made ";
cout << endl;
all arrays are size of 12, there are only 4 entries
the validate seat function as requested:
int validateSeat(int& col, int max)
{
while(col>max || col < 0)
{
cout << "Sorry, that is within an invalid range." << endl << "again: ";
cin >> col;
}
return col;
}
noPassengers is determined from the load found here:
int loadArrays(ifstream & fin,string name[],int reservation[][2])
{
int row=0;
for (; row < SIZE ; row++)
{
getline(fin,name[row]);
if (fin.eof())
break;
for (int col=0;col < 2; col++)
{
fin >> reservation[row][col];
}
fin.ignore(80,'\n');
}
return row;
}
validateSeat(row, '10'); is a mistake. '10' would be a multi-byte character constant, which I'm sure is not what you want.
Update: This should be validateSeat(row, 10), and the line after validateSeat(seat, 3).
Also it's possible that reservation[noPassengers] or name[noPassengers] is beyond the bounds of the amount of memory you have allocated , we can't tell based on the code you have shown.
Please update your post to show where you allocate memory for reservation and name before calling this function. (show the code, don't describe the code).