vendredi 1 mai 2020

Out of Scope Error using private Inheritance

I'm working on stacks in C++ and I've created my own stack class that inherits privately from a linked list class I created. However, when I call a function of the stack class, I get an error saying that function was not declared in the scope. Here is the error message:

Stack.h|15|error: 'insertAtFront' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]|

Also, the implementation of my stack class is basically just using some member functions of my linked list class to implement push() and pop() functionality of my stack. Here is my stack header file:

#define STACK_H

#include "List.h" // List class definition

template< typename STACKTYPE >
class Stack : private List< STACKTYPE > 
{
public:
   // push calls the List function insertAtFront
   void push( const STACKTYPE &data ) 
   { 
      insertAtFront( data ); 
   } // end function push

   // pop calls the List function removeFromFront
   bool pop( STACKTYPE &data ) 
   { 
      return removeFromFront( data ); 
   } // end function pop

   // isStackEmpty calls the List function isEmpty
   bool isStackEmpty() const 
   { 
      return this->isEmpty();
   } // end function isStackEmpty

   // printStack calls the List function print
   void printStack() const 
   { 
      this->print();
   } // end function print 
}; // end class Stack

#endif

Here is my Linked List header file also

#ifndef LIST_H
#define LIST_H

#include <iostream>
#include "ListNode.h" // ListNode class definition
using namespace std;

template< typename NODETYPE >
class List
{
public:
   List(); // constructor
   ~List(); // destructor
   ListNode<NODETYPE> * getFirstPointer() const;
   List<NODETYPE> concatList(List<NODETYPE> &) const;
    List<NODETYPE> reverseList() const;
   int getSize();
   void BubbleSort(ListNode <NODETYPE> *) const;
   double sum();
   void insertAtFront( const NODETYPE & );
   void insertAtBack( const NODETYPE & );
   bool removeFromFront( NODETYPE & );
   bool removeFromBack( NODETYPE & );
   bool isEmpty() const;
   void print() const;
private:
   ListNode< NODETYPE > *firstPtr; // pointer to first node
   ListNode< NODETYPE > *lastPtr; // pointer to last node
   int list_size = 0; //size of linked list

   // utility function to allocate new node
   ListNode< NODETYPE > *getNewNode( const NODETYPE & );
}; // end class List

// default constructor
template< typename NODETYPE >
List< NODETYPE >::List()
   : firstPtr( 0 ), lastPtr( 0 )
{
   // empty body
} // end List constructor

// destructor
template< typename NODETYPE >
List< NODETYPE >::~List()
{
   if ( !isEmpty() ) // List is not empty
   {
      cout << "Destroying nodes ...\n";

      ListNode< NODETYPE > *currentPtr = firstPtr;
      ListNode< NODETYPE > *tempPtr;

      while ( currentPtr != 0 ) // delete remaining nodes
      {
         tempPtr = currentPtr;
         cout << tempPtr->data << '\n';
         currentPtr = currentPtr->nextPtr;
         delete tempPtr;
      } // end while
   } // end if

   cout << "All nodes destroyed\n\n";
} // end List destructor

template< typename NODETYPE >
ListNode< NODETYPE > * List<NODETYPE>::getFirstPointer() const{
    return firstPtr;
}

template< typename NODETYPE >
List< NODETYPE > List<NODETYPE>::concatList(List<NODETYPE> &listobj) const{
    if(listobj.isEmpty()){
        cout<<"Empty List, concat failed"<<endl;
        return *this;
    }
    else {
        ListNode<NODETYPE> *ptr = getFirstPointer();
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            listobj.insertAtBack(data);
            ptr = ptr->nextPtr;
        }

        return listobj;
    }
}

template < typename NODETYPE >
int List< NODETYPE >::getSize() {
    return list_size;
}

