I'm trying to insert data based on a given value - strBeg. I want the vectors to be sorted numerically based on this value. There are two different vectors. With my driver program shown below I would want the output to be:
linei[0][0] = 1 linei[0][1] = 8 refi[0][0] = 81 refi[0][1] = 88
linei[1][0] = 21 linei[1][1] = 31 refi[1][0] = 10 refi[1][1] = 20
linei[0][0] = 33 linei[0][1] = 44 refi[0][0] = 0 refi[0][1] = 11
linei[1][0] = 45 linei[1][1] = 47 refi[1][0] = 6 refi[1][1] = 8
As you can see the value of refBeg/refEnd does not affect the order, but must stay with it's strBeg/strEnd pair. I've posted my code below...it does not work. My current method is going to require a very large sorting function accounting for many different cases and I would like to avoid that if possible. I'm wondering if there is a more efficient way to implement this? I've though about combining the two vectors into one that will have 4 columns but would rather not as this will make it more confusing to understand (but am not completely opposed if it's the best/easiest option). Also there will be no overlap in linei, as in there will not be two sets of data with the same strBeg and strBeg/strEnd will not fall in between another strings start and stop points. I read through some other similar questions but couldn't quite figure out how to adapt them to my situation. Any help would be greatly appreciated!!!
NOTE: If I don't reply tonight I will in the morning. Thanks again!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void insertData(const int refBeg, const int refEnd, const int strBeg, const int strEnd, vector<vector<int> >& refi, vector<vector<int> >& linei);
int main(int argc, const char * argv[])
{
vector<vector<int> > refi;
vector<vector<int> > linei;
insertData(0, 11, 33, 44, refi, linei);
insertData(10, 20, 21, 31, refi, linei);
insertData(6, 8, 45, 47, refi, linei);
insertData(80, 88, 1, 8, refi, linei);
for (int i=0; i<linei.size(); i++) {
cout << "linei[" << i << "][0] = " << linei[i][0] << " ";
cout << "linei[" << i << "][1] = " << linei[i][1] << " ";
cout << "refi[" << i << "][0] = " << refi[i][0] << " ";
cout << "refi[" << i << "][1] = " << refi[i][1] << endl;
}
return 0;
}
void insertData(const int refBeg, const int refEnd, const int strBeg, const int strEnd, vector<vector<int> >& refi, vector<vector<int> >& linei) {
linei.push_back(vector<int>() );//creates a new row in linei
refi.push_back(vector<int>() );//creates a new row in refi
int size=(int)linei.size();
if ((size-1) == 0) {
linei[0].push_back(strBeg);
linei[0].push_back(strEnd);
refi[0].push_back(refBeg);
refi[0].push_back(refEnd);
} else {
for (int i=0; i<size; i++) {
if (strBeg > linei[i][0]) {
linei[i+1].push_back(strBeg);
linei[i+1].push_back(strEnd);
refi[i+1].push_back(refBeg);
refi[i+1].push_back(refEnd);
break;
}
}
}
}
Working code:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct line_ref
{
vector<int> linei;
vector<int> refi;
bool operator<(const line_ref &rhs) const { return linei[0] < rhs.linei[0]; }
};
void insertData(const int refBeg, const int refEnd, const int strBeg, const int strEnd, vector<line_ref>& line_ref_i);
int main(int argc, const char * argv[])
{
vector<line_ref> line_ref_i;
insertData(0, 11, 33, 44, line_ref_i);
insertData(10, 20, 21, 31, line_ref_i);
insertData(6, 8, 45, 47, line_ref_i);
insertData(80, 88, 1, 8, line_ref_i);
cout << "UNSORTED\n";
for (int i=0; i<line_ref_i.size(); i++) {
cout << "LINEI[0] = " << line_ref_i[i].linei[0] << " ";
cout << "LINEI[1] = " << line_ref_i[i].linei[1] << " ";
cout << "REFI[0] = " << line_ref_i[i].refi[0] << " ";
cout << "REFI[1] = " << line_ref_i[i].refi[1] << endl;
}
sort(line_ref_i.begin(), line_ref_i.end() );//, /*??*/);
cout << "SORTED\n";
for (int i=0; i<line_ref_i.size(); i++) {
cout << "LINEI[0] = " << line_ref_i[i].linei[0] << " ";
cout << "LINEI[1] = " << line_ref_i[i].linei[1] << " ";
cout << "REFI[0] = " << line_ref_i[i].refi[0] << " ";
cout << "REFI[1] = " << line_ref_i[i].refi[1] << endl;
}
return 0;
}
void insertData(const int refBeg, const int refEnd, const int strBeg, const int strEnd, vector<line_ref>& line_ref_i) {
line_ref_i.push_back(line_ref() );
int size = (int)line_ref_i.size() - 1;
line_ref_i[size].linei.push_back(strBeg);
line_ref_i[size].linei.push_back(strEnd);
line_ref_i[size].refi.push_back(refBeg);
line_ref_i[size].refi.push_back(refEnd);
}
Instead of parallel vectors, why not put the related elements into a struct?
struct line_ref
{
vector<int> linei;
vector<int> refi;
};
vector <line_ref> line_ref_i;
Alternately, instead of declaring a struct, you could just use a std::pair<int,int>, if you don't mind generic names like first and second for the fields.
Related
I created a struct named products that contains multiple data types:
struct products{
int ID;
string Name;
double Price;
int Quantity;
};
Then in the main function, I created an array named details which utilizes the struct products:
int main(){
struct products details[5];
Then I gave each array element data.
details[0] = {1, "Apple Juice", 12, 240};
details[1] = {2,"Bread", 10, 100};
details[2] = {3, "Chocolate", 5, 500};
details[3] = {4, "Dates", 50, 150};
details[4] = {5, "Eggs", 30, 360};
finally, I tried to print the values of the element at index 2:
cout<<details[2];
it gave me this error:
"Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream') and 'struct products')"
Here is a picture of the whole code
There are several ways of doing what you need, here's 3 of them:
Overload << operator:
std::ostream& operator<< (std::ostream& os, const products& pr)
{
return os << pr.ID << " " << pr.Name << " " << pr.Price << " " << pr.Quantity;
}
std::cout << details[2]; should now work as expected.
Print the struct members directly:
std::cout << details[2].ID << " " << details[2].Name
<< " " << details[2].Price << " " << details[2].Quantity;
Add a to_string() member function:
struct products{
//...
std::string to_string() const
{
std::ostringstream os; // #include <sstream>
os << ID << " " << Name << " " << Price << " " << Quantity;
return os.str();
}
};
Usage:
std::cout << details[2].to_string();
i write you like code.
#include <iostream>
using namespace std;
struct H{
int n;
int b;
};
int main() {
H h[] = {10, 20};
cout << h[0] << endl; // you can not print it becouse it is array!
return 0;
}
in this code i try to print struct!
but i can not do it!
it like:
#include <iostream>
using namespace std;
struct H{
int n;
int b;
};
int main() {
H h = {10, 20};
cout << h << endl;
return 0;
}
just try:
#include <iostream>
using namespace std;
struct H{
int n;
int b;
};
int main() {
H h[] = {10, 20};
cout << h[0].n << endl;
cout << h[0].b << endl;
return
0;
}
I am new to C++ and learning data structures. In the below code I am getting an "out of range warning", and do not understand what I am doing wrong.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers{100,-1,2,4,55,78,3};
int temp {};
int pass {};
pass = numbers.size();
for(int i {0} ;i<pass-1;i++){
for(int j {0} ; j<pass-1-i ; j++){
if(numbers.at(j) > numbers.at(j+1)){
temp = numbers.at(j);
numbers.at(j)=numbers.at(j+1);
numbers.at(j+1)=temp;
}
}
}
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl;
cout << numbers.at(2) << endl;
cout << numbers.at(3) << endl;
cout << numbers.at(4) << endl;
cout << numbers.at(5) << endl;
cout << numbers.at(6) << endl;
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
return 0;
}
It seems like you may not understand how std::vectors work.
You have only declared 7 elements in your vector which means you can only go up to the index 6. This is because std::vector's indices start at 0. This is true for std::array as well.
vector<int> numbers{100,-1,2,4,55,78,3};
However, in your code you have put these two statements:
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
which doesn't work because like I mentioned you can only go up to index 6.
You should also consider using a for loop like the comments mention above. It is more simple to use and is less work.
For example eith a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers{ 100,-1,2,4,55,78,3 };
int temp{};
int pass{};
pass = numbers.size();
for (int i{ 0 }; i < pass - 1; i++) {
for (int j{ 0 }; j < pass - 1 - i; j++) {
if (numbers.at(j) > numbers.at(j + 1)) {
temp = numbers.at(j);
numbers.at(j) = numbers.at(j + 1);
numbers.at(j + 1) = temp;
}
}
}
std::cout << "v = { ";
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers.at(i) << ", ";
}
std::cout << "}; \n";
return 0;
}
Output:
v = { -1, 2, 3, 4, 55, 78, 100, };
I am trying to write a template-based function frequency that will return the count of the occurrences of an item in an array of items.
So far I have
#include <iostream>
using namespace std;
template <class T>
T frequency(T array[], T arraySize, T item) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}
int main() {
// Testing template with int
int intArray[10] = { 1, 2, 3, 3, 14, 3, 2, 7, 99, 2 };
cout << "{ ";
for (int i = 0; i < 10; i++) {
cout << intArray[i] << " ";
}
cout << "}" << endl;
cout << "Frequency of 3: " << frequency(intArray, 10, 3) << endl;
cout << "Frequency of 2: " << frequency(intArray, 10, 2) << endl;
cout << "Frequency of 99: " << frequency(intArray, 10, 99) << endl;
// Testing template with double
double doubleArray[10] = { 1.5, 2.2, 99.4, 132.11, 1.5, 2.22, 1.515, 66.2, 51.8, 34.0 };
cout << "{ ";
for (int j = 0; j < 10; j++) {
cout << doubleArray[j] << " ";
}
cout << "}" << endl;
cout << "Frequency of 1.5: " << frequency(doubleArray, 10, 1.5) << endl;
cout << "Frequency of 2.2: " << frequency(doubleArray, 10, 2.2) << endl;
cout << "Frequency of 100.1: " << frequency(doubleArray, 10, 100.1) << endl;
return 0;
}
however, I get an error of "no matching function for call to 'frequency(double [10], int, double)'" towards when I try to print out the frequency of the doubles. I am unsure what I am doing wrong.
Thank you for any help!
frequency takes parameters of element of array and arraySize with the same type, i.e. T. But you pass arguments of that with different types, i.e. double vs int. Then the type deduction fails because T can't be deduced (determined).
According to your implemantaion, the type arraySize seems fixed, you can just declare it as std::size_t or int. And same for the return type. Their types won't change then shouldn't be declared with template parameters.
template <class T>
int frequency(T array[], std::size_t arraySize, T item) {
int count = 0;
for (std::size_t i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}
You should not use your template parameter with arraySize. Because you compare it with i, int i = 0; i < arraySize;. And the return type should not be T too because a double is not accurate don't use it like counter. Plus you do return count and you write int count = 0;
template <class T>
int frequency(T const array[], int arraySize, T const &item);
Be aware that the standard library has a template function to this purpose. In a production code, you should use std::count_if().
int count = std::count_if(intArray.begin(), intArray.end(), [](int i){ return i == 42; });
You can crate frequency as, so that it can be used with other containers.
#include <iostream>
#include <vector>
using namespace std;
template <class outputIterator,class T>
int frequency(outputIterator b,outputIterator e ,const T& v) {
int count = 0;
while(b != e)
{
if(*b == v)
{
count++;
}
b++;
}
return count;
}
int main ()
{
std::vector<int> first={1,1,2,3,4,5,5};
std::cout<<frequency(first.begin(),first.end(),1)<<std::endl;
int arr[]={1,2,3,5,5,5};
std::cout<<frequency(std::begin(arr),std::end(arr),5)<<std::endl;
return 0;
}
I am fairly new to C++ and pointers, and would greatly appreciate any help. I am trying to print a sorted array of pointers without changing the original array of structs. I cannot properly sort the pointers. I am using the std::sort that worked on the original array, but I fail at using it on pointers. To make things worse, my failed attempts all change the original. Thank you for your time.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
struct Student
{
int age;
char name[30];
};
void displayStudent(Student s)
{
cout << endl<< s.age<< " "<< s.name;
}
int main()
{
Student s1;
s1.age = 10;
strcpy(s1.name, "Guy");
Student s2;
s2.age = 33;
strcpy(s2.name, "Buddy");
Student s3;
s3.age = 16;
strcpy(s3.name, "Friend");
Student s4;
s4.age = 55;
strcpy(s4.name, "Pal");
Student myClass[4];
myClass[0] = s1;
myClass[1] = s2;
myClass[2] = s3;
myClass[3] = s4;
Student *myClassPt;
myClassPt = &myClass[0];
Student *SBN[4];
Student *SBG[4];
Student *SBA[4];
for (int i = 0; i < 4; i++)
{
SBN[i] = &(myClassPt[i]);
SBA[i] = &(myClassPt[i]);
}
cout << "Original" << endl;
for (int i = 0; i < 4; i++)
{
displayStudent(myClass[i]);
}
std::sort(*SBN, *SBN + 4, [](Student &a, Student &b){ return a.name < b.name; });
std::sort(*SBA, *SBA + 3, [](Student const &a, Student const &b){ return a.age < b.age; });
cout <<endl<<endl<< "Sorted by name" << endl;
for (int i = 0; i < 4; i++)
{
displayStudent(*SBN[i]);
}
cout << endl << endl << "Sorted by age" << endl;
for (int i = 0; i < 4; i++)
{
displayStudent(*SBA[i]);
}
cout << endl <<endl<< "Original" << endl;
for (int i = 0; i < 4; i++)
{
displayStudent(myClass[i]);
}
return 0;
}
It seems you want to sort the pointers according to the objects they point to. So you need to sort the pointers according to the objects they point to, instead of trying to sort the objects they point to directly:
std::sort(SBN, SBN + 4, [](const Student* a, const Student* b)
{ return a->name < b->name; });
Here's a working example:
#include <iostream>
#include <algorithm>
struct student { int age; };
int main()
{
student ss[] = { {23}, {12}, {42}, {9}};
std::cout << "students\n";
for (const auto& s : ss) std::cout << s.age << " ";
std::cout << std::endl;
student* ps[] = { &ss[0], &ss[1], &ss[2], &ss[3]};
std::cout << "pointers to student\n";
for (auto p : ps) std::cout << p->age << " ";
std::cout << std::endl;
std::sort(ps, ps + 4, [](const student* a, const student* b)
{ return a->age < b->age;});
std::cout << "pointers to student after sorting\n";
for (auto p : ps) std::cout << p->age << " ";
std::cout << std::endl;
}
Output:
students
23 12 42 9
pointers to student
23 12 42 9
pointers to student after sorting
9 12 23 42
I'm trying to read names and ages from user, until user inputs "stop". Then just print all these values. Please help me , I'm just the beginner in C++
// Pass.cpp
// Reading names and ages from user and outputting them
#include <iostream>
#include <iomanip>
#include <cstring>
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::strcmp;
char** larger(char** arr);
int* larger(int* arr);
void read_data(char*** names, int** ages);
void print_data(char*** names, int** ages);
int main()
{
char** names = new char*[5];
char*** p_names = &names;
int* ages = new int[5];
int** p_ages = &ages;
read_data(p_names,p_ages);
print_data(p_names,p_ages);
}
void read_data(char*** names, int** ages)
{
const char* sent = "stop";
const int MAX = 15;
int count = 0;
char UI[MAX];
cout << "Enter names and ages."
<< endl << "Maximum length of name is " << MAX
<< endl << "When stop enter \"" << sent << "\".";
while (true)
{
cout << endl << "Name: ";
cin.getline(UI,MAX,'\n');
if (!strcmp(UI, sent))
break;
if (count + 1 > sizeof (&ages) / sizeof (&ages[0]))
{
*names = larger(*names);
*ages = larger(*ages);
}
*names[count] = UI;
cout << endl << "Age: ";
cin >> *ages[count++];
}
}
void print_data(char*** names, int** ages)
{
for (int i = 0; i < sizeof(*ages) / sizeof(*ages[0]);i++)
{
cout << endl << setw(10) << "Name: " << *names[i]
<< setw(10) << "Age: " << *ages[i];
}
}
char** larger(char** names)
{
const int size = sizeof(names) / sizeof(*names);
char** new_arr = new char*[2*size];
for (int i = 0; i < size; i++)
new_arr[i] = names[i];
return new_arr;
}
int* larger(int* ages)
{
const int size = sizeof(ages) / sizeof(*ages);
int* new_arr = new int[2 * size];
for (int i = 0; i < size; i++)
new_arr[i] = ages[i];
return new_arr;
}
You are really over complicating things.
Given the original problem:
Write a program that reads a number (an integer) and a name (less than
15 characters) from the keyboard. Design the program so that the data
is done in one function, and the output in another. Store the data in
the main() function. The program should end when zero is entered for
the number. Think about how you are going to pass the data between
functions
The problem wants you to think about passing parameters to functions. A simple solution would be:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
// Pass in a char array and an integer reference.
// These values will be modified in the function
void read_data(char name[], int& age)
{
cout << endl << "Age: ";
cin >> age;
cin.ignore();
cout << endl << "Name: ";
cin.getline(name, 16);
}
// Pass a const array and an int value
// These values will not be modified
void print_data(char const *name, int age)
{
cout << endl << setw(10) << "Name: " << name
<< setw(10) << "Age: " << age;
}
int main()
{
char name[16];
int age;
cout << "Enter names and ages."
<< endl << "Enter 0 age to quit.";
do {
read_data(name, age);
print_data(name, age);
} while (0 != age)
}
EDIT: Modified per user3290289's comment
EDIT2: Storing data in an array
// Simplify by storing data in a struct (so we don't have to manage 2 arrays)
struct Person {
char name[16];
int age;
};
// Returns how many People were input
int read_data(Person*& arr)
{
int block = 10; // How many persons to allocate at a time
arr = NULL;
int arr_size = 0;
int index = 0;
while (true) {
if (index == arr_size) {
arr_size += block;
arr = (Person *)realloc(arr, arr_size * sizeof(Person)); // Reallocation
// Should check for error here!
}
cout << endl << "Age: ";
cin >> arr[index].age;
cin.ignore();
if (0 == arr[index].age) {
return index;
}
cout << endl << "Name: ";
cin.getline(arr[index++].name, 16);
}
}
void print_data(Person *arr, int count)
{
for (int i = 0; i < count; i++) {
cout << endl << setw(10) << "Name: " << arr[i].name
<< setw(10) << "Age: " << arr[i].age;
}
}
int main()
{
Person *arr;
int count = read_data(arr);
print_data(arr, count);
free(arr); // Free the memory
}
try this:
#include <iostream>
#include <iomanip>
#include <vector>
#include <sstream>
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::strcmp;
void read_data(std::vector<std::string> &names, std::vector<int> &ages);
void print_data(std::vector<std::string> &names, std::vector<int> &ages);
int main()
{
std::vector<std::string> names;
std::vector<int> ages;
read_data(names, ages);
print_data(names, ages);
}
void read_data(std::vector<std::string> &names, std::vector<int> &ages)
{
const char* sent = "stop";
cout << "Enter names and ages."
<< endl << "When stop enter \"" << sent << "\".";
while (true)
{
std::string input;
cout << endl << "Name: ";
std::getline(cin, input);
if (!strcmp(input.c_str(), sent))
break;
names.push_back(input);
cout << endl << "Age: ";
std::string age;
std::getline(cin, age);
ages.push_back(atoi(age.c_str()));
}
}
void print_data(std::vector<std::string> &names, std::vector<int> &ages)
{
for (int i = 0; i < names.capacity() ; i++)
{
cout << endl << setw(10) << "Name: " << names.at(i)
<< setw(10) << "Age: " << ages.at(i);
}
}
One problem I see is this if statement:
if (count + 1 > sizeof (&ages) / sizeof (&ages[0]))
&ages is the address of an int**, a pointer, and so it's size is 8 (usually) as that is the size of a pointer type. The function does not know the size of the array, sizeof will only return the correct answer when ages is declared in the same scope.
sizeof(&ages) / sizeof(&ages[0])
will always return 1
I believe one natural solution about this problem is as follows:
create a "std::map" instance. Here std::map would sort the elements according to the age. Here my assumption is after storing the data into the container, you would like to find about a particular student age/smallest/largest and all various manipulation with data.Just storing and printing the data does not make much sense in general.
create a "std::pair" and take the both input from the user into the std::pair "first" and "second" member respectively. Now you can insert this "std::pair" instance value into the above "std::map" object.
While printing, you can now fetch the each element of "std::map" in the form of "std::pair" and then you can display pair "first" and "second" part respectively.