cannot print struct contents stored in vector C++ - c++

Hello guys I have problem when I have an array of student record which is struct by type. I have randomly assigned numbers to each of student during that I am storing each record in the vector. After that I want to sort it by marks. The problem is that iterator doesn't print the contents of vector. I believe problem is at statementcout<<*RecVectorItr.Marks<<endl; but I cannot figure out why. Can you point out what's wrong. Thank you in advance. Here is code
include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Record
{
int RollNum;
char Name[20];
float Marks;
char Status[10];
};
bool compFunc (struct Record Rec1, struct Record Rec2)
{
return (Rec1.Marks<Rec2.Marks);
}
int main ()
{
struct Record Students[20];
float MarksArray[20]={30.4, 20.1, 11.9, 50.0, 55, 100, 11, 34, 90, 12, 13, 14, 19, 22.4, 88 , 56, 22, 78, 98, 29};
vector<Record> RecVector;
for (int i=1;i<21;i++)
{
Students[i].Marks=MarksArray[i];
RecVector.push_back (Students[i]);
}
sort (RecVector.begin (), RecVector.end (), compFunc);
for (vector<Record>::iterator RecVectorItr=RecVector.begin (); RecVectorItr!=RecVector.end ();RecVectorItr++)
cout<<*RecVectorItr.Marks<<endl;
return 0;
}

Your code is not working due to a problem of Operator Precedence:
When parsing an expression, an operator which is listed on some row
will be bound tighter (as if by parentheses) to its arguments than any
operator that is listed on a row further below it.
Table that list the precedence can be found here
Change your printing line with the following:
cout<<RecVectorItr->Marks<<endl;

Related

Subclass Mess on a vague Binary Tree Question

So, I'm taking data structures and algorithms and I'm trying to answer the following question:
(20 marks) Exercise 6.7. Create a subclass of BinaryTree whose nodes have fields for storing preorder, post-order, and in-order numbers. Write methods preOrderNumber(), inOrderNumber(), and postOrderNumbers() that assign these numbers correctly. These methods should each run in O(n) time.
Now... I'm confused about what the question is even asking. Are they asking me to store an array in each Node that records the preOrder, inOrder and postOrder values of the whole tree??? Or are they asking me to create a subclass of Node that contains an integer that's hold the Next value, according to a preOrder, inOrder or postOrder value, relative to the Node we're in...
So, I went with the former and assumed that they wanted the array. But the trouble now is that I've created a new version of Node and I'm trying to call this preOrderNumber() function at the bottom but I get the following error:
BTNode.h contains the code I used in a previous question to construct a binary tree. It just defines a class Node with a left, right, and parent pointer, as well as an add() function to add new values to the tree, and a preOrderNEXT() function that gets the next value in the tree according to that transversal order. the same is true for inOrderNEXT(), and postOrderNEXT()
#include <iostream>
#include "BTNode.h"
#include <vector>
using namespace std;
class BinaryTree : public Node {
public:
vector<int> preOrderNumbers;
vector<int> inOrderNumbers;
vector<int> postOrderNumbers;
BinaryTree(int x);
~BinaryTree();
int preOrderNumber();
int inOrderNumber();
int postOrderNumber();
};
BinaryTree::BinaryTree(int x) : Node(x) {}
BinaryTree::~BinaryTree() {}
int BinaryTree::preOrderNumber() {
Node* next_Node = preOrderNEXT(this);
while (next_Node != NULL) {
preOrderNumbers.push_back(next_Node->data);
next_Node = preOrderNEXT(next_Node);
}
}
int BinaryTree::inOrderNumber() {
Node* next_Node = inOrderNEXT(this);
while (next_Node != NULL) {
inOrderNumbers.push_back(next_Node->data);
next_Node = inOrderNEXT(next_Node);
}
}
int BinaryTree::postOrderNumber() {
Node* next_Node = postOrderNEXT(this);
while (next_Node != NULL) {
postOrderNumbers.push_back(next_Node->data);
next_Node = postOrderNEXT(next_Node);
}
}
int main() {
Node* BinaryT = new BinaryTree(rand() % 1000);
int arr[] = { 71, 6, 28, 49, 41, 42, 88, 72, 21, 84, 85, 94, 59, 29, 2, 97, 33, 23, 78 };
cout << "We add these integers, one by one, using a for loop to the binary tree:\n" << endl;
cout << "[ 60, ";
for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
BinaryT->add(arr[i]);
cout << arr[i] << ", ";
}
int x = BinaryT->preOrderNumber();
}
OKAY, So yea I think I found out the real crux of this question and I'll answer this here for anyone else stuck in this situation.
The key to making sense out of this question is to visit its location in the textbook. The course coordinator ripped this question out of the textbook and doesn't provide any context. In Pat Morin's book Open Data Structure, An Introduction, on page 149 there's an illustration 6.10.
So, what this question IS ACTUALLY ASKING you to do is write a subclass for the Binary Tree Nodes such that each Node holds an integer that keeps track of its position within the corresponding traversal type. So maybe your Node would be visited 3rd in preOrder, 4th in an inOrder, and 2nd in a postOrder traversal. So that Node should hold a 3, a 4, and a 2 in the corresponding position. And then you need a function to update that position in O(n) time.

