I am trying to figure out how to bubble sort a 2D string array. I am currently stuck trying to figure out why my program isnt sorting the strings. I spsupect it could be possible that something is wrong with void swap. I feel somehting with the 2D array needs to be put in there. I am not very sure I just learned how to create bubble sorting algorithms.
#include
using namespace std;
const int SIZE = 2;
const int ROWS = 2;
void bubbleSort(string values[][SIZE]);
void swap(int &, int &);
int main ()
{
string values[ROWS][SIZE] = {{"A23", "A12"}, {"name1", "name2"}};
cout << "Unsorted Values: " << endl;
for(auto element : values)
cout << element << " ";
cout << endl;
cout << "Sorted Values" << endl;
bubbleSort(values);
for (auto element:values)
cout << element << " ";
return 0;
}
void bubbleSort(string values[][SIZE])
{
int maxElement;
int index;
for (maxElement = SIZE - 1; maxElement > 0; maxElement--)
{
for( index = 0; index < maxElement; index++)
{
if (values[0][index] > values[0][index + 1])
{
swap(values[0][index], values[0][index + 1]);
}
}
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
Your program prints out the adresses because your print loop iterate each entry of your string 2D array. Consequently, every entry is an array. So arr holds the pointer to the first element of the array.
You only need a nested loop to print out the values of the single elements:
for (auto row : values)
for (int i = 0; i < SIZE; i++)
std::cout << row[i] << " ";
Furthermore, there is no need to implement an own swap function. Just use std::swap(T&,T&)
But i assume that you want to achieve a multi array sort. Then you should use a simple struct to represent an entity instead of multiple arrays and implement a operator to compare two entities. I suggest to use a range based container too. Then you can take advantage of the standard sort functions.
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Entry
{
string id;
string name;
bool operator<(const Entry& comp)
{
return id < comp.id;
}
};
int main()
{
auto print = [](const vector<Entry>& vec)
{
for (auto& el : vec)
{
cout << el.id << "->" << el.name << "\t";
}
};
vector<Entry> values { {"A23","name1" }, {"A12", "name2"} };
cout << "Unsorted Values: " << endl;
print(values);
cout << endl;
std::sort(values.begin(), values.end());
cout << "Sorted Values" << endl;
print(values);
return 0;
}
Prints out:
Unsorted Values:
A23->name1 A12->name2
Sorted Values:
A12->name2 A23->name1
Related
Why doesn't the range-based loop with auto display addresses?
The for loop:
for (int i = 0; i < s; i++) cout << &ar[i] << endl;
works normally, but range-based loop with auto doesn't:
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int ar[] = { 12,-23,0,1,2 };
int s = sizeof(ar) / sizeof(int);
int * m = &ar[0];
sort(&ar[0], m+ s);
for (auto m : ar)
cout << m << endl;
cout << endl;
for (auto m : ar)
cout << &m << endl;
cout << endl;
for (int i = 0; i < s; i++)
cout << &ar[i] << endl;
system("pause");
}
With the auto m you are passing (array) elements by value / copy in your range based loop:
for (auto m : ar) { // pass by value
std::cout << &m << ' '; // prints addresses of copies, not the actual array elements
}
This means m becomes a copy of an array element in each iteration and has its own address in the memory.
If you passed by reference (auto& m) or a reference to const (const auto& m), you would observe the expected results:
for (auto& m : ar) { // pass by reference
std::cout << &m << ' '; // prints addresses of the actual array elements
}
Now m is an actual array element and &m represents the array element address as expected.
I want to increase the size of the array of string after declaring it once, how can it be done. I need to increase the size in the following code..
#include<iostream>
using namespace std;
#include<string>
int main()
{
int n;
string A[] =
{ "vaibhav", "vinayak", "alok", "aman" };
int a = sizeof(A) / sizeof(A[0]);
cout << "The size is " << a << endl;
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
cout << "Enter the number of elements you want to add to the string"
<< endl;
cin >> n;
cout << "ok now enter the strings" << endl;
for (int i = a; i < n + a; i++)
{
cin >> A[i];
}
a = a + n;
A.resize(a); // THIS KIND OF THING
for (int i = 0; i < a; i++)
{
cout << A[i] << endl;
}
return 0;
}
Plain and simple: you cannot.
You can get a larger array, copy all your stuff over and use that instead. But why do all that, when there is a perfectly good class already there, doing it all for you: std::vector.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
// want to enter more?
sd::string more;
std::cin >> more;
A.push_back(more);
std::cout << "The size is " << A.size() << std::endl;
for(string s : A)
{
std::cout << s << std::endl;
}
return 0;
}
Convert your code over to use std::vector and this problem becomes much easier to solve.
#include<iostream>
#include<string>
#include<vector>
int main(){
int n;
std::vector<std::string> A = {"vaibhav", "vinayak", "alok", "aman"};
int a = A.size();
std::cout << "The size is " << a << std::endl;
//Prefer Range-For when just iterating over all elements
for(std::string const& str : A){
std::cout << str << std::endl;
}
std::cout << "Enter the number of elements you want to add to the string" << std::endl;
std::cin >> n;
std::cout << "ok now enter the strings" << std::endl;
for(int i = 0; i < n; i++ ) {
//emplace_back automatically resizes the container when called.
A.emplace_back();
std::cin >> A.back();
//If you're using C++17, you can replace those two lines with just this:
//std::cin >> A.emplace_back();
}
for(std::string const& str : A){
std::cout << str << std::endl;
}
return 0;
}
Also, don't use using namespace std;, since it leads to expensive to fix bugs and makes your code harder to read for other C++ programmers.
I want to increase the size of the array of string after declaring it
once, how can it be done.
It cannot be done. Use std::vector if the element count isn't known at compile time or can change dynamically. It even has a resize member function named exactly like the one in your code.
You cannot increase the size of a Raw Array, you could use an std::vecto<std::string> as this type of array can grow at runtime.
However, you could also create a class that will store an array of string and create your own implementation to resize the raw array. Which would be creating a bigger array and copying all the other values over, then setting the class array to the new array (or just return it)
This program is supposed to create three arrays of class object My_array. The first array is filled with random numbers. The second array is an exact copy of the first. The third array is entered by the user. The program checks to make sure that the first two arrays indeed equal each other and then it check to the hamming distance of the first and third array. The professor defines the hamming distance as each part off the array that is different.
My problem has been getting hamming to work. I actually have a hard time with operating overloading so I am surprised that works (well I have no errors showing in VS Studio) but not the hamming part. Any help would be appreciated. There are three files in order: main.cpp, my_array.cpp, and my_array.h. Function definitions and declarations were provided by professor. I am required to insert how each function operates.
#include "my_array.h"
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "How big of an array shall we work with? ";
cin >> size;
My_array a(size);
My_array b(size);
My_array c(size);
a.randomize(100);
b = a;
c.input();
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << "a != b: " << (a != b) << endl;
cout << "a == b: " << (a == b) << endl;
cout << "The hamming distance is: " << a.hamming(c);
return 0;
}
#include "my_array.h"
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <time.h>
// Constructor
My_array::My_array(int the_size)
{
array = NULL;
size = 0;
resize(the_size);
}
// Destructor.
My_array::~My_array()
{
empty();
}
// Copy constructor
My_array::My_array(My_array &data)
: size(data.size)
{
array = new int[size];
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
// Overloaded assignment operator.
My_array &My_array::operator=(My_array &data)
{
if (this != &data) {
resize(data.size);
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
else
cout << "Attempt to copy an object on itself. "
<< "Operation ignored." << endl;
return *this;
}
void My_array::input()
{
int j;
cout << "Please enter " << size << " numbers.\n";
for (int i = 0; i < size; i++)
{
cout << "Number " << i + 1 << ": ";
cin >> j;
array[i] = j;
}
}
void My_array::randomize(int limit)
{
srand(time(NULL));
for (int i = 0; i < size; i++)
array[i] = rand() % limit + 1;
}
bool My_array::operator ==(My_array &data)
{
if(this->size != data.size)
return false;
for (int i = 0; i <size; i++)
{
if (*this[i].array != data.array[i])
return false;
}
return true;
}
bool My_array::operator !=(My_array &data)
{
if (*this == data)
return false;
return true;
}
int My_array::hamming(My_array &data)
{
int ham = 0;
for (int i = 0; i < size; i++)
if (*this[i].array != data[i].array)
ham++;
return ham;
}
// This function will empty the target object
void My_array::empty()
{
if (size != 0 && array != NULL) {
size = 0;
delete[] array;
}
}
// Resize the array.
void My_array::resize(int the_size)
{
if (size >= 0) {
empty();
if (the_size != 0) {
size = the_size;
array = new int[size];
}
}
else
cout << "Resize attepmted with a negative size. "
<< "Operation ignored." << endl;
}
// Access an element of the array.
int &My_array::operator[](int index)
{
if (index < size)
return array[index];
else {
cerr << "Illegal access to an element of the array." << endl
<< "The size of the array was " << size
<< " and the index was " << index << endl;
exit(1);
}
}
// Accessor
int My_array::get_size()
{
return size;
}
void My_array::output()
{
cout << "The array of size " << size
<< " contains the elements:" << endl;
for (int i = 0; i<size; i++)
cout << array[i] << ' ';
cout << endl;
}
//overloading the << operator.
ostream &operator<<(ostream &out, My_array &data)
{
out << "The array of size " << data.size
<< " contains the elements:" << endl;
for (int i = 0; i<data.size; i++)
out << data.array[i] << ' ';
out << endl;
return out;
}
#ifndef MY_ARRAY_H
#define MY_ARRAY_H
#include <iostream>
using namespace std;
class My_array {
protected:
int size;
int *array;
public:
// Constructor
My_array(int the_size = 0);
// Destructor
~My_array();
// Copy constructor
My_array(My_array &data);
// Assignment operator
My_array &operator=(My_array &data);
void input();
void randomize(int limit);
bool operator ==(My_array &data);
bool operator !=(My_array &data);
int hamming(My_array &data);
// Deletes the array
void empty();
// Resize the array.
void resize(int the_size = 0);
// Access an element of the array.
int &operator[](int index);
// Returns the size of the array.
int get_size();
// Output the elements of the array.
void output();
friend ostream &operator<<(ostream &out, My_array &data);
};
#endif
This:
*this[i].array != data[i].array
should be this:
array[i] != data.array[i]
or this:
array[i] != data[i]
The *this is unnecessary, and data[i] is a reference to an int (the same one you get by calling data.array[i], thanks to your operator[]), and an int has no member called "array".
I am the beginner of C++, and any help will be very appreciated.
here is the code i can run successfully:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
main(){
bool findIn=false;
RowVectorXd A(10);
A<<false,true,false,true,true,false,false,false,true,true;
std::cout << A << std::endl;
for (int i=0;i<A.size();i++){
if(A(i)==findIn){
std::cout << i << std::endl;
}
}
system("pause");
}
the result is {0,2,5,6,7}, and I want to design a function, the code is as follows:
int seq(bool findIn, VectorXd &resdX){
VectorXd A;
for(int i=0;i<resdX.size();i++){
if(resdX(i)==findIn){
A =A+i;
}
}
return(A);
}
I want this function to return result like that {0,2,5,6,7}.But I don`t know how to set up a array to save the result or is there a function just like 'which' in R software to produce sequence above.
Sounds like you want a vector of integers:
#include <vector>
std::vector<int> seq(bool findIn, VectorXd &resdX)
{
std::vector<int> v;
for(int i=0;i<resdX.size();i++) {
if (resdX(i) == findIn) {
v.push_back(i);
}
}
return v;
}
You can then print its contents by iterating through it:
std::vector<int> result = seq(false, A);
for (int i : result) std::cout << i << '\n';
I did not understand what are you looking for.
If you want just to print a sequence of integers indexing findIn values you might code:
void seq(bool findIn, VectorXd &resdX) { // not int
std::cout << "{ ";
for(int i=0;i<resdX.size();i++) // go inside the array
if(resdX(i)==findIn) // if you find that resdX(i) value equals findIn value
std::cout << i << " "; // print i index
std::cout << "}" << std::endl; // at the end prints a new line
}
EDIT1:
Try to adapt the following snippet:
#include <list>
...
std::list<int> seq(bool findIn, VectorXd& resdX) {
std::list<int> l;
for(int i=0; i<resdX.size(); i++) {
if (resdX(i) == findIn) {
l.push_back(i);
}
}
return l;
}
void print_seq(std::list<int> list_) {
std::cout << "{ ";
std::list<int>::iterator it = list_.begin();
for (; it != list_.end(); ++it) {
std::cout << i << " ";
}
std::cout << " }\n";
}
The following code should store a key and a value. At the end, I want a total sum of all values. But the variable *sum_all* in the my function object sum contains every time "0". What is going on?
// map
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
struct Item {
int count;
double value;
};
class Sum {
public:
Sum() {
sum_all = 0.0;
}
// keys are stored as const in a map
void operator()(pair<const string, Item>& pair) {
cout << pair.first << "\n";
cout << "Sum: " << pair.second.value << "\n";
cout << "Middle: " << pair.second.value/pair.second.count << "\n";
sum_all += pair.second.value;
}
double get_sum_all() {
return sum_all;
}
private:
double sum_all;
};
int main() {
map<string, Item> table;
for (int i = 0; i < 3; i++) {
string key;
double value;
cin >> key;
cin >> value;
// new item
if (table.find(key) == table.end()) {
Item item;
item.count = 1;
item.value = value;
table[key] = item;
} else {
Item& item = table[key];
item.count++;
item.value += value;
}
}
Sum sum;
for_each(table.begin(), table.end(), sum);
cout << "table.size() " << table.size() << "\n";
cout << "sum.get_sum_all() " << sum.get_sum_all() << "\n";
cout << "sum.get_sum_all()/table.size()" << sum.get_sum_all()/table.size() << "\n";
return 0;
}
Example input/output:
[peter#donut chap_6]$ ./u3_map
foo 1
bar 2
foo 1
bar
Sum: 2
Middle: 2
foo
Sum: 2
Middle: 1
table.size() 2
sum.get_sum_all() 0
sum.get_sum_all()/table.size()0
Debugging shows, that sum_all is modified like it should during for_each. But I'm not able to set a watchpoint, or gdb ignores the watchpoint. I thought the constructor is called twice, but this seem not to happen. What I'm doing wrong?
Thanks.
std::for_each takes its functor argument by value, not by reference. The original is not modified. You need to do something like this:
sum = for_each(table.begin(), table.end(), sum);