How to work with 1 array with few methods - c++

I have Multidimensional array in my struct i want to work with this array using few methods, i think i should use double pointer but i have no idea how to do it
struct generator {
char r[26][max];
void set();
void display();
};
void generator::set() {
char *tab = new char[max];
int k = 0;
cin >> tab;
while (tab[k] != '\0') {
r[0][k] = tab[k];
k++;
}
void generator::display(){
cout << r[0][1]; // should display first letter of string
}

in
cout << r[0][1]; // should display first letter of string
the comment is wrong, that displays the second letter, first letter is at index 0
Adding enough definitions and missing '}' to compile and execute :
#include <iostream>
using namespace std;
#define max 10
struct generator {
char r[26][max];
void set();
void display();
};
void generator::set() {
char *tab = new char[max];
int k = 0;
cin >> tab;
while (tab[k] != '\0') {
r[0][k] = tab[k];
k++;
}
}
void generator::display(){
cout << r[0][1]; // should display first letter of string
}
int main()
{
generator g;
g.set();
g.display();
cout << endl;
}
Compilation and execution :
/tmp % g++ -pedantic -Wall -Wextra g.cc
vxl15036 /tmp % ./a.out
aze
z

Related

C++ Creating Lottery Guessing Program

Okay so the project is to create a lottery number composed of 10 random positive integers and the user is suppose to guess it until the user guesses the correct number. All of my code looks good but when I run the program and enter in a number it gives me this MSVS Runtime Library error? I dont even know what it means as I am fairly new to programming. Help would be very appreciated!
Main.cpp
#include <iostream>
#include <cmath>
#include <ctime>
#include "Lottery.h"
using namespace std;
int main() {
const int size = 9; //declare variables
int win[size];
int g;
srand(time(NULL));
assign(win, size);
draw(win, size);
g = entry();
if (check(win,size,g) == true) {
cout << "Congradulations! You have won the lottery!" << endl;
}
else {
cout << "Try again!" << endl;
}
printOut(g);
}
Lottery.cpp
#include <iostream>
#include <cmath>
#include "Lottery.h"
using namespace std;
int entry() {
int guess;
cout << "Enter a number from 0 to 99." << endl;
cin >> guess;
return guess;
}
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1;
}
}
bool check(int w[], int s, int g) {
for (int i = 0; i < s; i++) {
if (g == w[i]) {
return true;
}
}
return false;
}
void draw(int w[], int s) {
for (int i = 0; i < s; i++) {
int tmp = rand() % 100;
if (check(w, s, tmp)) {
i--;
}
else
w[i] = tmp;
}
}
void printOut(int g) {
cout << "Numbers you have chosen:" << " " << g << endl;
}
Lottery.h
#ifndef LOTTERY_INCLUDED
#define LOTTERY_INCLUDED
void assign(int[], int);
bool check(int[], int, int);
void draw(int[], int);
int entry();
void printOut(int);
#endif //LOTTERY
Debugging tutorials are available elsewhere. But if something bad happens, don't panic and look for instructions.
First, your runtime error:
This has a link "Break and open exception settings" link or a "Break" button. Break which will take you to the end of main if you click it.
The details say we did something bad near win.
Look at this:
void assign(int w[], int s) {
for (int i = 0; i < s; i++) {
w[s] = -1; //<------Oh oops!
}
}
We know the length of the array is s i.e. 9, and are using w[s] where we clearly meant w[i].
The extra details in the error are telling you a possible place to look.

My Binary Search Algorithm Template Function is Always Returning False

