I have two arrays of data type double - called array1[10] and array2[8]. I am required to search for array2 inside array1 at each element using a linear search function. The function declaration is
string linSearch (double array1[10], double array2[8]);
If array2 is found inside array1 then I need to print out the index of where it is found in array1. If its not found I need the output to be "NA". This output must be a delimited-comma- string.
eg.
//given the two arrays:
array1={1.1,1.2,6,7,3.5,2,7,8.8,9,23.4}
array2={6,45,2,7,1.1,5,4,8.8}
//after the linear search completes, the output must be the index in which //array2 is found in array1. if its not found, then it must be NA:
2,NA,5,6,0,NA,NA,7
So far I have the code that follows. Its my first time working with arrays and I am still having difficulties grasping the concept- like once I define the function how do I even call it in the main program?! anyway..the function definition I have (excluding the main program) is:
string linSearch (double array1[10], double array2[8])
{
int index1 = 0;
int index2 =0;
int position =-1;
bool found = false;
while (index1<10 && !found && index2<8)
{
if array1[index1] == array2[index2])
{
found = true;
position = index1;
}
index1++;
index2++;
}
return position;
}
I am EXTREMELY confused about searching for one array in the other and how to output the delimited list as well as how to connect it to my main program. Any help would be GREATLY appreciated. Thanks!
#include <iostream>
using namespace std;
string linSearch(double array1[10], double array2[8])
{
string result = "";
bool found;
for (int j = 0; j < 8; j++)
{
if(j > 0)
result.append(", ");
found = false;
for (int i = 0; i < 10; i++){
if (array1[i] == array2[j]) {
result.append(to_string(i));
found = true;
}
}
if(!found)
result.append("NA");
}
return result;
}
int main(){
double a1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double a2[8] = {11, 25, 3, 41, 5, 6, 7, 8};
cout << linSearch(a1, a2) << endl;
return 0;
}
You are not searching one array inside the other. You are searching for elements from one array in a second array. If you are using a linear search and if you do not want to sort the array, you need 2 nested loops to do that. One for each element in the second array, and one to find that element in the first array.
Keep things simple and start with finding the position of a single element in one array. Because you are comparing doubles, you should not compare them with ==. Next you just need a function that calls the first for each element in the second array:
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
void index_to_string(const std::vector<double>& v,double e,std::ostream& out){
auto it = std::find_if(v.begin(),
v.end(),
[e](const double& x) {
return std::abs(e-x) < 1e-8;
}
);
if (it == v.end()) {
out << "NA";
} else {
out << (it - v.begin());
}
}
void all_indices_to_string(const std::vector<double>& v1,const std::vector<double>& v2,std::ostream& out){
if (v1.size() == 0 || v2.size()==0) return;
index_to_string(v1,v2[0],out);
for (size_t i=1;i<v2.size();++i){
out << ",";
index_to_string(v1,v2[i],out);
}
}
int main() {
double array1[] ={1.1,1.2,6,7,3.5,2,7,8.8,9,23.4};
double array2[] ={6,45,2,7,1.1,5,4,8.8};
all_indices_to_string(
std::vector<double>(std::begin(array1),std::end(array1)),
std::vector<double>(std::begin(array2),std::end(array2)),
std::cout
);
}
Output:
2,NA,5,3,0,NA,NA,7
In your example of arrays and the expected output
//given the two arrays:
array1={1.1,1.2,6,7,3.5,2,7,8.8,9,23.4}
array2={6,45,2,7,1.1,5,4,8.8}
and
2,NA,5,6,0,NA,NA,7
^
there is a typo. The output should be
2,NA,5,3,0,NA,NA,7
^
because the number 7 is found in the third position of the array array1.
Here you are.
#include <iostream>
#include <string>
#include <sstream>
std::string linearSearch( const double a1[], size_t n1, const double a2[], size_t n2 )
{
std::ostringstream os;
for ( size_t i = 0; i < n2; i++ )
{
if ( i != 0 ) os << ',';
size_t j = 0;
while ( j < n1 && a2[i] != a1[j] ) ++j;
if ( j == n1 ) os << "NA";
else os << j;
}
return os.str();
}
int main()
{
double a1[] = { 1.1, 1.2, 6, 7, 3.5, 2, 7, 8.8, 9, 23.4 };
const size_t N1 = sizeof( a1 ) / sizeof( *a1 );
double a2[] = { 6, 45, 2, 7, 1.1, 5, 4, 8.8 };
const size_t N2 = sizeof( a2 ) / sizeof( *a2 );
std::cout << linearSearch( a1, N1, a2, N2 ) << '\n';
return 0;
}
The program output is
2,NA,5,3,0,NA,NA,7
Related
I'm a newbie programmer trying to solve the following problem: I need to initialize a matrix with all the combinations from a array of objects so I can extract the values and perform certain calculations afterwards for each set of objects, in this case I used a struct for X, Y coordinates to represent the data. The entire data set consists on 35 coordinates, for now I'm dealing with as few data as possible, an input array of size 4, meaning 4 (n) combinations of 3 (r) objects. The program seems to work fine until I print the 4x3 matrix and find out I was only able to store the first combination, and after tinkering with the program I got stuck since I didn't code this program entirely. Could someone suggest me a solution so the matrix gets initialized correctly? I'd highly appreciate it.
#include <iostream>
#define n 4 //data set size
#define r 3 // combination size
using namespace std;
struct Points{
double x, y;
};
void Combination(Points Data [n], Points CombinationMatrix [][r],int start, int currLen, bool check []) {
// Return if the currLen is more than the required length.
if(currLen > r)
return;
// If currLen is equal to required length then add the sequence.
else if (currLen == r){
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
if (check[i] == true){
CombinationMatrix[i][j] = Data[j];
}
}
}
return;
}
// If start equals to len then return since no further element left.
if (start == n)
{
return;
}
// For every index we have two options.
// First is, we select it, means put true in check[] and increment currLen and start.
check[start] = true;
Combination(Data, CombinationMatrix, start + 1, currLen + 1, check);
// Second is, we don't select it, means put false in check[] and only start incremented.
check[start] = false;
Combination(Data, CombinationMatrix, start + 1, currLen, check);
}
int main()
{
Points Data [n] = { {1, 1} , {2, 7} , {3, 6} , {4, 13}}; //, {5,9} ,
//{6, 7} , {7, 12} , {8, 14} , {9, 17} , {10, 23} ,
//{11,28} , {12, 63} , {13, 45} , {14, 68} , {15, 32} ,
//{16,98} , {17, 115} , {18, 116}, {19, 112}, {20, 115},
//{21, 88} , {22, 86} , {23, 106}, {24, 136}, {25, 158},
//{26, 198}, {27, 128} , {28, 187}, {29, 112}, {30, 149},
//{31, 279}, {32, 224} , {33, 222}, {34, 260}, {35, 166}};
Points CombinationMatrix [n][r];
bool check[n];
for(int i = 0; i < n; i++){
check[i] = false;
}
Combination(Data, CombinationMatrix, 0, 0, check);
for (int i = 0; i < n; i++){
for(int j = 0; j < r; j++){
cout << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << " ";
}
cout << endl;
}
return 0;
}
I suggest that you have a look at std::prev_permutation.
If you have a std::vector<Data> points, then you can get all permutations via
do {
// Do something with the current permutation
for ( int i = 0; i < points.size(); ++i ) {
std::cout << points[i] << ' ';
}
std::cout << '\n';
} while ( std::prev_permutation(points.begin(),points.end()) );
Since this gives you points.size()! (Factorial) combinations, I would not store it in a matrix unless you have a very good reason to do so.
std::prev_permutation uses the lexicographically smaller. Thus, you need to overload the operator < for Data.
inline bool operator< (const Data& lhs, const Data& rhs){
/* do actual comparison e.g.*/
return ((lhs.x <rhs.x) && (lhs.y <rhs.y));
}
The following generates combinations of your array using std::prev_permutation.
Note that this is accomplished by using a bool vector that starts with r of those bits set to true, and on each iteration the bits in the bool vector have their positions changed.
The following uses std::vector<Point> instead of hard-coded arrays. This adds flexibility in that you don't have to guess how many combinations will be generated.
#include <iostream>
#include <vector>
#include <algorithm>
struct Points {
double x, y;
};
std::vector<std::vector<Points>> Combination(std::vector<Points>& Data, int n, int r)
{
// The returned vector
std::vector<std::vector<Points>> retVect;
// Array of bools
std::vector<bool> bits(n);
// Fill the first r positions of the bool array to true
std::fill(bits.begin(), bits.begin() + r, true);
// Our temporary 1 dimensional array we use when building a single combination
std::vector<Points> tempV;
do
{
tempV.clear();
for (int i = 0; i < n; ++i)
{
// for each item in the bool array that's true, add that to the vector
if (bits[i])
tempV.push_back(Data[i]);
}
// add this combination to vector of combinations
retVect.push_back(tempV);
// rearrange the bits
} while (std::prev_permutation(bits.begin(), bits.end()));
return retVect;
}
int main()
{
std::vector<Points> Data = { {1, 1}, {2, 7}, {3, 6}, {4, 13} };
auto CombinationMatrix = Combination(Data, 4, 3);
for (size_t i = 0; i < CombinationMatrix.size(); i++) {
for (size_t j = 0; j < CombinationMatrix[i].size(); j++) {
std::cout << "{" << CombinationMatrix[i][j].x << "," << CombinationMatrix[i][j].y << "} "; }
std::cout << std::endl;
}
}
Output:
{1,1} {2,7} {3,6}
{1,1} {2,7} {4,13}
{1,1} {3,6} {4,13}
{2,7} {3,6} {4,13}
Two quantities u and v are said to be at right angles if
nuv = u1v1 + u2v2 + u3v3 + u4v4 +………… + unvn = 0
Write a function that computes whether u and v are at right angles. You may use arrays if you wish. The function can assume that the vectors have the same dimension (n, say), but this number should be passed as a parameter to the function.
I have a few errors in my program. I'd appreciate some help, as I'm a beginner. The errors are telling me:
In function 'void function(int*,int*)'
cpp 26: error expected ';' before '}' token
cpp 29: error ;value required as left operand of assignment
#include <iostream>
using namespace std;
const int n = 5;
void function(int array[n],int array2[n]);
int main(){
int array[n] = {5, 3 , -4, 2, 8};
int array2[n] ={-7, -9, 5, 2, 9};
function(array, array2);
return 0;
}
void function(int array[n], int array2[n]){
int multiple;
for(int i=0; i <=5, i++)
{
(array[i]*array2[i]) + (array[i+1]*array2[i+1]) = multiple;
}
cout << multiple << endl;
}
Your for loop is malformed. You need to use < instead of <=, use n instead of 5, and use ; instead of ,.
Your assignment of multiple is backwards. The value on the right-side of the = operator is assigned to the variable on the left-side of =. You are trying to assign the value of multiple (which is uninitialized) to a dynamically computed value that has no explicit variable of its own. You should be assigning the computed value to multiple instead.
Also, you didn't follow the "this number [array dimensions] should be passed as a parameter to the function" requirement of your instructions.
Try this:
#include <iostream>
using namespace std;
const int n = 5;
void function(const int *array1, const int *array2, const int size);
int main()
{
int array1[n] = { 5, 3, -4, 2, 8};
int array2[n] = {-7, -9, 5, 2, 9};
function(array1, array2, n);
return 0;
}
void function(const int *array1, const int *array2, const int size)
{
int multiple = 0;
for(int i = 0; i < size; i++)
{
multiple += (array1[i] * array2[i]);
}
cout << multiple << endl;
}
Syntax error is where you are using the for loop in this fashion:
for(int i=0;i<=5,i++)
Use this instead:
for(int i=0; i <= 5; i++)
The function can assume that the vectors have the same dimension (n,
say), but this number should be passed as a parameter to the
function.
This function declaration
void function(int array[n],int array2[n]);
does not include a parameter that specifies the dimension of the arrays.
The above declaration is equivalent to
void function(int *array,int *array2);
because arrays passed by value are implicitly converted to pointers to their first elements.
There are a typo and a bug in this for statement
for(int i=0; i <=5, i++)
^^^^^^
There shall be
for ( int i=0; i < n; i++)
The variable multiple
int multiple;
is not initialized and this assignment
(array[i]*array2[i]) + (array[i+1]*array2[i+1]) = multiple;
does not have sense and has nothing common with the condition
nuv = u1v1 + u2v2 + u3v3 + u4v4 +………… + unvn = 0
It seems what you mean is the following
#include <iostream>
bool function( const int array[], const int array2[], size_t n )
{
long long int product = 0;
for ( size_t i = 0; i < n; i++)
{
product += array[i] * array2[i];
}
return product == 0;
}
int main()
{
const size_t N = 5;
int array[N] = { 5, 3 , -4, 2, 8 };
int array2[N] = { -7, -9, 5, 2, 9 };
std::cout << "array and array2 are "
<< (function(array, array2, N) ? "" : "not ")
<< "at right angles"
<< std::endl;
return 0;
}
These arrays
int array[N] = { 5, 3 , -4, 2, 8 };
int array2[N] = { -7, -9, 5, 2, 9 };
are not a right angles,
But these arrays
int array[N] = { 5, 3 , -4, 1, 9 };
int array2[N] = { -7, -9, 5, 1, 9 };
are at right angles. Try them.
Alternative: try the C++ way. Use std::array that knows it's length. Use algorithms provided by the standard library like std::inner_product.
#include <iostream>
#include <algorithm>
#include <array>
#include <numeric>
int main()
{
using arr_t = std::array<int,5>;
arr_t arr1 = {5, 3 , -4, 2, 8};
arr_t arr2 = {-7, -9, 5, 2, 9};
int mult = std::inner_product( begin(arr1), end(arr1), begin(arr2), 0,
std::plus<>(), std::multiplies<>() );
std::cerr << mult << "\n";
}
Problem: I want to get an array A[6] = {6, 5, 4, 3, 2, 1} to be A[6] = {5, 3, 1, 1, 1, 1}. In other words - "delete" every second value starting with 0th and shift all other values to the left.
My Attempt:
To do that I would use this code, where a - length of the relevant part of an array A (the part with elements that are not deleted), ind - index of the value that I want to delete.
for (int j = ind; j < n; j++)
A[j] = A[j+1];
However, I couldn't get this to work, using the code like that:
void deleting(int A[], int& a, int ind){
for (int j = ind; j < a; j++)
A[j] = A[j+1];
a--;
}
int A[6] = {6, 5, 4, 3, 2, 1};
a = 6
for (int i = 0; i < a; i+=2)
deleting(A, a, i);
After running this code I was getting A[6] = {5, 4, 2, 1, 1507485184, 1507485184}. So, it deleted the elements at indexes 0, 3. Why did it delete the 3rd index?
There are two ways to do this:
walk the array, copying the last n-i elements forward one place for every even i, or
figure out the eventual state and just go straight to that. The eventual state is the first n/2 places are array[i]=array[2*i + 1], and the last n/2 places are just copies of the last element.
The first method is what you asked for, but it does multiple redundant copy operations, which the second avoids.
As for your implementation problems, examine what happens when j=n-1, and remember A[n] is not a valid element of the array.
I suggest making the copy-everything-forward operation its own function anyway (or you can just use memcpy)
For these kinds of problems (in-place array manipulation), it's a good idea to just keep an index or pointer into the array for where you are "reading" and another where you are "writing." For example:
void odds(int* a, size_t len) {
int* writep = a;
int* readp = a + 1;
while (readp < a + len) { // copy odd elements forward
*writep++ = *readp;
readp += 2;
}
while (writep < a + len - 1) { // replace rest with last
*writep++ = a[len - 1];
}
}
Just for kicks, here is a version which doesn't use a loop:
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <utility>
#include <initializer_list>
template <typename T, std::size_t Size>
std::ostream& print(std::ostream& out, T const (&array)[Size]) {
out << "[";
std::copy(std::begin(array), std::end(array) -1,
std::ostream_iterator<T>(out, ", "));
return out << std::end(array)[-1] << "]";
}
template <std::size_t TI, std::size_t FI, typename T, std::size_t Size>
bool assign(T (&array)[Size]) {
array[TI] = array[FI];
return true;
}
template <typename T, std::size_t Size,
std::size_t... T0>
void remove_even_aux(T (&array)[Size],
std::index_sequence<T0...>) {
bool aux0[] = { assign<T0, 2 * T0 + 1>(array)... };
bool aux1[] = { assign<Size / 2 + T0, Size - 1>(array)... };
}
template <typename T, std::size_t Size>
void remove_even(T (&array)[Size]) {
remove_even_aux(array, std::make_index_sequence<Size / 2>());
}
int main() {
int array[] = { 6, 5, 4, 3, 2, 1 };
print(std::cout, array) << "\n";
remove_even(array);
print(std::cout, array) << "\n";
}
If C++ algorithms are an option, I tend to prefer them by default:
auto *const end_A = A + (sizeof(A)/sizeof(*A));
auto *new_end = std::remove_if(
A, end_A,
[&A](int const& i) { return (&i - A) % 2 == 0; });
// Now "erase" the remaining elements.
std::fill(new_end, end_A, 0);
The std::remove_if algorithm simply moves the elements that do not match the predicate (in our case, test if the address is MOD(2)=0), and std::moves them to the end. This is in place. The new "end" is return, which I then indexed over and set the elements to 0.
So if it has to be an array the solution would be like this:
void deleting(int A[size], int size){
for (int i = 0; i < size / 2; i++)
A[i] = A[2 * i + 1];
for (int i = size / 2; i < size; i++)
A[i] = A[size / 2];
}
You first loop through first half of the array "moving" every second number to the front, and then you loop through the rest filling it with the last number.
For a more versatile version of other's answers:
#include <iostream>
template<typename InputIt, typename T>
void filter(InputIt begin, InputIt end, T const& defaultvalue)
{
InputIt fastforward = begin;
InputIt slowforward = begin;
fastforward++; // starts at [1], not [0]
while (fastforward < end)
{
*slowforward = *fastforward;
++slowforward;
++ ++fastforward;
}
while (slowforward < end) // fill with default value
{
*slowforward++ = defaultvalue;
}
}
int main()
{
int A[6] = {6, 5, 4, 3, 2, 1};
std::cout << "before: ";
for (auto n : A)
std::cout << n << ", ";
std::cout << std::endl;
filter(A, A+6, 1);
std::cout << "after: ";
for (auto n : A)
std::cout << n << ", ";
std::cout << std::endl;
}
Outputs:
before: 6, 5, 4, 3, 2, 1,
after: 5, 3, 1, 1, 1, 1,
And this works with std::array<bool>, std::vector<std::string>, std::unordered_set<void*>::iterator, etc.
The common way of doing this would be keeping two indices: one to the entry you're modifying and the other to the entry you intend to process
const auto size = sizeof(A) / sizeof(int);
// N.b. if size == 1 entire array is garbage
int i = 0;
for (int nv = 1; nv < size; ++i, nv += 2)
A[i] = A[nv];
--i;
// Significative array is now [0;N/2[, fill with last now
for (int j = i + 1; j < size; ++j)
A[j] = A[i];
This grants an in-place-modify fashion.
you can combine std::remove_if and std::fill to do this
example code:
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
int A[6] = {6, 5, 4, 3, 2, 1};
auto endX = std::remove_if(std::begin(A),std::end(A),[&A](const int& i){return (&i-A)%2==0;});
if(endX!=std::begin(A))//in case nothing remained, although not possible in this case
std::fill(endX,std::end(A),*(endX-1));
//else /*something to do if nothing remained*/
for(auto a : A)std::cout<<a<<' ';
}
It seems to be a simply exercise, but something doesn't work with the following qsort algorithmus. The struct abcSort correctly shows all assigned values. Unfortunately, the qsort is not sorting anything.
typedef int(*compfn)(const void*, const void*);
struct ABCSort
{
int svSort[10];
string itemSort[10];
};
struct ABCSort abcSort;
int compare(struct ABCSort*, struct ABCSort*);
void mainSort()
{
for (int i = 0; i < 10; i++)
{
abcSort.svSort[i] = 100 - i;
abcSort.itemSort[i] = arrayREAD[i][2];
}
qsort( (void*)&abcSort, 10, sizeof(struct ABCSort), (compfn)compare );
}
int compare(struct ABCSort *elem1, struct ABCSort *elem2)
{
if (elem1->svSort< elem2->svSort)
return -1;
else if (elem1->svSort > elem2->svSort)
return 1;
else
return 0;
}
You have build two arrays of integer and strings and you want to sort them by the numbers, keeping the initial pairing. That's the first problem, you should have created one array of structs, each struct containg a number and a string and a function that compares the integer member of that struct to obtain the sort order.
You also tagged this question as C++ but you are using qsort, arrays and function pointers like C, so I'll present two complete C programs that solve your problem.
Let's see, using an array of structs, what your code could be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 6
#define CMAX 15
typedef int(*cmp_fn)(const void*, const void*);
typedef struct {
int num;
char str[CMAX];
} numABC;
int comp_struct(const numABC *lhs, const numABC *rhs ) {
if ( lhs->num < rhs->num )
return -1;
if ( lhs->num > rhs->num )
return 1;
return 0;
}
int main(void) {
numABC myArray[MAX] = { {6, "cat"}, {4, "dog"}, {8, "panter"},
{2, "red fish"}, {1, "hawk"}, {6, "snake"} };
int i;
// sort the array of structs by int member
qsort(myArray, MAX, sizeof(numABC), (cmp_fn)comp_struct);
// print out the sorted array
printf("\nSort by numbers:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",myArray[i].num,myArray[i].str);
}
return 0;
}
If you want to use this code, but you have a couple of arrays instead, one option is to convert those arrays:
int nums[MAX] = {6,4,8,2,1,3};
char str[MAX][CMAX] = {"cat","dog","panter","red fish","hawk","snake"};
int i;
// create the array of structs from the two arrays
numABC myArray[MAX];
for ( i = 0; i < MAX; ++i ) {
myArray[i].num = nums[i];
strcpy(myArray[i].str, str[i]);
}
Another option to sort two different arrays (mantaining the pairing or alignment between the two) is to use a more complicated method which consists in sorting an array of indeces instead. to keep the relationships between the two original arrays I'll have to use global variables which can be accessed inside the compare function(s). Once the indeces are sorted, the original arrays are changed accordingly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 6
#define CMAX 15
const size_t I_DIM = MAX * sizeof(int);
const size_t SS_DIM = MAX * sizeof(char*);
const size_t S_DIM = MAX * CMAX;
// global variables needed to perform comparisons
int *pg_int;
char **pg_str;
typedef int(*cmp_fn)(const void*, const void*);
int comp_num(const int *lhs, const int *rhs ) {
if (pg_int[*lhs] < pg_int[*rhs])
return -1;
if (pg_int[*lhs] > pg_int[*rhs])
return 1;
return 0;
}
int comp_str(const int *lhs, const int *rhs ) {
return strcmp(pg_str[*lhs],pg_str[*rhs]);
}
int main(void) {
int nums[MAX] = {6,4,8,2,1,3};
char str[MAX][CMAX] = {"cat","dog","panter","red fish","hawk","snake"};
int i;
// create an array of indeces
int index[MAX];
for ( i = 0; i < MAX; ++i ) {
index[i] = i;
}
// set global copies
pg_int = malloc(I_DIM);
memcpy(pg_int,nums,I_DIM);
pg_str = malloc(SS_DIM);
pg_str[0] = malloc(S_DIM);
memcpy(pg_str[0],str[0],S_DIM);
for ( i = 1; i < MAX; i++ ) {
pg_str[i] = pg_str[0] + i * CMAX;
}
// sort the indeces ordering by ints
qsort(index, MAX, sizeof(int), (cmp_fn)comp_num);
//update the two arrays
for ( i = 0; i < MAX; ++i ) {
nums[i] = pg_int[index[i]];
strcpy(str[i],pg_str[index[i]]);
}
// print out sorted couples
printf("Sort by numbers:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",nums[i],str[i]);
}
// sort the indeces ordering by strings
qsort(index, MAX, sizeof(int), (cmp_fn)comp_str);
//update the two arrays
for ( i = 0; i < MAX; ++i ) {
nums[i] = pg_int[index[i]];
strcpy(str[i],pg_str[index[i]]);
}
// print out sorted couples
printf("\nSort by strings:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",nums[i],str[i]);
}
free(pg_int);
free(pg_str[0]);
free(pg_str);
return 0;
}
The output (sorry for the silly example) is:
Sort by numbers:
1 hawk
2 red fish
3 snake
4 dog
6 cat
8 panter
Sort by strings:
6 cat
4 dog
1 hawk
8 panter
2 red fish
3 snake
If you want to accomplish the same task in C++ you should take advantage of the Standard Library and use std::vector as a container and std::sort as algorithm:
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
using std::string;
using std::cout;
struct numABC {
double num;
string str;
// instead of a compare function I can overload operator <
friend bool operator<( const numABC &lhs, const numABC &rhs ) {
return lhs.num < rhs.num;
}
};
// or use a lambda
auto cmp_str = []( const numABC &lhs, const numABC &rhs ) -> bool {
return lhs.str < rhs.str;
};
int main() {
vector<numABC> my_data = { {3.6, "cat"}, {5.7, "dog"}, {7.1, "panter"},
{0.2, "red fish"}, {1.8, "hawk"}, {1.1, "snake"}};
std::sort(my_data.begin(), my_data.end());
std::cout << "Sort by numbers:\n";
for ( auto & s : my_data ) {
std::cout << s.num << ' ' << s.str << '\n';
}
std::sort(my_data.begin(), my_data.end(), cmp_str);
// passing a lambda to specify how to compare ^^
std::cout << "Sort by strings:\n";
// if you don't like c++11 range for:
for ( int i = 0; i < my_data.size(); ++i ) {
std::cout << my_data[i].num << ' ' << my_data[i].str << '\n';
}
return 0;
}
Note that I have initialized my_data as a vector of objects of type numABC. If you have to start from two arrays, you can create the vector like this:
vector<double> nums = {3.6, 5.7, 7.1, 0.2, 1.8, 1.1};
vector<string> str = {"cat", "dog", "panter", "red fish", "hawk", "snake"};
vector<numABC> my_data;
for ( int i = 0; i < nums.size(); ++i ) {
my_data.push_back(numABC{nums[i],str[i]});
}
After sorting, if you have to extract the two vectors again (instead of simply looping through my_data) you can do something like this:
for ( int i = 0; i < my_data.size(); ++i ) {
nums[i] = my_data[i].num;
str[i] = my_data[i].str;
}
Alternatively you could implement an algorithm similar to the one I used before and sort the two vectors nums and srt using an auxiliary vector of indeces:
vector<double> nums = {3.6, 5.7, 7.1, 0.2, 1.8, 1.1};
vector<string> str = {"cat", "dog", "panter", "red fish", "hawk", "snake"};
// create the vector of indeces
vector<int> idx(nums.size());
std::iota(idx.begin(),idx.end(),0); // fill the vector, require #include <numeric>
// thanks to the lambda variable capture you don't need globals
auto cmp_ind = [ &nums ]
( const int &lhs, const int &rhs ) -> bool {
return nums[lhs] < nums[rhs];
};
// sort indeces
std::sort(idx.begin(), idx.end(),cmp_ind);
// create sorted arrays. It could be done in place but it's more difficult
vector<double> sorted_nums(nums.size());
vector<string> sorted_str(str.size());
for ( int i = 0; i < nums.size(); ++i ) {
sorted_nums[i] = nums[idx[i]];
sorted_str[i] = str[idx[i]];
}
std::cout << "Sort by numbers:\n";
for ( int i = 0; i < nums.size(); ++i ) {
std::cout << sorted_nums[i] << ' ' << sorted_str[i] << '\n';
}
You seem to intend to sort an array of integers (your compare function looks like that). But what you are actually handing over to qsort for sorting is a pointer to a structure that holds, among other stuff, an array.
So what you are actually trying to sort is one single struct ABCSort which is initialized and 9 other, uninitialized structures. This must fail.
Your qsort line should look like so:
qsort ((void*)&(abcsort.svsort), 10, sizeof (int), (compfn)compare);
Also, you should change the compare function so that it takes and works on two pointers to integers:
int compare (int * e1, int * e2) {
return *e1 - *e2;
}
EDIT:
After you have explained a bit better what you want, have a look at the following:
typedef int(compfn)(const void, const void*);
#define MAXCARS 5
struct car {
int sortKey;
double displacement;
char name[15]; /* Note I have decided this should be C */
};
/* This time we have an array of structs */
struct car cars [MAXCARS] = {
{ 0, 1.9, "BMW" },
{ 0, 6.3, "Audi" },
{ 0, 0.5, "Fiat" },
{ 0, 25.0, "Humvee" },
{ 0, 0.05, "Minibike" }
};
int compare(struct car*, struct car*);
void main(int argc, char *argv []) {
int i;
for (i = 0; i < MAXCARS; i++)
cars[i].sortKey = 100 - i;
qsort((void *)&cars, MAXCARS, sizeof(struct car), (compfn)compare);
}
/* Note we are comparing struct car-s in here, based on their displacement */
int compare(struct car *elem1, struct car *elem2) {
return elem1->sortKey - elem2->sortKey;
}
Pseudo Code:
int arr[ 5 ] = { 4, 1, 3, 2, 6 }, x;
x = find(3).arr ;
x would then return 2.
The syntax you have there for your function doesn't make sense (why would the return value have a member called arr?).
To find the index, use std::distance and std::find from the <algorithm> header.
int x = std::distance(arr, std::find(arr, arr + 5, 3));
Or you can make it into a more generic function:
template <typename Iter>
size_t index_of(Iter first, Iter last, typename const std::iterator_traits<Iter>::value_type& x)
{
size_t i = 0;
while (first != last && *first != x)
++first, ++i;
return i;
}
Here, I'm returning the length of the sequence if the value is not found (which is consistent with the way the STL algorithms return the last iterator). Depending on your taste, you may wish to use some other form of failure reporting.
In your case, you would use it like so:
size_t x = index_of(arr, arr + 5, 3);
Here is a very simple way to do it by hand. You could also use the <algorithm>, as Peter suggests.
#include <iostream>
int find(int arr[], int len, int seek)
{
for (int i = 0; i < len; ++i)
{
if (arr[i] == seek) return i;
}
return -1;
}
int main()
{
int arr[ 5 ] = { 4, 1, 3, 2, 6 };
int x = find(arr,5,3);
std::cout << x << std::endl;
}
The fancy answer:
Use std::vector and search with std::find
The simple answer
Use a for loop
If the array is unsorted, you will need to use linear search.
#include <vector>
#include <algorithm>
int main()
{
int arr[5] = {4, 1, 3, 2, 6};
int x = -1;
std::vector<int> testVector(arr, arr + sizeof(arr) / sizeof(int) );
std::vector<int>::iterator it = std::find(testVector.begin(), testVector.end(), 3);
if (it != testVector.end())
{
x = it - testVector.begin();
}
return 0;
}
Or you can just build a vector in a normal way, without creating it from an array of ints and then use the same solution as shown in my example.
int arr[5] = {4, 1, 3, 2, 6};
vector<int> vec;
int i =0;
int no_to_be_found;
cin >> no_to_be_found;
while(i != 4)
{
vec.push_back(arr[i]);
i++;
}
cout << find(vec.begin(),vec.end(),no_to_be_found) - vec.begin();
We here use simply linear search. At first initialize the index equal to -1 . Then search the array , if found the assign the index value in index variable and break. Otherwise, index = -1.
int find(int arr[], int n, int key)
{
int index = -1;
for(int i=0; i<n; i++)
{
if(arr[i]==key)
{
index=i;
break;
}
}
return index;
}
int main()
{
int arr[ 5 ] = { 4, 1, 3, 2, 6 };
int n = sizeof(arr)/sizeof(arr[0]);
int x = find(arr ,n, 3);
cout<<x<<endl;
return 0;
}
You could use the STL algorithm library's find function provided
#include <iostream>
#include <algorithm>
using std::iostream;
using std::find;
int main() {
int length = 10;
int arr[length] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int* found_pos = find(arr, arr + length, 5);
if(found_pos != (arr + length)) {
// found
cout << "Found: " << *found_pos << endl;
}
else {
// not found
cout << "Not Found." << endl;
}
return 0;
}
There is a find(...) function to find an element in an array which returns an iterator to that element. If the element is not found, the iterator point to the end of array.
In case the element is found, we can simply calculate the distance of the iterator from the beginning of the array to get the index of that element.
#include <iterator>
using namespace std;
int arr[ 5 ] = { 4, 1, 3, 2, 6 }
auto it = arr.find(begin(arr), end(arr), 3)
if(it != end(arr))
cerr << "Found at index: " << (it-begin(arr)) << endl;
else
cerr << "Not found\n";