Getting an array of structures by using an element of structure - c++

I have an array which holds a structure like:
struct Point
{
int x;
int y;
}
Point array_of_structure[10] ;
for(int i=0;i<10;i++)
{
array_of_structure[i].x = i*2;
}
I want to get the structure which holds x value of 6. In this way I access the y value of that structure. How can I do it?
It's something like the below:
Point p = Get the structure which contains x value of 6;
int c = p.y;
Here is a sample solution. But I need a better idea or ideas.
for(int i=0;i<10;i++)
if(array_of_structure[i].x==6)
return array_of_structure[i].y;
I thought about maybe pointers make this job but I'm not sure about it. I cannot figure out how to solve this problem.

Standard library provides a function std::find_if which can be used to find an item without a loop. As a learning exercise, however, you could do it using a loop as described below:
You can iterate your array of structs until you find the x of interest. You can use a pointer or an index, depending on your preferences. You need to set a flag indicating if you have found your item or not.
Here is how you can do it with a pointer:
struct Point *ptr;
bool found = false;
for (ptr = array_of_structure ; !found && ptr != &array_of_structure[10] ; ptr++) {
found = (ptr->x == x);
}
if (found) {
cout << ptr->y << endl;
}
Here is how you can do it with an index:
int index ;
bool found = false;
for (index = 0 ; !found && index != 10 ; index++) {
found = (array_of_structure[index].x == x);
}
if (found) {
cout << array_of_structure[index].y << endl;
}
Note: if you are looking for a find_if solution, here is an answer that explains this approach.

Related

Vector Subscript out of Range. Comparing Elements of Vectors

So I have a vector like this
All_Pos={0,10,15,24,30,33,66}
And three smaller vectors that contain the numbers from the previous vector, let's say
Vec_Lin={0,15}
Vec_Circ={24,33,66}
Vec_Arc={10,30}
I want to make something like this:
All_Pos[0]=Vec_Lin[0]? YES -> Do something
All_Pos[1]=Vec_Lin[1]?No
All_Pos[1]=Vec_Circ[0]?No
All_Pos[1]=Vec_Arc[0]?Yes -> Do Something
Ans so on, until i finish my All_Pos. The problem is that i get vector out of range and i don't know how to fix that.
int counter_linie=0;
int counter_cerc=0;
int counter_arc=0;
for (int p = 0; p < All_pos.size(); p++)
{
if(All_pos[p] == Vec_Lin[counter_linie])
{
//Do something
counter_linie++;
}
if (All_pos[p] == Vec_circ[counter_cerc])
{
//Do something
counter_cerc++;
}
if (All_pos[p] == Vec_Arc[counter_arc])
{
/Do something
counter_arc++;
}
}
You should check for out of range. [] operator works ,when indexing is in limits from '0' to vector.size().
void process_vector(void)
{
std::vector<int> All_Pos = { 0,10,15,24,30,33,66 };
std::vector<int> Vec_Lin = { 0,15 };
std::vector<int> Vec_Circ = { 24,33,66 };
std::vector<int> Vec_Arc = { 10,30 };
int counter_linie = 0;
int counter_cerc = 0;
int counter_arc = 0;
for (int p = 0; p < All_Pos.size(); p++) {
if (counter_linie< Vec_Lin .size() && All_Pos[p] == Vec_Lin[counter_linie])
{
//Do something
counter_linie++;
}
if (counter_cerc < Vec_Circ.size() && All_Pos[p] == Vec_Circ[counter_cerc])
{
//Do something
counter_cerc++;
}
if (counter_arc < Vec_Arc.size() && All_Pos[p] == Vec_Arc[counter_arc])
{
// Do something
counter_arc++;
}
}
std::cout << counter_linie << " " << counter_cerc << " " << counter_arc << std::endl;
}
You are trying to access elements that don't exist in your smaller vectors.
Vec_circ can only be accessed with indices 0, 1 and 2, but after three successful checks for Vec_circ in your loop counter_cerc will be 3.
Trying to access Vec_circ[3] then leads to the error.
You need a mechanism that prevents this case.
You should step through your code with a debugger to see the problem.
Initially the values are:
int counter_linie=0;
int counter_cerc=0;
int counter_arc=0;
After the first iteration the values are:
counter_linie=1;
counter_cerc=0;
counter_arc=0;
After the second iteration the values are:
counter_linie=1;
counter_cerc=0;
counter_arc=1;
After the third iteration the values are:
counter_linie=2;
counter_cerc=0;
counter_arc=1;
And now you try to read
Vec_Lin[2]
in
if(All_pos[p] == Vec_Lin[counter_linie])
That's your problem. Add a check into the if conditions.
if(counter_linie < Vec_Lin.size() && All_pos[p] == Vec_Lin[counter_linie])