template < typename NODETYPE >
List< NODETYPE > List< NODETYPE >::reverseList() const{
    List< NODETYPE > listobj;
    if(this->isEmpty()){
        cout<<"Empty List, reverse failed"<<endl;
        return *this;
    }
    else {
        ListNode<NODETYPE> *ptr = firstPtr;
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            listobj.insertAtFront(data);
            ptr = ptr->nextPtr;
        }

        return listobj;
    }
}

template <typename NODETYPE>
void List< NODETYPE >::BubbleSort(ListNode< NODETYPE > *ptr) const{
    int swapped;
    NODETYPE temp;
    ListNode <NODETYPE> *ptr1;
    ListNode <NODETYPE> *ptr2 = 0;

    if (ptr == 0)
        return;
    do{
        swapped = 0;
        ptr1 = ptr; // assign initial pointer
        while(ptr1->nextPtr != ptr2){
            if(ptr1->data > ptr1->nextPtr->data){
                temp = ptr1->data;
                ptr1->data = ptr1->nextPtr->data;
                ptr1->nextPtr->data = temp;
                swapped = 1;
        } //end if
        ptr1 = ptr1->nextPtr;
    }//end while
        ptr2 = ptr1;
    }//end do
    while(swapped);
}

template <typename NODETYPE>
double List< NODETYPE >::sum(){
    double sum = 0;
    if(this->isEmpty()){
        cout<<"Empty List, sum is 0"<<endl;
        return 0;
    }
    else {
        ListNode<NODETYPE> *ptr = firstPtr;
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            sum += data;
            ptr = ptr->nextPtr;
        }//end while
    } //end else
     return sum;
}

// insert node at front of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtFront( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

   if ( isEmpty() ) // List is empty
      firstPtr = lastPtr = newPtr; // new list has only one node
   else // List is not empty
   {
      newPtr->nextPtr = firstPtr; // point new node to previous 1st node
      firstPtr = newPtr; // aim firstPtr at new node
   } // end else
   list_size += 1;
} // end function insertAtFront

// insert node at back of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtBack( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

   if ( isEmpty() ) // List is empty
      firstPtr = lastPtr = newPtr; // new list has only one node
   else // List is not empty
   {
      lastPtr->nextPtr = newPtr; // update previous last node
      lastPtr = newPtr; // new last node
   } // end else
   list_size += 1;
} // end function insertAtBack

// delete node from front of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromFront( NODETYPE &value )
{
   if ( isEmpty() ) // List is empty
      return false; // delete unsuccessful
   else
   {
      ListNode< NODETYPE > *tempPtr = firstPtr; // hold tempPtr to delete

      if ( firstPtr == lastPtr )
         firstPtr = lastPtr = 0; // no nodes remain after removal
      else
         firstPtr = firstPtr->nextPtr; // point to previous 2nd node

      value = tempPtr->data; // return data being removed
      delete tempPtr; // reclaim previous front node
      list_size = list_size - 1;
      return true; // delete successful
   } // end else
} // end function removeFromFront

// delete node from back of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromBack( NODETYPE &value )
{
   if ( isEmpty() ) // List is empty
      return false; // delete unsuccessful
   else
   {
      ListNode< NODETYPE > *tempPtr = lastPtr; // hold tempPtr to delete

      if ( firstPtr == lastPtr ) // List has one element
         firstPtr = lastPtr = 0; // no nodes remain after removal
      else
      {
         ListNode< NODETYPE > *currentPtr = firstPtr;

         // locate second-to-last element
         while ( currentPtr->nextPtr != lastPtr )
            currentPtr = currentPtr->nextPtr; // move to next node

         lastPtr = currentPtr; // remove last node
         currentPtr->nextPtr = 0; // this is now the last node
      } // end else

      value = tempPtr->data; // return value from old last node
      delete tempPtr; // reclaim former last node
      list_size = list_size - 1;
      return true; // delete successful
   } // end else
} // end function removeFromBack

// is List empty?
template< typename NODETYPE >
bool List< NODETYPE >::isEmpty() const
{
   return firstPtr == 0;
} // end function isEmpty