So I'm supposed to use the Binary Search template function to read elements from a file to an array and then allow the user to search for an element if it's in the array. The problem is that whenever I search for a number, it gives me a "not found" even if the element does exist in the file. I know it's better to leave the template functions in the header file, but since I had no idea how to sort the file so the binary search would work I put the functions in the main program to make it less confusing. think the problem is in the main() or the sort function, but to my limited knowledge I can't figure out where exactly and how to fix it.
This is my code:
#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
using namespace std;
template<class elemType>
class orderedArrayListType
{
public:
static const int length = 20;//Const length of array you can change it accordingly
int list[length];
int binarySearch(elemType const&)const;
};
template<class elemType>
int orderedArrayListType<elemType>::binarySearch(const elemType& item) const
{
int first = 0;
int last = length - 1;
int mid;
bool found = false;
while (first <= last && !found)
{
mid = (first + last) / 2;
if (list[mid] == item)
found = true;
else if (list[mid] > item)
last = mid - 1;
else
first = mid + 1;
}
if (found)
return mid;
else
return -1;
}
void main()
{
std::fstream numberFile("text.txt", std::ios_base::in);
orderedArrayListType<int> object;
int number=0, a;
int i = 0;
int numberToSearch;
while (numberFile >> a)
{
object.list[i] = number;//Initalizing the array
i++;
}
cout << "Enter Number you want to search" << endl;
cin >> numberToSearch;
int output = object.binarySearch(numberToSearch);//Make search
if (output>0)
{
cout << "Element found at Index: " << output << endl;
}
else
{
cout << "Element not Found" << endl;
}
}
And these are the contents of the text.txt file:
1 2 3 4 5 6 7 8 9 10
Thanks in advance!
Here you are setting all elements of the list to 0:
while (numberFile >> a)
{
object.list[i] = number;//Initalizing the array
i++;
}
Instead, you should fill in the numbers read from the file:
while (numberFile >> a)
{
object.list[i] = a;//Initalizing the array
i++;
}
Then, it would be better if you would use the template parameter for the list, because else the template will only work for int:
template<typename elemType>
class orderedArrayListType
{
public:
static const int length = 20;//Const length of array you can change it accordingly
elemType list[length];
int binarySearch(elemType const&)const;
};
template<typename elemType>
int orderedArrayListType<elemType>::binarySearch(const elemType& item) const
{
int first = 0;
int last = length - 1;
elemType mid;
....
Problem is not in the binary search function but with :
while (numberFile >> a)
{
object.list[i] = number;//Initalizing the array
i++;
}
number is always 0.
One advice , change :
mid = (first + last) / 2;
to
mid=first + (last-first)/2
It avoids overflow. It's always a good programming practice to look for these cases as well.
Thanks to those tips I was able to run the program correctly. Here is the edited main() program code to make it extra clear for anyone who might stumble upon any problems with such a program.
void main()
{
std::fstream numberFile("text.txt", std::ios_base::in);
orderedArrayListType<int> object;
int number=0, a;
int i = 0;
int numberToSearch;
while (numberFile >> a)
{
object.list[i] = a;//Initalizing the array
i++;
}
cout << "Enter Number you want to search" << endl;
cin >> numberToSearch;
int output = object.binarySearch(numberToSearch);//Make search
if (output>0)
{
cout << "Element found at Index: " << output << endl;
}
else
{
cout << "Element not Found" << endl;
}
}
Note that the change was only made to the part where the array is initialized as user (alain) advised:
while (numberFile >> a)
{
object.list[i] = a;//Initalizing the array
i++;
}

Getter and Segmentation Fault

I need a bit of help on my program:
#include <iostream>
#include<conio.h>
using namespace std;
class Position {
public :
int line;
int column;
Position(int,int);
Position();
};
Position::Position(int n, int m) : line{n},column{m}{}
class Board {
private :
int** tab;
int nbline;
int nbcolumn;
public :
Board(int, int);
void setValue(Position&, int);
int getValue(Position&);
int getNbline();
int getNbcolumn();
};
class Play {
private :
// Play m_instance;
void moves(Board, Position&); // quand le joueur joue
// void moves(Board, Position); // quand l'IA joue. Mettre une énum pour direction,
bool wincondition(Board);
Play& operator=(const Play&);
public :
// static Play& Instance();
};
Board::Board(int m, int n) : tab{new int*[m]}, nbline{m}, nbcolumn{n}{
int x(0);
for (int i = 0; i < m; ++i){
tab[i] = new int[n];
for(int j = 0; j < n; ++j) {
tab[i][j] = x; x++;}}
}
void Board::setValue(Position& p, int value) { tab[p.line][p.column] = value; }
int Board::getValue(Position& p) { return tab[p.line][p.column]; }
int Board::getNbline() { return nbline; }
int Board::getNbcolumn() { return nbcolumn; }
void Play::moves(Board tab, Position& blank) {
/* int c = getch() ;
Position tmp;
if(c==0 || c==224) {c = getch();
switch(c){
case 75 : //left
if(blank.column-1>=0) {
tmp.column = blank.column;
tmp.line = blank.line;
tab.setValue(blank,tab.getValue(tmp));
blank.column++;
tab.setValue(blank, 0);
}
break;
case 72 : // haut
if(blank.line+1<=0) {
tmp.column = blank.column+1;
tmp.line = blank.line;
tab.setValue(blank,tab.getValue(tmp));
blank.column++;
tab.setValue(blank, 0);
}
break;
case 77 ://droit
if(blank.column+1<=tab.getNbcolumn()) {
tmp.column = blank.column;
tmp.line = blank.line;
tab.setValue(blank,tab.getValue(tmp));
blank.column--;
tab.setValue(blank, 0);
}
break;
case 80 : //bas
if(blank.line+1<=tab.getNbline()) {
tmp.column = blank.column+1;
tmp.line = blank.line;
tab.setValue(blank,tab.getValue(tmp));
blank.column++;
tab.setValue(blank, 0);
}
break;
default : cout << "\n ERROR " << endl; break; // erreur
}
}*/
}
int main()
{
int lines, columns;
cout << "Enter number of lines" << endl;
cin >> lines;
cout << "Enter number of columns" << endl;
cin >> columns;
Board tab(lines,columns);
Position pos(lines,columns);
Position& p = pos;
for (int i = 0; i<lines;i++)
{
for(int j = 0; j<columns;j++)
{
cout << tab.getValue(p) << " ";
if (i == lines) { cout << endl;}
}
}
return 0;
}
When I call getValue at line 139, I get a segmentation fault. Get value is defined at line 57. When executing getValue, both p.line and p.column got the right values caught at the beginning of main function.
The program got no errors, only 2 warnings because I don't use Play::moves arguments (because currently between /* */, waiting for tests). I use Code::Blocks with -Wall -Wextra -pedantic -std=c++11.
I really see no reason for a segmentation fault. Did I miss something?
You are calling get with a position that is set to the size of your board. Since arrays are 0 index based the size of your array is actually one past the end of the array.
const int size = 100
int arr[size]; //0, 1, 2, ... 98, 99
arr[size]; // fail arr is 0-99 and size is 100

assistance in sorting an array of pointers pointing to a string array in c++

I have been attempting to find a way to sort an array of pointers (pointing to strings) and then display the non-sorted list and the sorted list but no mater what I try the 2nd printed list is always identical to the original non-sorted list. Any help you could offer would be greatly appreciated (and I'm sorry if my code is a mess I'm a new student)
this is my main(lab5.cpp)
#include <cstdlib>
#include <iostream>
#include "student.h"
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
student stu;
stu.list();
system("PAUSE");
return EXIT_SUCCESS;
}
This is my header(student.h)
#include <string>
class student
{
public:
student( );
void setnameage();
int getage(int);
std::string getname(int);
void sort();
void list();
private:
std::string name[50];
std::string nameL[50];
int age[50];
std::string * Pname ;
int * Page;
int amount;
};
This is my object (student.cpp)
#include <iostream>
#include <iomanip>
#include "student.h"
#include <string>
using namespace std;
//constructor
student::student()
{
int i = 0;
amount = 0;
Pname = name;
Page = age;
while (i != 50)
{
age[i] = 0;
name[i] = "A";
i = i +1 ;
}
std::cout << "Enter number of students(max 50) \n" << ">";
std::cin >> amount;
}
//sets the neame and the age
void student::setnameage()
{
int i = 0;
while (i != amount)
{
std::cout << "Enter name " << i+1 <<" (last, first):";
std::cin >> name[i] >> nameL[i];
std::cout << "enter age";
std::cin >> age[i];
i++;
}
}
//get age
int student::getage(int i)
{
return age[i];
}
//get name
std::string student::getname(int i)
{
return name[i];
}
//sorts the aray of pointers
void student::sort()
{
std::string tempL;
int tempN;
i = 0
for (int i = 1; i <= amount-1; i++)
{
for(int j=i+1; j <= amount; j++)
{
if(Pname[i].compare(Pname[j]) > 0)
{
tempN = Page[i];
Page[i] = Page[j];
Page[j] = tempN;
// tempL = Pname[i];
Pname[i].swap(Pname[j]);
//Pname[j] = tempL;
}
}
}
}
//displayes the final results
void student::list()
{
setnameage();
int i = 0;
std::cout << "original list\n-------------";
while(i != amount)
{
std::cout<< "\n" << getname(i) << ">" << getage(i);
i++;
}
sort();
i = 0;
std::cout << "\nAlphabetized list\n-------------";
while(i != amount)
{
std::cout<< "\n" << Pname[i] << ">" << Page[i];
i++;
}
}
First let me say your program has a lot of design problems, but to answer your actual question:
The trouble is you don't have an array of 50 pointers, you just have one pointer to the start of the array. In your sort function you have this line to swap the string pointers:
Pname[i].swap(Pname[j]);
But this doesn't swap the pointers, it swaps the original strings. So instead of ending up with the original array of strings, and a re-ordered array pointing to those strings, you just end up with an array of re-ordered strings.
You should change std::string* pName; to std::string* pName[50];. At the start of your program, initialise the array to point to the strings.
for (int i = 0; i < 50; i++) pName[i] = &name[i];
Then in your sort function you should use std::swap() to swap the pointers themselves:
std::swap(pName[i], pName[j]);
Finally, since pName[i] is now a pointer, whenever you actually want to access the string you have to dereference the pointer. For example,
if(Pname[i].compare(Pname[j]) > 0)
becomes
if(Pname[i]->compare(*Pname[j]) > 0)
The same problem exists with your method of sorting the ages.
A much better design for your program would be to use std::list<std::pair<std::string, int>> to store the names and ages. Then you can use the built in sorting functions to sort the list (and easily make a copy of it if you need to keep the original as well).