How to order a list of numbers without changing the list [duplicate]

This question already has answers here:
Sorting a vector of custom objects
(14 answers)
Closed 4 years ago.
I am in need of ordering a list of numbers stored in a C++ vector:
#include <vector>
#include <iostream>
#include <algorithm>
struct A
{
};
bool compare(A i1, A i2)
{
if(i1.vec.size() > i2.vec.size())
return true;;
}
int main()
{
std::vector<A> ax;
ax.emplace_back(A{ 100, 300, 6, 123, 12, 451, 552});
ax.emplace_back(A{ 100, 300, 6, 123, 12, 451});
std::sort(ax.begin(), ax.end(), compare);
return 0;
}
As per the above code the ordering of ax vector should be:
{ 100, 300, 6, 123, 12, 451}
{ 100, 300, 6, 123, 12, 451, 552}
I am unable to get what needs to be added in compare function to achieve it?
your comparison is not based on the content of the vector but on their size
furthermore you pass Oid by value rather than by const reference in compare, this is expensive for nothing because they are copied each time

Initialization of list of sets of integers in C++98

this might seem trivial but I wasn't able to find it on the web so far, so
I want to initialize a list of sets of integers or a set of sets of integers, like this:
list< set<int> > lsi = {{}};
or maybe like this:
set< set<int> > ssi = {{5}, {6}, {7}};
in C++98. The reason for this is that I have to submit it as an exercise in a submission system that does not accept C++11.
I have found out how to initialize a container in the old syntax from an array of integers, for example
int tmp[] = {1,2,3};
set<int> s (tmp, tmp + sizeof(tmp) / sizeof(tmp));
but not a list< set<int> >.
As mentioned in the comments, this is not possible without c+11 / boost.
That being said, the shortest way to initialize would probably be repeating set's initialization (which you mentioned in your question):
int set1v[] = {10, 20, 30, 40};
int set2v[] = {11, 22, 33, 44};
int set3v[] = {15, 25, 35, 45};
set<int> setV[] = {
set<int>(set1v, set1v + sizeof(set1v) / sizeof(set1v[0])),
set<int>(set2v, set2v + sizeof(set2v) / sizeof(set2v[0])),
set<int>(set3v, set3v + sizeof(set3v) / sizeof(set3v[0]))
};
set< set<int> > mySet(setV, setV + sizeof(setV) / sizeof(setV[0]));
Btw, Since you're checking arrays' sizes so many times I'd suggest you use a count macro:
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
It will look a little better:
#define END_OF(x) (x + COUNT_OF(x))
int set1v[] = {10, 20, 30, 40};
int set2v[] = {11, 22, 33, 44};
int set3v[] = {15, 25, 35, 45};
set<int> setV[] = {
set<int>(set1v, END_OF(set1v)),
set<int>(set2v, END_OF(set2v)),
set<int>(set3v, END_OF(set3v))
};
set< set<int> > mySet(setV, END_OF(setV));
I will give you some approach I have used to initialize static STL storages, but the syntax becomes somewhat obscure for this case:
template <typename Type>
struct SetInit : public std::set<Type> {
SetInit<Type>& operator()(const Type& data) {
this->insert(data);
return *this;
}
};
int main () {
std::set<std::set<int> > test_set = SetInit<std::set<int> >() // Call ctor
(SetInit<int>()(1)(2)(3))(SetInit<int>()(4)(5)(6)); // Each element in () is inserted in the set
return 0;
}
The basic idea is to use an operator() to include elements in the storage. The advantage of this idea is that it can be used to initialize static lists and sets because the expressions can be evaluated at compile time.

C++ : Creating an array of objects

I have the following class:
class student
{
int rol , marks;
char name[20];
public:
student(int r , int m , char n[])
{
rol = r;
marks = m;
strcpy(name,n);
}
int roll()
{
return rol;
}
};
and now I am trying to create an array of objects like so:
student a[]= {(1,10,"AAA"),(2,20,"BBB"),(3,30,"CCC")}; // I get the error on this line
but I get this error message:
Error: testing.cpp(40,56):Cannot convert 'char *' to 'student[]'
When I do this :
student a(1,10,"AAAA");
student b(2,20,"BBBB");
student c(3,30,"CCCC");
student d[3]={a,b,c};
it works perfectly.
#WhozCraig Thx a lot . this is the solution to my problem:
I had to initialize the array as below:
student a[]= {
student(1, 10, "AAA"),
student(2, 20, "BBB"),
student(3, 30, "CCC")
};
My initial code is wrong probably because the constructor cant create more than 1 object at a time.
In an expression (1,10,"AAA") means to apply the comma operator. To initialize an array, you have to provide expressions that can initialize each array member. So one way is:
student a[] = {
student(1, 10, "AAA"), // creates a temporary student to use as initializer
student(2, 20, "BBB"),
student(3, 30, "CCC") };
Since C++11 you can write:
student a[] = { {1, 10, "AAA"}, {2, 20, "BBB"}, {3, 30, "CCC"} };
because C++11 added the feature that an object's constructor can be called via a brace-enclosed initializer list. This is the same reason you could also write afterwards:
a[0] = { 4, 40, "DDD" };
Note: as mentioned in comments, char n[] should be char const n[], and you could improve safety by using std::string name; instead of char name[20];.