// return pointer to newly allocated node
template< typename NODETYPE >
ListNode< NODETYPE > *List< NODETYPE >::getNewNode(
   const NODETYPE &value )
{
   return new ListNode< NODETYPE >( value );
} // end function getNewNode

// display contents of List
template< typename NODETYPE >
void List< NODETYPE >::print() const
{
   if ( isEmpty() ) // List is empty
   {
      cout << "The list is empty\n\n";
      return;
   } // end if

   ListNode< NODETYPE > *currentPtr = firstPtr;

   cout << "The list is: ";

   while ( currentPtr != 0 ) // get element data
   {
      cout << currentPtr->data << ' ';
      currentPtr = currentPtr->nextPtr;
   } // end while

   cout << "\n\n";
} // end function print

#endif

And here is my implementation file

int main()
{
   Stack< int > intStack; // create Stack of ints

   cout << "processing an integer Stack" << endl;

   // push integers onto intStack
   for ( int i = 0; i < 3; i++ ) 
   {
      intStack.push( i );
      intStack.printStack();
   } // end for
   }

I've also run the example code in the textbook where I'm learning from and I get the same error. Any help with regards to why this program does not compile would be of great help to me. Thanks.

what is the most efficient way to find total number of distinct subarrays having distinct elements

here's the brute force method, counting distinct sets in set of sets. but well it's so inefficient can hardly call it a solution, appreciate your help. i have already tried hashing but couldn't come up with a solution

int main(){
  int n;
  cin>>n;
  int v[n];
  set<int>s;
  set<set<int>>a;
  for(int h=0;h<n;h++)
  cin>>v[h];
  for(int h=0;h<n;h++){
    for(int j=h;j<n;j++){
    s.insert(v[j]);
    a.insert(s);
    }
    s.clear();
  }
cout<<a.size();
}

Linux SIGSTOP causes waitpid to continue

I wrote a shell program for linux, and created the following code for pipe command:

void PipeCommand::execute() {
jobs_list->removeFinishedJobs();
if(signal(SIGTSTP , ctrlZHandlerPipe)==SIG_ERR) {
    perror("smash error: failed to set ctrl-Z handler");
    return;
}
if(signal(SIGINT , ctrlCHandlerPipe)==SIG_ERR) {
    perror("smash error: failed to set ctrl-C handler");
    return;
}
bool is_bg = false;
string new_command = command;
if (_isBackgroundComamnd(command.c_str())) {
    //Ends with &
    is_bg = true;

    char temp[COMMAND_ARGS_MAX_LENGTH];
    strcpy(temp, command.c_str());
    _removeBackgroundSign(temp);
    new_command = string(temp);
}

//Produce first and second command
int pipeIndex = new_command.find('|');
bool isStderrPipe = new_command[pipeIndex + 1] == '&';
string cmd1 = new_command.substr(0, pipeIndex);
string cmd2 = new_command.substr(pipeIndex + 1 + (int) isStderrPipe);

SmallShell &temp_smash = SmallShell::getInstance();
auto command1 = temp_smash.CreateCommand(cmd1.c_str());
auto command2 = temp_smash.CreateCommand(cmd2.c_str());

pid_t pid = fork();
if (pid < 0) {
    perror("smash error: fork failed");
    return;
} else if (pid == 0) {
    //Child
    setpgid(0,0);
    //pid_t gid = getpgid(0);
    //Create pipe
    int fd[2];
    if (pipe(fd) == -1) {
        perror("smash error: pipe failed");
        return;
    }

    pid_t pid_cmd1 = fork();
    if (pid_cmd1 < 0) {
        perror("smash error: fork failed");
        return;
    } else if (pid_cmd1 == 0) {

        //Child command 1
        if (isStderrPipe) {
            if (dup2(fd[1], STDERR_FILENO) == -1) {
                perror("smash error: dup2 failed");
                return;
            }
        } else {
            if (dup2(fd[1], STDOUT_FILENO) == -1) {
                perror("smash error: dup2 failed");
                return;
            }
        }
        close(fd[0]);
        close(fd[1]);
        command1->execute();
        exit(0);
    } else {

        //Parent command 1

        pid_t pid_cmd2 = fork();

        if (pid_cmd2 < 0) {
            perror("smash error: fork failed");
            return;
        } else if (pid_cmd2 == 0) {
            if (dup2(fd[0], STDIN_FILENO) == -1) {
                perror("smash error: dup2 failed");
                return;
            }
            close(fd[1]);
            close(fd[0]);
            command2->execute();
            exit(0);
        }
        else{
            close(fd[0]);
            close(fd[1]);

            int res1 = waitpid(pid_cmd1, nullptr, WUNTRACED);
            int res2= waitpid(pid_cmd2, nullptr, WUNTRACED);
            if (res1 == -1 || res2 == -1) {
                perror("smash error: waitpid failed");
                return;
            }
            exit(0);
        }
    }

} else {
    //Parent
    if (is_bg) {
        jobs_list->addJob(command, pid, false);
        return; //No need to wait...
    } else {
        jobs_list->setFg(command, pid, -1);
        int res = waitpid(pid, nullptr, WUNTRACED);
        if (res == -1) {
            perror("smash error: waitpid failed");
            return;
        }
        jobs_list->setFg("", -1, -1);
    }
    if(signal(SIGTSTP , ctrlZHandler)==SIG_ERR) {
        perror("smash error: failed to set ctrl-Z handler");
    }
    if(signal(SIGINT , ctrlCHandler)==SIG_ERR) {
        perror("smash error: failed to set ctrl-C handler");
    }
}

}

