not able to run this code to reverse the array - c++

#include<iostream>
using namespace std;
void reverse(int arr[],int n){
int start=0,end=n-1;
int temp;
while(start<=end){
temp=arr[end];
arr[end]=arr[start];
arr[start]=temp;
}
start++;
end--;
}
void print(int arr[],int n){
for(int i=0;i<n;i++){
cout<<arr;
}
cout<<endl;
}
int main(){
int arr[5]={1,2,3,4,5};
int brr[6]={3,6,8,2,1,0};
reverse(arr,5);
reverse(brr,6);
print(arr,5);
print(brr,6);
}
I am not able to run this code at any compiler, can anyone tell me where I am making the mistake
after running it I am getting nothing

I am not to happy about the material that is teaching you C++.
For one it still uses "C" style arrays, and it is learning you to write
using namespace std; which will lead to problems (name clashes) in big projects. So if you have a teacher tell him about this.
Here is a more C++ oriented example :
#include <algorithm>
#include <iostream>
#include <vector>
// Using namespace std; <-- No unlearn this
// don't use "C" style arrays, use std::array or std::vector
// "C" style arrays are inherently more "buggy" to use.
// for one it easy to get mismatch array size and the size you pass.
void reverse(std::vector<int>& values)
{
//std::reverse(values.begin(), values.end()); C++ has this out of the box for you
std::size_t left_pos = 0ul;
std::size_t right_pos = values.size() - 1; // last index in array
/// manually, you start with first and last element and swap them
// then move left position one to the right, and right position one to the left
// repeat until left_pos and right_pos cross.
for (; left_pos < right_pos; ++left_pos, --right_pos)
{
// c++ has a swap method to swap values
std::swap(values[left_pos], values[right_pos]);
}
}
// prints the content of the vector
std::ostream& operator<<(std::ostream& os, const std::vector<int>& values)
{
bool print_comma{ false };
for (const int value : values)
{
if (print_comma) std::cout << ",";
std::cout << value;
print_comma = true;
}
std::cout << "\n";
return os;
}
int main()
{
std::vector<int> arr1{ 1,2,3,4,5 };
reverse(arr1);
std::cout << arr1;
return 0;
}

Just for your information: I would recommend you to just use std::reverse() for the concrete example. Also, do not use raw arrays.
#include <algorithm>
#include <iostream>
template <typename T>
void print(const T& arr) {
for (auto &value: arr) {
std::cout << value << " ";
}
std::cout << "\n";
}
int main(){
std::array arr={1,2,3,4,5}; // Or just use a std::vector
std::array brr={3,6,8,2,1,0};
std::reverse(arr.begin(), arr.end());
std::reverse(brr.begin(), brr.end());
print(arr);
print(brr);
}

Related

Is there a way to use an array passed as parameter on std::begin or std::end?

