How to call struct from separate function? - c++

#include <iostream>
#include <cmath>
using namespace std;
struct workers{
int ID;
string name;
string lastname;
int date;
};
bool check_ID(workers *people, workers &guy);
void check_something(workers *people, workers &guy, int& i);
int main()
{
workers people[5];
for(int i = 0; i < 5; i++){
cin >> people[i].ID;
cin >> people[i].name;
cin >> people[i].lastname;
cin >> people[i].date;
if(check_ID(people, people[i]) == true)
cout << "True" << endl;
else
cout << "False" << endl;
check_something(people, people[i], i);
}
return 0;
}
bool check_ID(workers *people, workers &guy){
for(int i = 0; i < 5; i++){
if(people[i].ID == guy.ID)
return true;
break;
}
return false;
}
void check_something(workers *people, workers &guy, int& i){
check_ID(people, guy[i]);
}
This is the code I have, it's not very good example, but I quickly wrote it to represent my problem I have because my project is kinda too big. So basically, I want to call struct from a different function and I'm getting this error:
error: no match for 'operator[]' in guy[i] on this line :
check_ID(people, guy[i]); in the function check_something.

In main, people is an array. You access the ith element of it people[i] and try to pass it to check_something in the position of function-local variable guy. You then try to dereference guy - which is not an array, but a single object instance.
int main()
{
workers people[5]; // <-- array
...
check_something(people /* <-- people */, people[i] /* <-- guy */, i /* <-- i */);
vs
void check_something(workers *people, workers &guy, int& i){
check_ID(people, guy[i] /* <-- array access on single instance*/);
You actually passed the array in the first argument, people. You don't need "guy" here, because it is people[i], isn't it? So you could do:
void check_something(workers *people, int& i){
worker& guy = people[i];
check_ID(people, guy);
or just
void check_something(workers *people, int& i){
check_ID(people, people[i]);
or
would work, or you could just pass
void check_something(workers* people, workers& guy) {
check_id(people, guy);
}
---- EDIT ----
You also have a python-like bug in your check_ID function.
if(people[i].ID == guy.ID)
return true;
break;
In Python, this says:
if people[i].ID == guy.ID:
return True
break
What you want is
if ( people[i].ID == guy.ID ) {
return true;
break;
}
or just
if ( people[i].ID == guy.ID )
return true;
(since the return is going to exit the function, there's no point in also saying break afterwards)

workers does not have an overloaded subscript operator, nor is guy an array. Therefore you cannot call [] on it. Either create an array or delete [i] after guy.
check_ID(people, guy); //delete [i]

Guy is a reference, not a pointer. You cannot use the operator[] on a reference.

Related

Why does this code work when I remove the return statement in the void function called dfs but returns an inaccurate answer otherwise?

Leetcode q: https://leetcode.com/contest/biweekly-contest-69/problems/longest-palindrome-by-concatenating-two-letter-words/
My Solution:
#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
bool isPalindrome(string str){
int n=str.size();
for(int i=0;i<=n/2;i++){
if(str[i]!=str[n-1-i]){
return false;
}
}
return true;
}
int ans=0;
void dfs(string curStr, unordered_map<int,bool> visited, vector<string> &words){
//Snippets for debugging:-
// cout<<curStr<<endl;
// cout<<"Visited map:- \n";
// for (auto i : visited)
// cout << i.first << " is " << i.second
// << endl;
//
// cout<<endl;
//Excluding this gives the correct answer, idk why it dosent work otherwise
//P1:-
// if(visited.size() == words.size()){
// return;
// }
for(int i=0;i<words.size();i++){
if(!visited[i]){
string newStr = curStr + words[i]; //chk?
if(isPalindrome(newStr)){
if(ans<newStr.size()){
ans=newStr.size();
}
}
visited[i]=true;
dfs(newStr, visited, words);
visited[i]=false;
}
}
}
int longestPalindrome(vector<string>& words) {
unordered_map<int,bool> visited;
dfs("", visited, words);
return ans;
}
};
Main Function with invocation:-
int main(){
Solution s1;
vector<string> tc{"lc","cl","gg"};
cout<<"ANS:"<<s1.longestPalindrome(tc);
return 0;
}
I ran my code for this test case shown in main but whenever I exclude the Part Called P1 (or the return statement in the void fn called dfs), it gives the right answer of "6." However, when that snippet P1 is included, it gives an answer "4"
I have no why this is happening. I'm guessing it's something silly but it'd mean a lot if someone could help. Thanks!

How do I return value to main function without directly calling the function

I have multiple functions in my program. Each function has some conditions. If conditions are met, then it passes on the value to another function which again checks the value with some conditions, modifies it.
The first function [named 'squarefree()'] is called from main [obviously] and it further goes on to call another function which in course calls another function untill the process stops at last function named 'end()'. Like this:
#include <iostream>
using namespace std;
int squarefree(int n);
int goodnumber(int sf);
int end(int gn);
int main() {
// your code goes here
int l,r;
cin>>l;
cin>>r;
for(int p=l;p<=r;p++)
{squarefree(p);}
/*int ret=end(int gn); PROBLEM LIES HERE
cout<<ret; */
return 0;
}
int squarefree(int n){
int i;
for(int i=2;i<n;i++)
{
if((n%(i*i))==0)
{
cout<<"number not square free"<<endl;
break;
}
else{
cout<<"number square free"<<endl;
goodnumber(n);
break;
}
}
return 0;
}
int goodnumber(int sf){
cout<<"Sf is:"<<sf<<endl;
int s=0,c=0,flag=0;
for(int j=1;j<=sf;j++)
{
if(sf%j==0)
{
s+=j;
for(int k=2;k<=j/2;++k)
{
if(j%k==0)
{
c++;
}
}
}
}
cout<<"s is:"<<s<<endl;
cout<<"no.of prime numbers dividin s are:"<<c<<endl;
for(int l=2;l<=c/2;++l)
{
if(c%l==0)
{
flag=1;
break;
}
}
if (flag==0)
{cout << "C is a prime number, so this is good number and needs to be passed to next function"<<endl;
end(s);
}
else
{cout << "C is not a prime number"<<endl;
}
return 0;
}
int end(int gn)
{
int sum=0;
sum+=gn;
cout<<"SUm of factors of the good number is:"<<sum<<endl;
return sum;
}
The 'end()' function returns a value sum. Now I want this value sum to be updated everytime the for loop in main() function runs. For example: Sum in first iterations is 5, sum is 2nd iteration is 10, so total sum gets 15 and so on.
If somehow, the value returned by end function can be fetched into main function, that would be great.
Look at all those int-returning functions that are always returning 0. You might be able to take advantage of that.
A trivial example:
#include <iostream>
int step3(int val)
{
return val * val;
}
int step2(int val)
{
return step3(val + 1);
}
int step1(int val)
{
return step2(val * 2);
}
int main()
{
std::cout << step1(1);
}
But take care. You might find a case where you don't get any valid results and need to inform the caller that no result was found.
In addition to the idea of having the functions return the result of the next stage in the pipeline, which is an excellent idea, you can pass the address of the variable in which to store the result (allowing you to return more than one result, or an error code), or store the result of each stage in a temporary variable and return that (allowing you to use a result in more than one computation). I would advise against using a global variable to bypass the stack; it’s considered poor practice.
Some Examples:
// Returning the result of the next stage in the pipeline:
int g(int);
int f(int x)
{
return g(x);
}
// Passing a variable by reference:
enum errcode { success, failure };
errcode sqr( int input, int& output )
{
output = input * input; // This modifies the second variable the caller gave.
return success;
}
// Storing in a temporary variable:
int stage2(int);
int stage1(int x)
{
const int y = stage2(x); // Store the result in a temporary.
const int z = sqr(y);
return z;
}
// Passing results through a global variable is a bad idea:
int necessary_evil = 0; // Declared in global scope; should at least be
// declared static if possible to make it visible only in this source file.
// Namespaces are a fancier way to do something similar.
void kludge(int x)
{
necessary_evil = x * x; // The caller will check the global.
return;
}
There are examples of all of these in the standard library: printf() is essentially a wrapper for vfprintf(), strtol() takes a parameter by reference that the function sets to a pointer to the remainder of the string, and errno is a global variable.

Creating a class while using cascading and PLP

So I am trying to create a class ( Version ) with data members. The member functions are setters ( allow for cascading calls ) and getters ( use PLP and handle constant objects ). In the int main, it allows the user to input the numbers, then it needs to use cascading member functions calls for all data members in one statement and display the version by calling the getters and have them return just the value of the data member.
I pretty much coded everything, but I feel like I'm missing a step or doing something wrong with the parameters. My error says that I need a ')' for my setters, but I feel like it is a different problem. I did not get all my notes for how to do this, so can someone tell me what I am missing or need to fix? Thanks!
#include<iostream>
using namespace std;
class Version
{
private:
int major, minor, service_pack;
public:
Version();
Version& setMajor(int maj);
Version& setMinor(int min);
Version& setService_pack(int sp);
int getMinor(Version *const this);
int getMajor(Version* const this);
int getService_pack(Version* const this);
};
Version::Version()
{
major = 0;
minor = 0;
service_pack = 0;
}
Version& Version::setMinor(int min)
{
minor = min;
return *this;
}
Version& Version::setMinor(int maj)
{
major = maj;
return *this;
}
Version& Version::setMinor(int sp)
{
service_pack = sp;
return *this;
}
int Version::getMinor(Version* const this)
{
return this->minor;
(*this).minor;
}
int Version::getMajor(Version* const this)
{
return this->major;
(*this).major;
}
int Version::getService_pack(Version* const this)
{
return this->service_pack;
(*this).service_pack;
}
int main()
{
int minor, major, service_pack;
Version a;
cout << "Enter minor, major, and service pack: " << endl;
cin >> minor, major, service_pack;
a.setMinor(minor).setMajor(major).setService_pack(service_pack);
cout << "Major: " << a.getMajor() << "Minor: "<< a.getMinor << "Service Pack: " << a.getService_pack();
system("PAUSE");
}
You are missing parenbtheses in main() for diplaying a.getMinor(). Without the parentheses, you'd refer to the member function itself.
Your getters should in principle take no arguments if you return the value. In any case, avoid passing arguments called this.
One further improvement you could make, would be to declare the getters as const:
int Version::getMinor() const
{
return minor; // this-> is only needed to disambiguate
}

Sending an array between two functions C++

I am trying to send a array of 15 integers between two functions in C++. The first enables the user to enter taxi IDs and the second functions allows the user to delete taxi IDs from the array. However I am having an issue sending the array between the functions.
void startShift ()
{
int array [15]; //array of 15 declared
for (int i = 0; i < 15; i++)
{
cout << "Please enter the taxis ID: ";
cin >> array[i]; //user enters taxi IDs
if (array[i] == 0)
break;
}
cout << "Enter 0 to return to main menu: ";
cin >> goBack;
cout << "\n";
if (goBack == 0)
update();
}
void endShift ()
{
//need the array to be sent to here
cout << "Enter 0 to return to main menu: ";
cin >> goBack;
cout << "\n";
if (goBack == 0)
update();
}
Any help is great valued. Many thanks.
Since the array has been created on the stack, you would just need to pass the pointer to the first element, as an int*
void endshift(int* arr)
{
int val = arr[1];
printf("val is %d", val);
}
int main(void)
{
int array[15];
array[1] = 5;
endshift(array);
}
Since the array is created on the stack, it will no longer exist once the routine in which it was created has exited.
Declare the array outside of those functions and pass it to them by reference.
void startShift(int (&shifts)[15]) {
// ...
}
void endShift(int (&shifts)[15]) {
// ...
}
int main() {
int array[15];
startShift(array);
endShift(array);
}
This isn't exactly pretty syntax or all that common. A much more likely way to write this is to pass a pointer to the array and its length.
void startShift(int* shifts, size_t len) {
// work with the pointer
}
int main() {
int array[15];
startShift(array, 15);
}
Idiomatic C++ would be different altogether and use iterators to abstract away from the container, but I suppose that is out of scope here. The example anyway:
template<typename Iterator>
void startShift(Iterator begin, Iterator end) {
// work with the iterators
}
int main() {
int array[15];
startShift(array, array + 15);
}
You also wouldn't use a raw array, but std::array.
It won't work to use a local array in the startShift() function. You are best off to do one or more of the following:
Use an array in the function calling startShift() and endShift() and pass the array to these functions, e.g.:
void startShift(int* array) { ... }
void endShift(int* array) { ... }
int main() {
int arrray[15];
// ...
startShift(array);
// ...
endShift(array);
// ...
}
Don't use built-in arrays in the first place: use std::vector<int> instead: that class automatically maintains the current size of the array. You can also return it from a function altough you are probably still best off to pass the objects to the function.
void endShift (int* arr)
{
arr[0] = 5;
}

Stack-based palindrome checker

i have a problem with my program. It should be program that recognize palindome through the stack. Everything works great, only thing that don't work is printing stacks(original and reversed) after the funcion is done.
Here is my entire code, and the problem is at case d and e:
#include <iostream>
using namespace std;
const int MAXSTACK = 21;
class stack {
private:
int stop;
char stk[MAXSTACK];
public:
stack();
~stack();
stack(const stack& s);
void push(const char c);
char pop();
char top(void);
int emptystack(void);
int fullstack(void);
void stack_print(void);
int stack::create(void);
};
stack::stack()
{
stop = 0;
}
stack::~stack() { }
stack::stack(const stack& s)
{
stop = s.stop;
strcpy(stk,s.stk);
}
void stack::push(const char c)
{
stk[stop++] = c;
}
char stack::pop()
{
return stop--;
}
char stack::top(void)
{
return stk[stop - 1];
}
int stack::emptystack(void)
{
return !stop;
}
int stack::fullstack(void)
{
return stop == MAXSTACK;
}
void stack::stack_print(void)
{
for (int i=0; i<stop; i++)
cout<<stk[i];
cout<<endl;
}
int stack::create(void)
{
return !stop;
}
char menu()
{
char volba;
cout<<"\n";
cout<<" **********.\n";
cout<<"\n";
cout<<" a ... make new containers\n";
cout<<" b ... delete content\n";
cout<<" c ... enter string\n";
cout<<" d ... print on screen first stack\n";
cout<<" e ... print on screen first stack\n";
cout<<" f ... is it palindrom\n";
cout<<" x ... exit\n";
cout<<"\n your choice : ";
cin >> volba;
return volba;
}
int main() {
char palindrome[MAXSTACK];
char volba;
stack original,reversed;
int stackitems = 0,i;
//cin.getline(palindrome,MAXSTACK);
do{
volba = menu();
switch (volba)
{
case'a':
{
original.create();
reversed.create();
cout<<"done'";
break;
}
case'b':
{
original.emptystack();
reversed.emptystack();
cout<<"empty";
break;
}
case'c':
{
cout<<"enter your string"<<endl;
cin.get();
//cin.get();
cin.getline(palindrome,MAXSTACK);
for(int o = 0; o < strlen(palindrome); o++)
if (isalpha(palindrome[o]))
{
original.push(tolower(palindrome[o]));
stackitems++;
}
original.stack_print();
break;
}
case'd':
{
original.~stack();
for(int g = 0; g < strlen(palindrome); g++)
original.push(tolower(palindrome[g]));
original.stack_print();
}
/*//cin.getline(palindrome,MAXSTACK);
for(int g = 0; g < strlen(palindrome); g++)
if (isalpha(palindrome[g]))
{
original.push(tolower(palindrome[g]));
stackitems++;
}
}
original.stack_print();*/
break;
/*{
cout<<"original: ";
original.stack_print();
break;
}*/
break;
case'e':
{
cout<<"reversed:"<<endl;
for( i = 0; i < stackitems; i++) {
reversed.push(original.top());
original.pop();
}
reversed.stack_print();
}
break;
case'f':
{
for( i = 0; i < stackitems / 2; i++) {
reversed.push(original.top());
original.pop();
}
if (stackitems % 2)
original.pop();
while (!original.emptystack()) {
if (original.top() != reversed.top()) break;
original.pop(); reversed.pop();
}
if (original.emptystack())
cout << "it is palindrom\n";
else
cout << "not palindrom\n";
break;
}
default:cout<<"!??!";
}
} while(volba!='x');
}
You've explicitly called your stack's destructor. There is almost never a good reason to do this. If the stack is a local ("on the stack", hee hee), the compile will do it for you. If it's on the heap, created with new, call delete on it, which will cause the compiler to call the destructor.
case'd':
{
original.~stack();
You have commented palindrome reading :)
//cin.getline(palindrome,MAXSTACK);
There are a few things I would like to respond with. First, I think GMan, tpdi, and Vinay all have good points. This FAQ explains why calling the destructor on a local variable is a bad idea.
I realize this is just a simple homework problem and you are probably just trying to keep your stack class lightweight, but you might consider using a container class instead of an array of characters in your stack class.
Next, I'm not sure your emptystack and create functions are doing what you think they are doing. When you declare your original and reversed stack classes in the main program the memory is allocated for your internal character array. It's not really necessary in this case to have a create function. Perhaps if you were allocating memory on the heap for your character array, you would put that code into the create function (if you chose to leave it out of the constructor for some reason), but that's not the case here.
Similarly, emptystack isn't really doing anything. It would be better to have empty stack set the stop member variable to 0. At least that way the stack would appear to be empty the next time someone tried to use it.
There's a lot more that could be said about this class, but it might be better if you tried some of the suggestions here like using the std::stack and debugging. This is, after all, your homework assignment: it will help you a lot more in the future if you find the solution yourself!