And the following handler for ctrZ which send SIGSTOP to the pipe and its inner commands:

void ctrlZHandlerPipe(int sig_num){
cout << "smash: got ctrl-Z" << endl;
SmallShell& smash = SmallShell::getInstance();
pid_t fg_pid = smash.getJobsList()->getFgPid();
if(fg_pid == smash.getSmashPid()){
    return;
}
if(fg_pid != -1){
    if(killpg(fg_pid, SIGSTOP) == -1){
        perror("smash error: kill failed");
    }
    else{
        if(!smash.getJobsList()->getBgToFg()){
            smash.getJobsList()->addJob(smash.getJobsList()->getFgCmd(),fg_pid, true);
        }
        else{
            smash.getJobsList()->getJobById(smash.getJobsList()->getFgId())->setJobStatus(false);
        }
        smash.getJobsList()->setFg("", -1, -1);
        smash.getJobsList()->setBgToFg(false);
        cout << "smash: process " << fg_pid << " was stopped" << endl;
    }
}
if(signal(SIGTSTP , ctrlZHandler)==SIG_ERR) {
    perror("smash error: failed to set ctrl-Z handler");
}

}

Now the problem is that while I run a pipe command, for example sleep 100|sleep 100, then pressing ctrlZ and then sending SIGCONT to the pipe again, it immediately continues and not waiting for its inner commands in the following lines:

int res1 = waitpid(pid_cmd1, nullptr, WUNTRACED);
int res2= waitpid(pid_cmd2, nullptr, WUNTRACED);

I cant figure out the problem might be..

Thank you

How could i aquire the source code for C++ library?For instance, std::thread

How could i aquire the source code for C++ library?For instance, std::thread.

If you could tell me a web site,that would be better.

Should type aliases be used in local or global scopes?

Should one alias c++ types locally or globally? I consider to use "using" or "typedef" to define type alias.

Exception 0xc0000005 i.e. Access Violition in C++

So I have been trying to eradicate this error for a few hours now but I was unable to. I am making a 2D game where I am reading different maps for different screens.

This is where I get the error. I call this in my main. Here, curr_map_ is a string and mapper is an object of Map.

curr_map_ = mapper.GetMapLabels();

Here is my Map class.

#include <mylibrary/map.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using mylibrary::Direction;
using mylibrary::Location;

int prev_row = 0;
int prev_col = 0;