I keep getting a compilation error if I use an array passed as parameter to a method on std::begin or std::end such as this:
#include <iostream>
#include <algorithm>
using namespace std;
class Test
{
public:
static bool exists(int ints[], int size, int k)
{
if (std::find(std::begin(ints), std::end(ints), k) != std::end(ints)) {
return true;
}
return false;
}
};
I tried casting it to &int[0] but it will still not compile.
The parameter ints is not an array, so you aren't passing an array into std::begin / std::end in the example. A function parameter is never an array in C++. When you declare a function array to be an array such as in your example, that parameter is adjusted to be a pointer to the element of such array. In your case, the type of the parameter ints has been adjusted to be a pointer to int i.e. int*, and you cannot pass a pointer into std::begin / std::end, as the error message surely explains.
You have passed the size as another parameter, so you could instead use:
std::find(ints, ints + size, k)
A more modern API design is to wrap the pointer and the size into a single class. The C++20 standard library comes with such class template: std::span. It also has convenient range algorithms that are quite convenient:
static bool exists(std::span<const int> ints, int k)
{
if (std::ranges::find(ints, k) != std::end(ints)) {
Even moreso, C++20 standard library has a function template that makes your function unnecessary:
std::ranges::contains(some_array, k);
Use std::span.
try this:
#include <algorithm>
#include <iostream>
#include <span>
bool exists(std::span<int> span, int needle) {
return std::find(span.begin(), span.end(), needle) != span.end();
}
int main() {
int arr[] = {0, 1, 2, 3, 4};
bool ok = exists(arr, 3);
if (ok) {
std::cout << "ok" << '\n';
} else {
std::cout << "not ok" << '\n';
}
return 0;
}
Here is a working example.
#include <iostream>
#include <vector>
bool exists(int x[], const int size, const int k)
{
std::vector<int> v(x, x + size);
if (std::find( v.begin(), v.end(), k) != v.end()) {
return true;
}
return false;
}
int main()
{
int const sz = 10;
int arrayi[sz] = { 1, 2, 3,4 ,5 ,6 ,7 , 8, 9, 0 };
if (exists(arrayi, sz, 4))
std::cout << "exist" << std::endl;
else
std::cout << "it does not" << std::endl;
}

How to change values of array at initialization in C++?

I want an array that have new attributed values if the value is x.
I can do that in PHP with that code:
$test = array(1=>55, 2=>66);
on above code if test[0] = 1, the new value of test[0] is going to be 55.
I want to do that in C++.
Normal C++ arrays do not have keys. There are always 0-indexed.
But we have std::map which is what PHP also use internally for key-based containers.
https://en.cppreference.com/w/cpp/container/map
You can make your own attributed values class in C++, so it has that behavior.
You can make it so the behavior is hard coded into the class. Or if you want to get fancier you can make the class having a value mapping passed in.
Here's an example with the value mapping passed into the class.
#include <cstddef>
#include <iostream>
#include <map>
#include <stdexcept>
#include <vector>
using sad_panda = std::logic_error;
using std::cout;
using std::map;
using std::size_t;
using std::vector;
namespace {
class AttributedValues {
vector<int> v;
map<int, int> attr_to_value;
public:
AttributedValues(map<int, int> mapping);
void set(size_t index, int value);
int operator[](size_t index) const;
};
AttributedValues::AttributedValues(map<int, int> mapping)
: attr_to_value{mapping}
{ }
void AttributedValues::set(size_t index, int value) {
if (index >= v.size()) {
v.resize(index+1);
}
auto iter = attr_to_value.find(value);
if (iter != attr_to_value.end()) {
value = iter->second;
}
v[index] = value;
}
int AttributedValues::operator[](size_t index) const {
if (index >= v.size()) {
throw sad_panda("AttributedValues::operator[] index out of range");
}
return v[index];
}
} // anon
int main() {
auto test = AttributedValues{{{1, 55}, {2, 66}}};
test.set(0, 1);
test.set(10, 2);
cout << test[0] << "\n";
cout << test[10] << "\n";
}

Generating a map of strings to std::list of pointers in c++

I am trying to achieve the creation of such a map. The following code attempts to do this
#include <list>
#include <map>
#include <string>
class IntWithString {
private:
int a;
std::string s;
public:
IntWithString(int a, std::string s) : a(a), s(s) {}
std::string getString() { return s; }
int getInt() { return a; }
};
namespace {
std::map<std::string, std::list<IntWithString *> > m;
}
void appendMap(IntWithString *a) {
auto it = m.find(a->getString());
if (it != m.end()) {
m[a->getString()].push_back(a);
} else {
std::list<IntWithString *> l;
l.push_back(a);
m[a->getString()] = l;
}
}
int main() {
IntWithString a(10, "ten");
IntWithString b(11, "ten");
appendMap(&a);
appendMap(&b);
return 0;
}
However when looking at the map m with the debugger I am getting a map that maps "ten" to a list of size 0. What I would like is a list of size 2.
I am not sure what you mean. If I do:
std::cout << m.size() << ", " << m["ten"].size() << std::endl;
I get this output:
1, 2
which is a map with one key ("ten"), and two values for that key (10 and 11), as expected.
Live demo
PS: Storing pointers in a container like this is a bit uncommon in C++. If you really want to do this though, consider to use Smart Pointers.

How would I pass an unnamed (new) array as an argument c++ [duplicate]

I'd like to be able to declare an array as a function argument in C++, as shown in the example code below (which doesn't compile). Is there any way to do this (other than declaring the array separately beforehand)?
#include <stdio.h>
static void PrintArray(int arrayLen, const int * array)
{
for (int i=0; i<arrayLen; i++) printf("%i -> %i\n", i, array[i]);
}
int main(int, char **)
{
PrintArray(5, {5,6,7,8,9} ); // doesn't compile
return 0;
}
If you're using older C++ variants (pre-C++0x), then this is not allowed. The "anonymous array" you refer to is actually an initializer list. Now that C++11 is out, this can be done with the built-in initializer_list type. You theoretically can also use it as a C-style initializer list by using extern C, if your compiler parses them as C99 or later.
For example:
int main()
{
const int* p;
p = (const int[]){1, 2, 3};
}
It's allowed with a typecast in C++11 and in extern "C" with C99:
void PrintArray(size_t len, const int *array)
{
for(size_t i = 0; i < len; i++)
printf("%d\n", array[i]);
}
int main(int argc, char **argv)
{
PrintArray(5, (const int[]){1, 2, 3, 4, 5});
return 0;
}
This compiles, but I wouldn't recommend it.
#include <stdio.h>
struct arr
{
int array[5];
};
static void PrintArray(int arrayLen, arr array)
{
for (int i=0; i<arrayLen; i++) printf("%i -> %i\n", i, array.array[i]);
}
int main(int, char **)
{
PrintArray(5, (arr){5,6,7,8,9});
return 0;
}
Disclaimer: For this answer I get some downvotes, but it originates from 2009, where C++ 11 was about to be defined. For modern C++ please scroll below.
Well, try using boost...
Here is the solution using the boost::assign library and bit more C++ like programming ;)
#include <boost/assign/list_of.hpp>
#include <iostream>
#include <algorithm>
namespace
{
template<class CollectionT>
void print(CollectionT const& coll)
{
std::ostream_iterator<int> out(std::cout, ", ");
std::copy(coll.begin(), coll.end(), out);
}
}
int main()
{
using namespace boost::assign;
print( list_of(1)(2)(3)(4)(5) );
return 0;
}
C++ 11 and higher with the explanation of particular features
Complied with clang:
clang++ -std=c++14 -I /usr/local/include/ main.cpp
#include <boost/assign/list_of.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <initializer_list>
template<typename CollectionT, typename OStream>
auto // <- auto result type deduction from C++ 14
make_output_iterator(CollectionT const& coll, OStream& out)
{
return std::ostream_iterator<typename CollectionT::value_type>(out, ", ");
}
// here template specialization is used, to demonstrate initializer lists from C++ 11
template<typename T>
void print(std::initializer_list<T> items)
// ^----------------------^ passed by value due to move semantics
{
using namespace std;
cout << "printing an initializer list: ";
copy(items.begin(), items.end(), make_output_iterator(items, cout));
cout << endl;
}
template<typename CollectionT>
void print(CollectionT const& items)
{
using namespace std;
cout << "printing another collection type: ";
copy(items.begin(), items.end(), make_output_iterator(items, cout));
cout << endl;
}
int main()
{
print({0,1,2,3,4,5,6,7,9});
using namespace boost::assign;
print( list_of(0)(1)(2)(3)(4)(5)(6)(7)(8)(9) );
}
Starting from C++11, you can just use std::begin(std::initializer_list const&) to get the pointer. Example:
#include <iostream>
#include <iterator>
void func(int len, const int* x)
{
for(int i=0;i<len;++i)
std::cout << x[i] << "\n";
}
int main()
{
func(5, std::begin({1,3,6,823,-35}));
}
Unlike the accepted answer, this is really Standard-compatible code.
With C++0x you could use an std::initializer_list (and a foreach loop)
#include <iostream>
#include <initializer_list>
void print (const std::initializer_list<int>& array)
{
for (auto x : array) // C++0x foreach loop
std::cout << x << std::endl;
}
int main (int argc, char ** argv)
{
print ({ 1, 2, 3, 4, 5 });
}
Yes and no. In the current version of the standard (ISO C++ 1998 with ammendments from 2003), it is not possible. However, in the next version of the standard "C++0x" (which, despite its name implying that it will be released in 200x, will most likely be released in 2010), it will be possible with std::initializer_list<>.
You can use std::initializer_list list Joe D suggests, however I am not sure you can use it if you want other parameters. (I can't seem to find any information on that.) However, if you declare a const reference to a vector, the initializer_list that is created with { ... } will get converted to the vector.
#include <iostream>
#include <vector>
void PrintArray(const char* prefix, const std::vector<int>& array)
{
std::cout << prefix << std::endl;
for (int i : array) {
std::cout << i << std::endl;
}
}
int main(int, char **)
{
PrintArray("test array", {5,6,7,8,9} );
return 0;
}
You could use a variable number of arguments instead of passing an array:
static void PrintArray(int arrayLen, ...)
{
int this_value;
va_list array;
va_start(array, arrayLen);
for (int i=0; i<arrayLen; i++)
{
this_value = va_arg(array, int);
printf("%i -> %i\n", i, this_value);
}
va_end(array);
}
I didn't compile this so I probably made a mistake or two, but hopefully it's close enough. Look up va_start for reference.
Here's a simple clean solution to get a C-style array that no-one else has mentioned:
#include <iostream>
using namespace std;
template <int N>
int
get_last( const int ( &my_array )[N] ) {
return my_array[N-1];
}
int main()
{
cout << "Last: " << get_last( { 1, 2, 3, 55 } );
return 0;
}
Another choice would be to use array in the TR1 library which is likely to become part of the next standard and is supported by many compilers.
#include <array>
#include <algorithm>
#include <iostream>
using std::tr1::array;
using std::cout;
using std::copy;
using std::ostream_iterator;
template <class Container>
void PrintArray(Container &values)
{
copy(values.begin(), values.end(), ostream_iterator<int>(cout, "\n"));
}
int main()
{
array<int, 5> values = {1, 2, 3, 4, 5};
PrintArray(values);
}
You can do this in ANSI-C using good ol' va_list
Templatized C++ with a std::vector returned for convenience in addition
#include <stdarg.h>
#include <vector>
using namespace std ;
struct Point
{
int x,y;
Point():x(0),y(0){}
Point( int ix, int iy ):x(ix),y(iy){}
~Point(){printf("%d %d - the point has been destroyed!\n",x,y);}
void print(){printf("%d,%d\n",x,y);}
} ;
// Concrete example using a list of int
int* initFrom( int numItems, ... )
{
int* list = new int[ numItems ] ;
va_list listPointer;
va_start( listPointer, numItems );
for( int i = 0 ; i < numItems; i++ )
list[ i ] = va_arg( listPointer, int ) ;
return list ;
}
// templatized version.
template <typename T> vector<T> initFrom( int numItems, ... )
{
vector<T> list ;
list.resize( numItems ) ;
va_list listPointer;
va_start( listPointer, numItems );
for( int i = 0 ; i < numItems; i++ )
list[ i ] = va_arg( listPointer, T ) ;
return list ;
}
int main()
{
int* theList = initFrom( 4, 900, 2000, 1000, 100 ) ;
for( int i = 0 ; i < 4 ; i++ )
printf( "Item %d=%d\n", i, theList[i] );
puts( "\n\n--Lots of destruction using non-ptr" ) ;
vector<Point> thePoints = initFrom<Point>( 3, Point(3,7), Point(4,5), Point(99,99) ) ;
puts( "Our listing:" ) ;
for( int i = 0 ; i < 3 ; i++ )
thePoints[i].print() ;
puts( "\n\n-- Less destruction using ptr" ) ;
// Be careful of extra copy construction. Using a vector of pointers
// will avoid that
vector<Point*> theNewPoints = initFrom<Point*>( 3, new Point(300,700), new Point(400,500), new Point(990,990) ) ;
puts( "Our listing:" ) ;
for( int i = 0 ; i < 3 ; i++ )
theNewPoints[i]->print() ;
puts( "END OF PROGRAM --" ) ;
}
PrintArray function is expecting a int*, but const. So you can pass a temporary int array created with new.
PrintArray(5, new int[5]{5,6,7,8,9});
Or with std::move() to add more sense.
#include <utility>
PrintArray(5, std::move(new int[5]{5,6,7,8,9}));
No, and it's bad coding practice anyway. Just declare const int* foo = {5,6,7,8,9}; before the function call. Even if this did work, it wouldn't speed up your program or compile time. The values would still need to be allocated in memory and passed through the function call.

(C++) Reversing a string using stacks?

I'm trying to reverse a string using stacks. It correctly reverses the string, but the for loop crashes when i reaches 0. I get a "string subscript out of range" error. Currently the for loop only decrements to 1. How can I get it to push and display s1[0]?
This is the main code:
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cin, cout
#include <stack> // Provides stack
#include <string> // Provides string
using namespace std;
. . .
string reverse(string & s1)
{
stack<char> stk1;
string::size_type i;
// this for loop sets the rest of the characters
for (i = s1.size() - 1; i > 0; i--)
{
stk1.push(s1[i]);
cout << stk1.top();
}
return "The function was a success. Now that's what I call reverse psychology.";
}
This is the header file:
#ifndef MAIN_SAVITCH_STACK1_H
#define MAIN_SAVITCH_STACK1_H
#include <cstdlib> // Provides size_t
namespace main_savitch_7A
{
template <class Item>
class stack
{
public:
// TYPEDEFS AND MEMBER CONSTANT -- See Appendix E if this fails to compile.
typedef std::size_t size_type;
typedef Item value_type;
static const size_type CAPACITY = 30;
// CONSTRUCTOR
stack( ) { used = 0; }
// MODIFICATION MEMBER FUNCTIONS
void push(const Item& entry);
void pop( );
// CONSTANT MEMBER FUNCTIONS
bool empty( ) const { return (used == 0); }
size_type size( ) const { return used; }
Item top( ) const;
private:
Item data[CAPACITY]; // Partially filled array
size_type used; // How much of array is being used
};
}
#include "stack1.template" // Include the implementation.
#endif
And this is the stack implementation (a template file):
#include <cassert> // Provides assert
namespace main_savitch_7A
{
template <class Item>
const typename stack<Item>::size_type stack<Item>::CAPACITY;
template <class Item>
void stack<Item>::push(const Item& entry)
// Library facilities used: cassert
{
assert(size( ) < CAPACITY);
data[used] = entry;
++used;
}
template <class Item>
void stack<Item>::pop( )
// Library facilities used: cassert
{
assert(!empty( ));
--used;
}
template <class Item>
Item stack<Item>::top( ) const
// Library facilities used: cassert
{
assert(!empty( ));
return data[used-1];
}
}
I want to change the for loop to this, but it doesn't work:
// this for loop sets the rest of the characters
for (i = s1.size() - 1; i >= 0; i--) // i > -1 doesn't work either
{
stk1.push(s1[i]);
cout << stk1.top();
}
cout << s1[0] << "\n\n";
return "The function was a success. Now that's what I call reverse psychology.";
}
I can think of the following couple of options.
Using the string::size_type for the loop counter:
string::size_type i;
for (i = s1.size(); i > 0; i--)
{
stk1.push(s1[i-1]);
cout << stk1.top();
}
or
Using an int for the loop counter:
int i = 0;
for (i = s1.size()-1; i >= 0; i--)
{
stk1.push(s1[i]);
cout << stk1.top();
}
i is unsigned so it wraps around when it is decremented if it is equal to 0. You need to use a signed type for it or to check the boundary condition without involving negative numbers(that is, do not compare it with -1 and do not decrement it if it is 0).