I can't identify my mistake. I need to create a function int search (int *p, int s, int n) that will search the array for target, and if found it it will return the adress yet if not found it will return NULL;
#include <iostream>
using namespace std;
int search(int *p , int s, int n)
{
for(int i = 0; i < s; i++)
{
if(*p == n)
return &p;
p++;
}
return NULL;
}
int main()
{
int n;
int arr[6] = {1, 2, 3, 4, 5, 6};
cout << "Enter target: "<< endl;
cin >> n;
cout << search(arr, 6, n) << endl;
return 0;
}
You are almost there:
return &p;
This is the issue that you are experiencing: You are returning address of a local pointer that you use for iterating over the input array.
Since you have used if(*p == n) in your code I would suppose that you have been aware that p is a pointer already. Then, once found the element you should simply return it right away:
return p;
Returning &p is definitely an error. p is a function parameter, and its life does not extend past the end of its function. In common implementation it resides in the stack and vanishes at return time, or more exactly can be overwritten at any time after the function returns.
But you do not need that. If you want an integer index, you need:
return i;
and if you really want an address, you should have:
int* search ( int *p , int s, int n) // returns an int* not an int
{
for(int i = 0; i<s;i++)
{
if(*p==n)
return p;
p++;
}
return NULL; // you should return a defined value if not found
}
#include <iostream>
#include <memory>
#include <algorithm>
#include <vector>
void findItemInVec(std::vector<int> &v ,int number) {
std::for_each(v.begin(), v.end(), [number](int &item_in_vec) ->void {
if (item_in_vec == number) {
std::cout << &item_in_vec << std::endl;
}
});
}
int main()
{
std::vector<int> v{ 1,2,5,8,7,6,1 };
findItemInVec(v, 1);
return 0;
}
The argument in the function is a vector of integer values. The function std::for_each checks every item inside the vector with the iterators help and checks if it has the same value with the number argument. For every check that returns true, it types the address of this item.
Related
I'm trying to create this function:
std::vector<int> graph::getNeighbors(int n){
int i = 0; for(int el : verteces[n]) i++;
if( i != 0){
auto iter = verteces[n].begin();
std::vector<int> res = std::vector<int>{i};
for(int j=0; j<i; j++)
res[j] = *(iter++);
return res;
}
return std::vector<int>{};
}
As the name itself explain, it is supposed to get the neighbors of a vertex. The graph is made like this:
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
ยทยทยท
};
Now, the problem is that whenever i is greater than 0, the program crashes badly with the error:
malloc(): corrupted top size
I don't understand what I am doing wrong.
EDIT
In order to make a reproducible example I am going to show all the three files.
main.cpp:
#include <iostream>
#include <set>
#include "graph/graph.h"
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1;
for(int i=0; i<G.getSize(); i++){ // for each vertex
std::set<int> colorNeigh{};
for(auto &j : G.getNeighbors(i)){
if(colors[j] != -1)
colorNeigh.insert( colors[j] );
}
int col = 0;
for(auto &el : colorNeigh){
if(el == col) col++;
else break;
}
colors[i] = col;
}
}
int main() {
{
std::vector<int> r;
for(int i=0; i<100; i++)
r.push_back(i);
}
graph a = graph(10);
a.addEdge(2, 5);
a.addEdge(2, 5);
a.addEdge(1,2);
a.addEdge(2,3);
a.addEdge(3,4);
greedyAlgorithm(a);
return 0;
}
graph.h:
//
// Created by salvo on 11/08/21.
//
#ifndef P2_GRAPH_H
#define P2_GRAPH_H
#include <forward_list>
#include <vector>
#include <stdexcept>
class node;
// list implementation
class graph {
private:
std::vector<std::forward_list<int>> verteces;
unsigned long int n;
public:
graph();
graph(unsigned long int n); // vertex number
void addEdge(int a, int b);
std::vector<int> getNeighbors(int n);
unsigned long getSize(){return n;};
};
#endif //P2_GRAPH_H
graph.cpp:
//
// Created by salvo on 11/08/21.
//
#include <iostream>
#include <openssl/ossl_typ.h>
#include "graph.h"
graph::graph() {
// verteces call default constructor
n = 0;
}
graph::graph(unsigned long int n) {
verteces = std::vector<std::forward_list<int>>{n};
for(auto &el : verteces) el = std::forward_list<int>{};
this->n = n;
}
void graph::addEdge(int a, int b) {
if(a == b){
std::cout << " No self loop!\nexiting ";
exit(-2);
}
int m = a > b ? a : b + 1;
if(m > n){
std::cout << "The graph only contains " << n << " verteces.\n exiting.";
exit(-1);
}
// Check if the edge exist already
for(auto &el : verteces[a]){
if(el == b) return;
}
verteces[a].emplace_front(b);
verteces[b].emplace_front(a);
std::cout << verteces.size() << std::endl;
}
std::vector<int> graph::getNeighbors(int n){
std::vector<int> res{};
for(auto el : verteces[n])
res.push_back(el);
return res;
}
Output if executed:
malloc(): corrupted top size
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
I am using C++14.
Without even looking at the code, I added -D_GLIBCXX_DEBUG1 to compiler flags (to enable container bounds checks) and got this:
Error: attempt to subscript container with out-of-bounds index 1, but
container only holds 1 elements.
Then I used GDB to understand where exactly that happens:
void greedyAlgorithm(graph &G){
std::vector<int> colors{static_cast<int>(G.getSize())};
for(int i=0; i<G.getSize(); i++)
colors[i] = -1; <-- HERE
This means that the syntax you used created a vector with a single element (with value G.getSize()).
This is why you should never EVER use direct-list-initialization (i.e. with curly braces, without =) with containers. If the vector had some other element type (not a number), this would've worked, and this is exactly why you shouldn't do it.
The fix is to use parentheses:
std::vector<int> colors(static_cast<int>(G.getSize()));
1 This is libstdc++-specific flag (it only works with the GCC's standard library). Other standard library implementations have similar checks. There are also address sanitizers that could also work here.
std::vector<int> colors{static_cast<int>(G.getSize())}
Constructs a vector with one element equal to static_cast<int>(G.getSize()). You want std::vector colors(here_the_size) not with { }. std::vector colors(G.getSize()); will construct a vector with G.getSize() elements.
Because subsequent colors[i] = -1; overwrites memory without any checks, you get errors.
Use .at() instead of []. Using colors.at(i) = -1; will allow you to detect errors early on.
The code snippet is as follows. The error is in foo function for the cout line:
typedef struct Datatype {
int first;
int second;
} Datatype;
void foo(std::array<Datatype, 100>* integerarray){
cout << *integerarray[0].first << endl; //ERROR: has no member first
}
void main() {
std::array<Datatype, 100> newarray;
for(int i=0; i<100; i++)
newarray[i] = i;
}
foo(&newarray);
}
Because of operator precedence, *integerarray[0].first is translated as *(integerarray[0].first), which is not what you want. You need to use (*integerarray)[0].first.
cout << (*integerarray)[0].first << endl;
You can make your life simpler by passing a reference.
void foo(std::array<Datatype, 100>& integerarray){
cout << integerarray[0].first << endl;
}
Also, you don't need to use typedef struct DataType { ... } DataType; in C++. You can use just struct DataType { ... };
newarray[i] = i;
In this line you have missed adding value to structure variables.
Also you have passed array as a reference to function. Removing it and passing just the name of array will pass base address of array.
I am adding following code for your reference:
#include<iostream>
#include <array>
struct Datatype{
int first;
int second;
}
typedef Datatype varInts;
void display(std::array<varInts,20> &dummy)
{
int b =5;
for(int i=0; i<20; i++)
{
dummy[i].first =b++;
dummy[i].second = b+5; //Give any logic you wish.just adding different values;
b++;
}
}
int main()
{
std::array<varInts,20> data;
int a =1;
for(int i=0;i<20;i++)
{
data[i].first = a++;
data[i].second = a+5;
a++; //Just adding values for example
}
display(data);
return 0;
}
It runs without error.Hope it helps!!
How do i access the array in the main using the reference arrref
The memory leak in the code below is intended to know valgrind tool.But i am not able to compile the code below
#include <iostream>
int& func();
int main()
{
int &arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
int& func()
{
int *a = new int[10];
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return *a;
}
Thanks
The syntax needed is (&arrref)[1]. That refers to the second element of an array.
But make sure that the reference returned from func indeed refers to the first element of an array with sufficient number of elements.
To communicate clearly that func returns a reference to an array you may like to return a range, e.g.:
#include <iostream>
#include <boost/range/as_array.hpp>
boost::iterator_range<int*> func() {
static int array[2] = {1, 2};
return boost::as_array(array);
}
int main() {
auto array = func();
std::cout << array[0] << '\n';
std::cout << array[1] << '\n';
for(auto const& value: func())
std::cout << value << '\n';
}
Outputs:
1
2
1
2
Firstly it is not a good idea access local variables of one function in some other functions.
The function return type is int& which says that you want to return a reference to an int variable.
If you want to access the array local array 'a' then the function should be rewritten as -
#include <iostream>
int* func();
int main()
{
int *arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
int *func()
{
int *a = new int[10];
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return a;
}
Alternatively you can also use vectors -
#include<iostream>
#include<vector>
std::vector<int>& func();
int main()
{
std::vector<int>& arrref = func();
std::cout<<arrref[1];//Error
std::cout<<&arrref[1];//Error
}
std::vector<int>& func()
{
std::vector<int> a(10);
for(int i = 0;i<10 ;++i)
a[i] = i*2;
return a;
}
I defined a function getArray() in class A, like this:
void getArray(int * arr){
arr = new int[10];
arr[0] = 1;
}
I want to modify pointer arr in getArray(). And I invoked function getArray() in main(), like this:
int main(){
A obj;
int * arr = new int[2];
obj.getArray(arr);
cout<<arr[0]<<endl;
delete[] arr;
}
But when I executed main(), the output of arr[0] is 0, not 1. Why?
Actually, I want to allocate new memory to pointer arr and set the contents of the array in function getArray(). Then I want to get the contents of the array and deallocate pointer arr in main(). But I don't know what to do.
The array was not modified, because you reassign the variable in getArray. This code will work:
void getArray(int * arr){
arr[0] = 1;
}
You should decide where the memory for array is allocated. If the answer is in main, then you should deallocate it at the end of this function:
int main(){
A obj;
int * arr = new int[2];
obj.getArray(arr);
cout<<arr[0]<<endl;
delete[] arr;
}
If the array should be created in getArray, then you don't need the allocation in main, and you should return the new pointer from getArray, and don't forget to deallocate it:
int * getArray(){
int * arr = new int[10];
arr[0] = 1;
return arr;
}
int main(){
A obj;
int * arr = obj.getArray();
cout<<arr[0]<<endl;
delete[] arr;
}
Because you are calling getArray with a copy of your pointer.
You can call functions by-value or by-reference. Using a pointer may look like a by-reference call, yet it is a by-value call as a pointer only stores a reference.
You could use pass the pointer by-reference to achieve what you are trying to do: void getArray(int *& arr).
BTW: I hope that this code isn't somewhere in a productive environment as it has 2 memory leaks.
UPDATE:
Examples using std::vector:
Example 1:
#include<iostream>
#include<vector>
struct A
{
void getData(std::vector<int>& v){
v = std::vector<int>(10, 0); //vector with 10 zeros
v[0] = 1;
}
};
void printData(const std::vector<int>& v)
{
std::cout << "v.size() = " << v.size() << std::endl;
for(int value : v)
{
std::cout << value << std::endl;
}
}
int main(){
A obj;
std::vector<int> v;
obj.getData(v);
printData(v);
return 0;
}
Example 2:
#include<iostream>
#include<vector>
struct A
{
std::vector<int> getData(){
std::vector<int> v(10, 0); //vector with 10 zeros
v[0] = 1;
return v;
}
};
void printData(const std::vector<int>& v)
{
std::cout << "v.size() = " << v.size() << std::endl;
for(int value : v)
{
std::cout << value << std::endl;
}
}
int main(){
A obj;
std::vector<int> v = obj.getData();
printData(v);
return 0;
}
It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.