namespace mylibrary {

Map::Map() = default;

Map::Map(std::vector<std::vector<char>> game_screen) {
  for (int i = 0; i < 16; i++) {
    for (int j = 0; j < 16; j++) {
      this->coordinates_[i][j] = game_screen[i][j];
    }
  }
}

void Map::ReadImageLabels() {
  std::string map_label_file = "C:/Users/monty/CLionProjects/cinder_0.9.2_vc2015/projects/Break/assets/background.txt";
  std::ifstream file(map_label_file);

  while(!file.eof()) {
    std::string map_label;
    std::getline(file, map_label);
    map_labels_.push_back(map_label);
  }
}

void Map::ReadGameScreens() {
  int map_line_count = 0;
  std::string maps_file = "C:/Users/monty/CLionProjects/cinder_0.9.2_vc2015/projects/Break/assets/maze.txt";
  std::ifstream file(maps_file);
  while (!file.eof()) {
    std::string map_line;
    std::getline(file, map_line);
    if (!map_line.empty()) {
      SetupMap(map_line);
      map_line_count++;


      if (map_line_count == 16) {
        Map game_screen = Map(map_);
        game_maps_.push_back(game_screen);

        map_line_count = 0;
        map_.clear();
      }
    }
  }
}

void Map::SetupMap(std::string map_line) {
  std::vector<char> map_line_char;
  map_line_char.reserve(16);
  for (int i = 0; i < 16; i++) {
    map_line_char.push_back(map_line.at(i));
  }
  map_.push_back(map_line_char);
}

std::string Map::GetMapLabels() {
  for (int i = 0; i < map_labels_.size(); i++) {
    if (i == screen_num_) {
      return map_labels_[i];
    }
  }
}

std::vector<Map> Map::GetScreen() {
  return game_maps_;
}

bool Map::IsScreenChange() {
  return is_screen_change_;
}

int Map::GetNewScreenNum() {
  return screen_num_;
}

Location Map::GetPlayerNewLoc(const Map& curr_map, Engine engine) {
  Location location = engine.GetPrisoner().GetLoc();
  int curr_row = location.Col();
  int curr_col = location.Row();

  for (int j = 0; j < entry_points_.size(); j++) {
    if (curr_map.coordinates_[curr_row][curr_col] == entry_points_.at(j)) {
      screen_num_ = GetTransitionScreenNum(GetCurrScreenNum(curr_map),
                                           entry_points_.at(j));
      is_screen_change_ = true;
      if (engine.GetDirection() == Direction::kUp) {
        return {curr_col, 11};
      } else if (engine.GetDirection() == Direction::kDown) {
        return {curr_col, 1};
      } else if (engine.GetDirection() == Direction::kLeft) {
        return {14, curr_row};
      } else if (engine.GetDirection() == Direction::kRight) {
        return {1, curr_row};
      }
    }
  }

}

int Map::GetCurrScreenNum(const Map& curr_map) {
  int count = 0;
  for (int i = 0; i < game_maps_.size(); i++) {
    for (int j = 0; j < 16; j++) {
      for (int k = 0; k < 16; k++) {
        if (game_maps_[i].coordinates_[j][k] == curr_map.coordinates_[j][k]) {
          count++;
        } else {
          count = 0;
          goto outerloop;
        }
        if (count == 256) {
          return i;
        }
      }
    }
    outerloop:;
  }
}

int Map::GetTransitionScreenNum(int num, char entry) {
  for (int i = 0; i < game_maps_.size(); i++) {
    if (i != num) {
      for (int j = 0; j < 16; j++) {
        for (int k = 0; k < 16; k++) {
          if (game_maps_[i].coordinates_[j][k] == entry) {
            return i;
          }
        }
      }
    }
  }
}

}  // namespace mylibrary

My text files are -

maze.txt

1111111111111111
0000000100100101
1011110100000101
1010010001110001
1010110001010111
1011010100000001
1010010111101101
1000010100100101
1011011100101100
1001000000110001
1001001110001111
1011101000000001
1010001000110111
1011011011100111
10000100101000d1
1111111111111111