Unable to access members of a class; SegFault

I have a program where I am setting up a closed hash table. In each Element of the Hash table, there is a Student class which holds varies members (name, id, year, etc.). I am simply trying to print out what has been added to my array, but I keep getting a SegFault, and I don't know why. It is only in my print function, though. I have copied the line of code to my other functions or put them in different classes, and they work there, but not when I try to print from my print function. I am at the end of my rope, trying to figure out why I can access the memory location of each member, but not it's actual value.
Here is my program:
main.cpp:
using namespace std;
#include <cstdlib>
#include "hash.h"
int main()
{
string temp1;
string temp2;
string temp3;
string temp4;
string temp5;
string temp6;
Hash h;
do{
cout << "set> ";
cin >> temp1;
//Checking for quit command.
if(temp1.compare("quit") == 0)
{
return 0;
}
//checking for add command.
else if(temp1.compare("add") == 0)
{
cin >> temp2;
cin >> temp3;
cin >> temp4;
cin >> temp5;
cin >> temp6;
Student *s1 = new Student(temp2, temp3, temp4, temp5, temp6);
Element e1(s1);
h.add(e1);
}
//checking for remove command.
else if(temp1.compare("remove") == 0)
{
int r;
cin >> r;
h.remove(r);
}
//checking for print command.
else if(temp1.compare("print") == 0)
{
h.print();
}
//Anything else must be an error.
else
{
cout << endl;
cout << "Error! "<< endl;
}
}while(temp1.compare("quit") != 0);
}
hash.h:
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
// Student Class
class Student{
private:
string firstName;
string lastName;
string id;
string year;
string major;
public:
//Constructor
Student(string a, string b, string c, string d, string e);
friend class Element;
friend class Hash;
};
//Element class
class Element{
private:
Student *data;
public:
int getKey();
Student* getData();
void printStudent();
//Constructor
Element(Student *e)
{
data = e;
};
friend class Hash;
};
class Hash{
private:
Element **array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element *[10];
};
friend class Student;
};
hash.cpp:
#include "hash.h"
//The Constructor for Student
Student::Student(string a, string b, string c, string d, string e)
{
firstName = a;
lastName = b;
id = c;
year = d;
major = e;
}
//getKey function for Element Class
int Element::getKey()
{
int key = atoi(getData()->id.c_str());
return key;
}
Student* Element::getData()
{
return data;
}
void Element::printStudent()
{
string c = data->firstName;
cout<< "(" << c << ")";
}
//The add command
void Hash::add(Element e1)
{
int x = e1.getKey()%10;
int i = 0;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
}
else
{while(array[x] != NULL || array[x]->getData() != NULL)
{
x=(x+(i*i))%10;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
break;
}
else
{
i++;
}
}}
}
//The remove command
void Hash::remove(int n)
{
Element e2(NULL);
for(int j = 0; j<10; j++)
{
if(n == array[j]->getKey())
{
array[j] = &e2;
cout << "true" << endl;
break;
}
}
cout << "false" << endl;
}
//The Print command
void Hash::print()
{ int k = 0;
while(k<10)
{
if(array[k] == NULL)
{
cout << "(NULL)";
}
else if(array[k]->getData() == NULL)
{
cout << "(DEL)";
}
else
{
cout << "(" << array[k]->getData()->firstName << ")";
}
k++;
}
cout << endl;
}
Thank you for your help.
You have dangling pointers.
This function gets a temporary copy of an Element, calling it e1.
//The add command
void Hash::add(Element e1)
{
It then stores the address of this local variable.
array[x] = &e1;
And when Hash::add leaves scope, e1 no longer exists.
}
array[x] now points to memory that is no longer Element e1.
The general problem you are facing is that you have designed a Hash class that maintains pointers to objects, but has little control or knowledge regarding when those objects get destroyed.
You will need to personally ensure that objects added to your Hash last at least as long as the Hash does.
Simplest solution for your problem could be to store Element instances in Hash by value not by pointers. So:
class Hash{
private:
Element *array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element[10];
};
friend class Student;
};
Now when you store new element or remove existing you copy them:
array[x] = e1; // not &e1 anymore
This is not very good practice, but at least could change your program in some workable state with minimal changes.