My array is gettting an error because it's being defined as a singular integer

The point of this program is to output whether a series of digits (the number of digits undefined) is sorted or not (largest to smallest or smallest to largest).
I have defined my array in my function parameter, and I am trying to use a for loop to store the user's input, as long as it is above 0, in said array.
However, I am getting the error argument of type int is incompatible with parameter of type int*.
The exact error is the argument of type int is incompatible with parameter of type int*.
It is referring to line 22 and 23, these two;
isSorted(list[2000]); and
bool is = isSorted(list[2000]);.
I know this means my for loop is assigning a single value to my variable repeatedly from reading similar questions however I can not figure out how to fix this.
#include <iostream>
using namespace std;
bool isSorted(int list[]);
int main()
{
int i;
int list[2000];
int k = 0;
for (i = 0; i < 2000; i++)
{
int j;
while (j > 0)
{
cin >> j;
list[i] = j;
}
}
isSorted(list[2000]);
bool is = isSorted(list[2000]);
if (is == true)
cout << "sorted";
else
cout << "unsorted";
return 0;
}
bool isSorted(int list[])
{
int i = 0;
for (i = 0; i < 2000; i++)
{
if (list[i] > list[i + 1] || list[i] < list[i - 1])
{
return false;
}
else
return true;
}
}
I removed unused variable k.
Made 2000 parameterized (and set to 5 for testing).
In isSorted you are not allowed to return
true in the else as if your first element test would end in else you would return true immediately not testing other elements. But those later elements can be unsorted as well.
In isSorted you are not allowed to run the loop as for(i = 0; i < 2000; i++), because you add inside the for loop 1 to i and end up querying for i == 1999 list[2000], which is element number 2001 and not inside your array. This is correct instead: for (i = 0; i < 1999; i++). You also do not need to check into both directions.
You cannot call isSorted(list[2000]) as this would call is sorted with an int and not an int array as parameter.
You write int j without initializing it and then query while j > 0 before you cin << j. This is undefined behaviour, while most likely j will be zero, there is no guarantee. But most likely you never enter the while loop and never do cin
I renamed the isSorted as you just check in your example for ascending order. If you want to check for descending order you are welcome to train your programming skills and implementing this yourself.
Here is the code with the fixes:
#include <iostream>
using namespace std;
bool isSortedInAscendingOrder(int list[]);
const int size = 5; // Set this to 2000 again if you want
int main()
{
int i;
int list[size];
for (i = 0; i < size; i++)
{
int j = 0;
while(j <= 0)
{
cin >> j;
if(j <= 0)
cout << "rejected as equal or smaller zero" << endl;
}
list[i] = j;
}
if (isSortedInAscendingOrder(list))
cout << "sorted" << endl;
else
cout << "unsorted" << endl;
return 0;
}
bool isSortedInAscendingOrder(int list[])
{
for (int i = 0; i < size -1; i++)
{
if (list[i] > list[i + 1])
{
return false;
}
}
return true;
}
This is a definition of an array of 2000 integers.
int list[2000];
This is reading the 2000th entry in that array and undefined, because the highest legal index to access is 1999. Remember that the first legal index is 0.
list[2000]
So yes, from point of view of the compiler, the following only gives a single integer on top of being undefined behaviour (i.e. "evil").
isSorted(list[2000]);
You probably should change to this, in order to fix the immediate problem - and get quite close to what you probably want. It names the whole array as parameter. It will decay to a pointer to int (among other things loosing the information of size, but you hardcoded that inside the function; better change that by the way).
isSorted(list);
Delete the ignored first occurence (the one alone on a line), keep the second (the one assigning to a bool variable).
On the other hand, the logic of a your sorting check is flawed, it will often access outside the array, for indexes 0 and 1999. I.e. at the start and end of your loop. You need to loop over slightly less than the whole array and only use one of the two conditions.
I.e. do
for (i = 1; i < 2000; i++)
{
if (list[i] < list[i - 1])
/* ... */
The logic for checking ascending or descending sorting would have to be more complex. The question is not asking to fix that logic, so I stick with fixing the issues according to the original version (which did not mention two-way-sorting).
You actually did not ask about fixing the logic for that. But here is a hint:
Either use two loops, which you can break from as soon as you find a conflict, but do not return from the fuction immediatly.
Or use one loop and keep a flag of whether ascending or descending order has been broken. Then return true if either flag is still clear (or both, in case of all identical values) or return false if both are set.

How to assign values to struct?

I have a struct to assign values to it. But my programm crashs it. Hopefully you can help me.
struct HashEntry{
std::string key; //the key of the entry
bool used; //the value of the entry
int value; //marks if the entry was used before
};
HashEntry *initHashList(int N){
HashEntry* hashList = new HashEntry[N];
for (int i = 0; i <= N; i++){
hashList[i].key = " ";
hashList[i].value = -1;
hashList[i].used = false;
}
for(int i = 0; i <N; i++){
cout<<hashList[i].value<<endl;
}
return hashList;
}
You iterate through one element too many on creation:
for (int i = 0; i <= N; i++){
Shoule be
for (int i = 0; i < N; i++){
It's because with arrays being 0-based, you can't access the element N of an array of the size N, only N-1, but in return also element 0.
Also, to make the code clearer and less error prone, you could use std::array instead of a pure C style array, or even an std::vector to be able to loop through them range based. You might also rething your use of new which should be avoided in most cases. If you don't really need that, I'd change the function to
std::vector<HashEntry> initHashList(int N) {
std::vector<HashEntry> hashList(N, { "", false, -1, }); //Creating vector of N elements
for (const HashEntry& entry : hashList) { //Iterating through the elements
std::cout << entry.value << std::endl;
}
return hashList;
}
I hope this makes it clearer how you can approach such a problem.
This way of creating the vector and looping through it avoids the potential access errors and is easier to read, imo. For more information, search for std::vector, its constructors, and range-based loops.

C++ Array comparison and printing difference

The thing i want to do is compare two arrays, A and B, and post numbers from array B that doesn't appear in array A.
http://pastebin.com/u44DKsWf My full code.
Problem starts at line 42 i think.
int writingPosition = 1;
for (int c = 1; c<=firstArrayLength; c++)
{
for(int z = 1; z>secondArrayLength; z++)
{
if (firstArray[c] != secondArray[z])
{
thirdArray[writingPosition] = secondArray[z];
writingPosition++;
}
if (firstArray[c] == secondArray[z])
{
thirdArray[c] == '0'; // NEED FIXING I GUESS
}
}
}
The idea is that i mark numbers that dont fit my task as '0', so later on i can print array while ignoring 0.
Thank you!
You could use binary_search from algorithm module from C++ Standard Library.
Note this works with std::vector aswell.
Live demo
#include <array>
#include <iostream>
#include <algorithm>
int main()
{
std::array<int, 3> firstArray { 1, 3, 5 }; // stack based array like int[3]
std::array<int, 3> secondArray { 2, 3, 4 };
// Sort first array to be able to perform binary_search on it
std::sort(firstArray.begin(), firstArray.end());
for (const auto secondArrayItem : secondArray)
{
// Binary search is a very efficient way of searching an element in a sorted container of values
if (std::binary_search(firstArray.begin(), firstArray.end(), secondArrayItem) == false)
{
std::cout << "Item " << secondArrayItem << " does not exist in firstArray" << std::endl;
}
}
return 0;
}
Correction to your code should be somewhat like :
int writingPosition = 1;
for (int c = 1; c<=firstArrayLength; c++)
{
for(int z = 1; z<=secondArrayLength; z++)
{
if (firstArray[c] != secondArray[z])
{
thirdArray[writingPosition] = secondArray[z];
writingPosition++;
}
if (firstArray[c] == secondArray[z])
continue;
}
}
On a side note : Prefer using 0 as the base index for arrays.
There are many things wrong with your code.
Arrays of size s always range from 0 to s-1, so in your case you should use
for(int g = 0; g<50; g++)
i.s.o.
for(int g = 0; g<=50; g++)
and similar for the other arrays
Secondly, you fill the third array with char elements, and then compare them to int
thirdArray[c] == '0';
and later
if(thirdArray[g] != 0)
Either use '0' or 0 both times, but don't mix them up.
But the general algorithm doesn't make much sense either, you're overriding third array both based on index c as index z.
Also the range on z makes little sense.
(I assume this is homework or at least you're trying to study, so won't simply give a solution)
why don't you store the numbers that doesn't exist in a string and then you print the string from cout? this is how you can do this:
string output = "";
bool isFound = false;
for (int c = 1; c<=secondArrayLength; c++)
{
isFound = false;
for(int z = 1; z>firstArrayLength; z++)
{
if (secondArray[c] == firstArray[z])
{
isFound = true;
}
}
if(!isFound)
output+=(secondArray[c].str()+" ");
}
cout<<output;
try this it must work fine

Applying heuristic to recursive backtracking

Searched for other problems -- and there are similar ones, but none that deal with this particular heuristic.
I have working code for a problem which asks to take a vector into some function, determine whether any values in that vector sum up to a given target value, and then returns whether it does or not (boolean). This is simple.
I have to use the backtracking heuristic supplied to create this function (below), which is working correctly in principle. I have to ensure that my function is not generating combinations which have been generated before (ABC is the same as BAC, for instance). How do I prevent my code from doing this? I cannot change the parameters going into the function (so the function prototype has to remain as it is below), but wrapper or helper functions are OK.
Here is the heuristic:
bool Solve(configuration conf) {
if (no more choices) // BASE CASE
return (conf is goal state);
for (all available choices) {
try one choice c;
// recursively solve after making choice
ok = Solve(conf with choice c made);
if (ok) return true;
else unmake choice c;
}
return false; // tried all choices, no soln found
}
My code:
bool CanMakeSum(Vector<int> & nums, int targetSum) {
if (nums.isEmpty()) {
cout << "you've reached the target sum" << endl;
return true;
} else {
for (int i = 0; i < nums.size(); i++) {
element = nums[i];
Vector<int> rest = nums;
cout << "list the subset: " << listSubset(rest) << endl;
rest.removeAt(i);
// try one
int new_target_sum = targetSum - element;
CanMakeSum(rest, new_target_sum);
if (new_target_sum == 0) {
return true;
} else {
new_target_sum = targetSum + element;
}
}
}
return false;
}
string listSubset(Vector<int> &partial_solution) {
string solution = " ";
for (int i = 0; i < partial_solution.size(); i++) {
solution += IntegerToString(partial_solution[i]) + " ";
}
return solution;
}
You could introduce ordering in choosing elements. For example after choosing ith element you cannot choose any element with index less than i. Change required in code is that after choosing ith element you need to remove all elements from index 0 to i.