aaaaaaaaaaaaaaaa
bbbbbbbabbabbaba
abaaaababbbbbaba
ababbabbbaaabbba
ababaabbbababaaa
abaabababbbbbbba
ababbabaaaabaaba
abbbbababbabbaba
abaabaaabbabaaab
abbabbbbbbaabbba
abbabbaaabbbaaaa
abaaababbbbbbbba
ababbbabbbaabaaa
abaabaabaaabbadd
ddbbbabbababbbdd
aaaaaaaaaaaaaaaa

background.txt

maze1.png
maze2.png

Any help will be appreciated.

Selection Sort - Array vs Vector

I implemented SelectionSort algorithm in C++ both using simple arrays and vectors. Tested them with random samples in range [1, 65535]. Here are the results:

+-------------+-------------------+--------------------+
| Sample Size | Time for impArray | Time for impVector |
+-------------+-------------------+--------------------+
|      50     |      9.263 ns     |      32.329 ns     |
+-------------+-------------------+--------------------+
|     500     |     471.537 us    |     3039.441 us    |
+-------------+-------------------+--------------------+
|     5000    |     117.911 ms    |     1202.402 ms    |
+-------------+-------------------+--------------------+

If this were a time critical application with big sample sizes, implementations would differ a lot. I want to ask the reason of big execution time differences between two implementations?

Sorting.h
#ifndef SORTING_ALGORITHMS_H
#define SORTING_ALGORITHMS_H

#include <utility>
#include <vector>
//#include <iterator>
#include <algorithm>

namespace etpc
{

    template <class T>
    void sortSelection(T* pArrHead, int i32ArrSize)
    {
        int i32SmallestIndex;
        for(int i=0; i<i32ArrSize-1; i++)
        {
            i32SmallestIndex = i;
            for(int j=i+1; j<i32ArrSize; j++)
            {
                if(pArrHead[j] < pArrHead[i32SmallestIndex])
                    i32SmallestIndex = j;
            }
            if(i32SmallestIndex != i)
            {
                std::swap(pArrHead[i], pArrHead[i32SmallestIndex]);
            }
        }
    }

    // Based on the following answer
    // https://codereview.stackexchange.com/a/177919/206877
    // typename vs class
    // https://stackoverflow.com/questions/2023977/difference-of-keywords-typename-and-class-in-templates
    template <class T>
    void sortSelection(std::vector<T>& vArrHead)
    {
        typename std::vector<T>::iterator it;
        for(it = vArrHead.begin(); it != vArrHead.end(); it++)
        {
            std::iter_swap(it, std::min_element(it, vArrHead.end()));
        }
    }

}
#endif // SORTING_ALGORITHMS_H
Main.cpp
#include "Sorting.h"
#include <iostream>
#include <chrono>

template <class T>
void printArr(T* pArrBegin, int i32ArrSize)
{
    for(int i=0; i<i32ArrSize; i++)
    {
        std::cout << pArrBegin[i] << " ";
    }
    std::cout << '\n';
}

template <class T>
void printVect(std::vector<T>& vArrHead)
{
    for (auto elem : vArrHead)
        std::cout << elem << " ";
    std::cout << '\n';
}


int main()
{
    std::chrono::steady_clock::time_point begin;
    std::chrono::steady_clock::time_point end;

    static const int i32Size = 1;
    int arr[i32Size] = {0};
    begin = std::chrono::steady_clock::now();
    etpc::sortSelection<int>(arr, i32Size);
    end = std::chrono::steady_clock::now();
    std::cout << "Time difference impArray = " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() << "[ns]" << std::endl;
    //printArr<int>(arr, i32Size);

    std::vector<int> v = {1};
    begin = std::chrono::steady_clock::now();
    etpc::sortSelection<int>(v);
    end = std::chrono::steady_clock::now();
    std::cout << "Time difference impVector = " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count() << "[ns]" << std::endl;
    //printVect(v);

    return 0;
}