Program hanging while running, compiles well

EDITED :
#include<iostream>
using namespace std;
#include<conio.h>
#include<string.h>
void dfsvisit(int a[][30], int i, const char *color[])
{
int v;
int p[30];
int f[30]={};
static int j=1;
color[i]="gray";
for(v=1;v<31;v++)
while(a[i][v]!=0)
if(!strcmp(color[a[i][v]],"white"))
{
p[a[i][v]]=i;
dfsvisit(a,i,color);
}
color[i]="black";
j++;
f[i]=1;
cout<<f[i]<<" ";
}
int main()
{
int a[][30]={{2, 16},{4, 8},{5, 16, 21},{1, 2},{1, 9, 27},{1, 10, 15},{4, 6, 11, 12},{4, 16},{2, 19, 29},{3, 14, 28},{3, 13, 15, 17},{8, 9, 18, 26},{1, 7, 10, 19},{5, 8, 20, 24},{3, 21, 29},{1, 2, 8},{16, 23, 28, 29},{4, 12, 21, 24}, {3, 15, 16},{2, 3, 6, 22},{4, 15, 25},{4, 6, 20, 24},{9, 10, 11, 12},{19, 26, 30},{2, 27, 29},{1, 28, 29, 30},{8, 16, 29},{6, 10, 30},{19, 21, 27},{1, 2, 3, 22}};
int i;
const char *color[30];
for(i=1;i<31;i++)
color[i]="white";
for(i=1;i<31;i++)
if(!strcmp(color[i],"white"))
dfsvisit(a,i,color);
return 0;
}
Just want to make sure if I am using const char c correct? If yes, where else have I done the mistake? I am trying to run it on codeblocks. It compiles well, but when I try to run it, it shows program has stopped working.
Thanks.
Change:
for(i=1;i<=30;u++)
to:
for (i = 0; i < 30; i++)
You're comparing pointers to constant strings, which may or may not be equal when the strings are equal. Use an enum for this kind of algorithm:
enum { BLACK, GRAY, WHITE };
First of all, your for loop is incorrect, it should be like this:
for(i = 0; i < 30; i++)
Second, your array int a[][30] should be like int a[30][] (30 elements of 2, 3 or 4 integers).
Third, you can't pass an array like this, use a pointer.
Well, this code is not clear, and the recursive function could make a stack overflow.
I hope it will help you.
You say that this:
for(i=1;i<=30;u++)
compiles?
I suggest changing the u to an i...
EDIT:
OK, so you say the u was a typo.
Next step: start the thing in a debugger, wait for it to loop, break into it and step through.
That should tell you where something happens to your loop variable.
EDIT 2:
< niggle >
I second everybody who suggests you use std::string. You might consider dropping the irregular arrays in favor of std::vectors of std::vectors, which, through the use of iterators, would have caught the fencepost error in your loop for you. In general, the STL vector is safer and more comfortable than an array while being just as fast and small.
And while were at it, it is best practice to declare your loop variables within the for instead of at the beginning of the function scope (RAII). Unless, of course, you need that value after the loop.
< /niggle >
EDIT 3:
For more on std::string, std::vector and std::otherStuff: the book Accelerated C++ gives a good introduction to C++ and especially the STL. Concepts like char* or arrays only come up quite late, after the STL-way of doing things has been safely covered and practiced. I'd really like to see something like that for the Boost library...
You want to use strcmp instead of == for your string comparison.
However, it's not clear why this would hang. You've removed the code that could have this go into an infinite loop.
No, you are not correctly using C style strings (char *). Give it up and use std::string instead.
For example:
const char *color[30];
for(i=1;i<31;i++)
color[i]="white";
The above fragment copies pointers and does not make duplicates of the text. This may or may not be what you wanted.
Rewritten more safely:
const char * color[30]; // 30 pointers to char.
const char text_white[] = "white";
for (i = 0; i < 30; ++i) // Note addition of spaces
{
color[i] = text_white;
}
The const char text_white[] declares a pointer, text_white, to constant data. This will let the compiler know when you try to assign to the literal.
The C++ code for this:
typedef std::vector<std::string> Text_Container;
Text_Container texts;
const std::string white_text("white");
const unsigned int MAX_TEXTS = 30;
for (i = 0; i < MAX_TEXTS; ++i)
{
texts[i] = white_text; // Makes a copy of the string.
}
Give up on char * for text unless your program needs to conserve memory. Prefer std::string and std::vector.