Hi,
i am trying to make a dictionary which takes an english word and its meaning in spanish in the following format from an input file.
<english>:<spanish>

i also need to add words manually,remove,search,print ,and store new tree in the same file by updating the file.

my up() and load() are not working so cant read words and store them back to the file.
I would appropriate it if you help me.thanks

#include "Tree.h"
#include <iostream>
#include <string>
    #include <fstream>
    #include <string>
    #include <sstream>

using namespace std;

using std::cout;
using std::cin;

OrderTree tree;
void load() //inserting a word  into the tree. 
{
		string filename;
	  //the variable of type ifstream:
   std::cout << "Please enter the desired filename with it's extension:\t ";
    std::cin  >> filename;

    const char *file=filename.c_str();
    std::ifstream myfile(file, std::ios::in);

    if (!myfile.is_open())
    {
    cout << "Can't open file\n";
    }
	else if (myfile.is_open())
	{
    string line;
     
    // read one line at a time
    while (getline(myfile, line,':'))
    {
    stringstream sstrm(line);
  std::string English;
  std::string Spanish;
     
    if(sstrm >> English >> Spanish )
    {
		cout <<English<<":"<< Spanish <<endl;
    // two words extracted ...
    tree.insert(Order(English, Spanish));
	
    }
    }
	}

    }

void insert() //inserting a word  into the tree. 
{
  std::cout << 
    "Insert a word into the tree\n"
    "Enter a Word:\n <English> : <Spanish> ";
  std::string English;
  std::string Spanish;
  std::cin >> Spanish; 
	  std::cout << ":";
  std::cin >> Spanish;
  tree.insert(Order(English, Spanish));
  cout <<English<<":"<< Spanish <<endl;
}

void remove() //removing the first work order of a contractor from the tree
{
  std::cout << "Remove the first work order for a word from the tree" << std::endl;
  std::cout << "Enter word: ";
  unsigned English;
  std::cin >> English;
  std::cout << tree.remove(English) << std::endl;
}


void search()  //searching for the contractor in the tree
{
  std::cout << "Search for a word" << std::endl;
  std::cout << "Enter word: ";
  unsigned English;
  std::cin >> English;
  Order *foo = tree.search(English);
  if (foo)
    std::cout << *foo << std::endl;
  else
    std::cout << "word was not founded.";
}

void print() //printing the contents of the tree in sorted order
{
  std::cout << "Print the words" << std::endl;
  tree.inOrderPrint();
}
void up()
{
		    fstream file("example.txt", ios::out); //open for output
    file<< "Print the words" << std::endl;
  tree.inOrderPrint();
    file.seekp(6, ios::beg); //move the put cursor to start of "text"
    file<<"program for files"<<endl;
    file.close();
}
int menu()
{
  std::cout << 
    "1. Insert a word into the tree\n"
    "2. Remove \n"
    "3. Search for a word\n"
    "4. Print the words\n"
    "5. Quit\n"
	"6.Load\n"
    "Enter menu number: ";
  int n;
  std::cin >> n;
  return n;
}

int main()
{
  bool done = false;
  do
  {
    switch (menu())
    {
    case 1:
      insert(); //inserting a work order into the tree 
      break;
    case 2:
      remove(); //remove the first work order for a contractor from a tree
      break;
    case 3:

      search(); // search for a contractor
      break;
    case 4:
      print(); //printing the tree 
      break;
    case 5:
      done = true;
      break;
	  case 6:
      load(); //load data from a file 
      break;
	  case 7:
      up(); //updating the tree 
      break;
    }
  } while (!done);

}
Member Avatar for danb737

In your load() code, I see a problem. You read a piece of a line with while (getline(myfile, line,':')) because it stops at the first ':' it finds. Instead you should read the whole line, then make a stringstream and read until the ':'.

Here is another version which seems to work

void load() //inserting a word  into the tree.
{
    string filename;
    //the variable of type ifstream:
    std::cout << "Please enter the desired filename with it's extension:\t ";
    std::cin  >> filename;

    const char *file=filename.c_str();
    std::ifstream myfile(file, std::ios::in);

    if (!myfile.is_open())
    {
        cout << "Can't open file\n";
    }
    else if (myfile.is_open())
	{
        string line;

        // read one line at a time
        while (getline(myfile, line))
        {
            stringstream sstrm(line);
            std::string English;
            std::string Spanish;

            if(getline(sstrm, English,':'))
            {
                sstrm >> Spanish;
                cout <<English<<":"<< Spanish <<endl;
                // two words extracted ...
                tree.insert(Order(English, Spanish));
            }
        }
    }
}

For your up() function, I don't know how your Tree.h is implemented and so how the function tree.inOrderPrint(); works.
I'm just puzzled by file.seekp(6, ios::beg); //move the put cursor to start of "text" . What are you trying to achieve with this ?

oh thanks alot!
this is my code for inOrderPrint_:

void inOrderPrint_(Node *tree) const  // printing the contents of the tree in sorted order i.e InOrder Traversal 
  {
    if (tree)
    {
      inOrderPrint_(tree -> left);
      std::cout << tree -> data << std::endl;
      inOrderPrint_(tree -> right);
    }
  }

file.seekp(6, ios::beg); is for setting the start of where it starts to store in the file but i guess there is no need for it.

Member Avatar for danb737

First of all, your method is inOrderPrint_ but in the function up() you call tree.inOrderPrint() I would actually consider overloading the operators << and >> for the OrderTree class. So you could just write cout << tree; So you could define in your Tree.h header the following functions :

&istream operator<<(const OrderTree& tree, const istream& in)
{
    //Have some way to go through your tree like DFS or BFS and for each data you do
    in << tree.data << std::endl;

    //After going through all your tree, just return the stream
    return in;
}

&ostream operator>>(const OrderTree& tree, const ostream& out)
{
    //Have some way to go through your tree like DFS or BFS and for each data you do
    out >> tree.data >> std::endl;

    //After going through all your tree, just return the stream
    return out;
}

Maybe if you would post the entire Tree.h, I could help a bit more...

Thanks alot,you are so helpful :)
I have another problem in my tree that my english word is actually an unsigned number and i tried to change it to string but it didnt work.
I would appreciate it if you help me solve this problem as well.Thanks
here is my tree.h:

#pragma once
#include "Order.h"


class OrderTree
{
//private members of the class 
private:

  struct Node  // bst as a reference structure made up of nodes
  {
    Node *left;
    Order data;
    Node *right;
    Node(): left(0), right(0) {}
    Node &operator=(const Node &v)
    {
      left = v.left;
      data = v.data;
      right = v.right;
      return *this;
    }
  };

  Node *root;

  void insert_(Node *&tree, const Order &v) // inserting in the binary tree
  {
    if (tree)
    {
      if (v < tree->data)  // the node's left subtree has values which are strictly less than it .
		insert_(tree->left, v);
      else
		insert_(tree->right, v);  // the node's right subtree has values which are strictly greater than or equal to it .
    }
    
	else   //crating the first element of the tree
    {
      tree = new Node;
      tree -> left = 0;
      tree -> right = 0;
      tree -> data = v;
    }
  }

  double remove_(Node *&tree, unsigned v, bool &remove)  // to remove an element from the tree 
  {
    if (tree)
    {
      if (v > tree -> data.English())
		return remove_(tree -> right, v, remove);  //going to the right of the tree if the number is greater
      
	  else if (v < tree -> data.English())
		return remove_(tree -> left, v, remove);  // going to the left of the tree if the number is smaller
      
	  
	  else  //if the node to be deleted has only one child 
      {
		double c;
		if ((!tree -> left) && (tree -> right))   // if it has only right child
		{
			 Node *foo = tree -> right;
			 *tree = *(tree -> right);
			 delete foo;
		}
	
		else if ((tree -> left) && (!tree -> right)) // if it has only left child
		{
			Node *foo = tree -> left;
			*tree = *(tree -> left);
			delete foo;
		}

	else if ((!tree -> left) && (!tree -> right))  // if the node to be deleted does not have any children
	{
	  delete tree;
	  tree = 0;
	}
	else   // if the node to be deleted has 2 children
	{
	  Node **p = &(tree -> right);
	  Node *m = tree -> right;
	  while (m -> left)
	  {
	    p = &(m -> left);
	    m = m -> left;
	  }

	  tree -> data = m -> data;
	  *p = m -> right;
	  delete m;
	}
	remove = true;  // return true if remove was successful
	return c;
	  }
	}
    else
    {
      remove = false;  // return false if remove was unsuccessful 
      return 0;
    }
  }

  void removeAll_(Node *tree) // to delete all the nodes from the tree
  {
    if (tree)
    {
      removeAll_(tree->left);  //deleting the left subtrees 
      removeAll_(tree->right); //deleting the right subtrees 
      delete tree; 
    }
  }

  Order *search_(Node *tree, unsigned English) const  // to search the tree for a given contractor English
  {
    if (tree)
    {
      if (English == tree->data.English())
		return &(tree->data); // return the leaf if the contractor is found 
      
	  if (English > tree->data.English())
		return search_(tree->right, English);   // search the right subtree if the English is greater than the node 
      
	  if (English < tree->data.English())
		return search_(tree->left, English);  // search the left subtree if the English is lesser than the node
    }

    else
      return 0; //return 0, if the contractor English is not found 
  }

  void inOrderPrint_(Node *tree) const  // printing the contents of the tree in sorted order i.e InOrder Traversal 
  {
    if (tree)
    {
      inOrderPrint_(tree -> left);
      std::cout << tree -> data << std::endl;
      inOrderPrint_(tree -> right);
    }
  }
  void copy_(const Node *tree) //copy 
  {
    if (tree)
    {
      insert(tree->data);
      copy_(tree->left);
      copy_(tree->right);
    }
  }

public:

  OrderTree(): root(0) {}

  OrderTree(const OrderTree &v) // copy constructor of the class OrderTree 
  {
    copy_(v.root);
  }
  ~OrderTree() // destructor of the class - deletes the dynamically allocated memory
  {
    removeAll();
  }

  void insert(const Order &v)  //inserting a word into the tree. 
  {
    insert_(root, v);
  }
 
  double remove(unsigned English)  //removing the word
  {
    bool foo;
    return remove_(root, English, foo);
  }

  double removeContractor(unsigned English)
  {
    bool foo;
    double c = 0;
    do
    {
      c += remove_(root, English, foo);
    } while (foo);
    return c;
  }

 

  Order *search(unsigned English) const   //searching for the word in the tree
  {
    return search_(root, English);
  }

  void inOrderPrint() const  //printing the contents of the tree in sorted order.
  {
    inOrderPrint_(root);
  }
};

and my order.h:

#pragma once
#include <string>
#include <iostream>

class Order
{
// private members of the class
private:
  unsigned English_;
  std::string translation_;

public:
  Order(unsigned English = 0, const std::string &translation = ""): English_(English), translation_(translation)  
	  //constructor to take the English
	{

	}
  
	Order &operator=(const Order &v)  //copy constructor 
	{
		English_ = v.English_;
		translation_ = v.translation_;
		return *this;
    }

  unsigned English() const 
  { 
	  return English_;  // return the English
  }

  std::string translation() const 
  { 
	  return translation_; // return meaning
  }


  void settranslation(const std::string &v)
  {
    translation_ = v;
  } // getting an error message here 

  bool operator==(const Order& v) const { return English_ == v.English_; }
  bool operator!=(const Order& v) const { return English_ != v.English_; }
  bool operator<(const Order& v) const { return English_ < v.English_; }
  bool operator>(const Order& v) const { return English_ > v.English_; }
  bool operator<=(const Order& v) const { return English_ <= v.English_; }
  bool operator>=(const Order& v) const { return English_ >= v.English_; }
};

std::ostream &operator<<(std::ostream &s, const Order &o)  // print
{
  s << o.English() << ": " << o.translation();
  return s;
}

i figured out the string but output is not working.

Member Avatar for danb737

Would you please explain what's the goal of your project ? I understood it was some kind of dictionary, but now you're saying that the English word is actually an unsigned int ? That's confusing me.

I started the project with using unsigned int in my tree because it was easier to compare int in my tree .I also wasn't sure i can compare strings.but then i changed all unsigned ints to std::string and its working.Now i need some help with up().so want to put the tree in an output file.

I tried

void up()
{
	Order s;

		    fstream file("example.txt", ios::out); //open for output
    file<< s << std::endl;
  std::cout<< s;

    
    file.close();
}

but i only get one colon (:) in my output file.

so English is actually a string.and yes its some kind of dictionary.would appreciate it if you help me with it.thanks

Member Avatar for danb737

Ok, in that case, would you please post your latest code (order.h, tree.h and main.cpp) ?

The up() is actually the same.if you help me figure out how to do it with unsigned int then i change to string myself.assume English is an unsigned int,then how you do it?

Member Avatar for danb737

As you said, you need to put the whole tree in your file. So you need to traverse it and output that in your file. I assume you want the output to look similar to your print : <English>:<Spanish>.

In Order.h

std::ostream& operator<<(std::ostream &s, const Order &o)  // print
{
  s << o.English() << ":" << o.translation() << std::endl;
  return s;
}

In tree.h

class OrderTree
{
//private members of the class 
private:

  struct Node  // bst as a reference structure made up of nodes
  {
    Node *left;
    Order data;
    Node *right;
    Node(): left(0), right(0) {}
    Node &operator=(const Node &v)
    {
      left = v.left;
      data = v.data;
      right = v.right;
      return *this;
    }
  };

  std::ostream& operator<<(std::ostream& o, const Node* nod)
  {
    if (nod)
    {
      o << nod->left;
      o << nod->data;
      o << nod->right;
    }
    return o;
  }
 
  //Rest of the private code for OrderTree comes here

public:
  const Node* getRoot() {return root;} //returns the root of the Tree

  //Rest of the public code for OrderTree comes here

};

//And out of the OrderTree class definition
std::ostream& operator<<(std::ostream& o, const OrderTree& ordtree)
{
  o << ordtree.getRoot();
  return o;
}

And in main.cpp

void up()
{
    fstream file("example.txt", ios::out); //open for output
    file << tree;
    file.close();
}

As I don't have your code, I can't test what I suggest. It's probably full of little mistakes, but you'll get the general idea. You need for each of your class/structs to define how to overload the operator<<.

it says too many parameters for this operator function.

Member Avatar for danb737

As I said, I didn't try my code. Indeed I defined the operator<< inside the OrderTree class, and it then passes this as the first parameter, which is not what I wanted. So here is another attempt... Tell me if that's working for you ?

main.cpp

//////////////////////////////////////////////////////////////
//////main.cpp///
/////////////////////////////////////////////////////////////
//////Author:xxxxxxxxxxxxxx
/////////////////////////////////////////////////////////////
//////Student number:xxxxxxxxx
/////////////////////////////////////////////////////////////
//////Date of creation:July 14,2011
/////////////////////////////////////////////////////////////

#include "Tree.h"
#include <iostream>
#include <string>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

using std::cout;
using std::cin;

OrderTree tree;
void load() //inserting words from a file into the tree.
{
    string filename;
    //the variable of type ifstream:
    std::cout << "Please enter the desired filename with it's extension:\t ";
    std::cin  >> filename;

    const char *file=filename.c_str();
    std::ifstream myfile(file, std::ios::in);

    if (!myfile.is_open())
    {
        cout << "Can't open file\n";
    }
    else if (myfile.is_open())
	{
        string line;

        // read one line at a time
        while (getline(myfile, line))
        {
            stringstream sstrm(line);
            std::string English;
            std::string Klingon;

            if(getline(sstrm, English,':'))
            {
                sstrm >> Klingon;
                cout <<English<<":"<< Klingon <<endl;
                // two words extracted
                tree.insert(Order(English, Klingon));
            }
        }
    }
}
void insert() //inserting a word  into the tree.
{
  std::cout <<
    "Insert a word into the tree\n"
    "Enter a Word:\n <English> : <Klingon> ";
  std::string English;
  std::string Klingon;
  std::cin >> English;
	 // std::cout << "";
  std::cin >> Klingon;
  tree.insert(Order(English, Klingon));

  cout <<English<<":"<< Klingon <<endl;
}

void remove() //removing a word
{
  std::cout << "Remove a word" << std::endl;
  std::cout << "Enter word: ";
  std::string English;
  std::cin >> English;
  std::cout << tree.remove(English) << std::endl;
}


void search()  //searching for a word in the tree
{
  std::cout << "Search for a word" << std::endl;
  std::cout << "Enter word:";
  std::string English;
  std::cin >> English;
  Order *foo = tree.search(English);
  if (foo)
    std::cout << *foo << std::endl;
  else
    std::cout << "word was not founded.";
}

void print() //printing the contents of the tree
{
  std::cout << "Print the words" << std::endl;
  std::cout << tree;
}
void out()
{
    fstream file("example.txt", ios::out); //open for output
    file << tree;
    file.close();
    std::cout << "OUTPUT FILE CREATED - example.txt" << endl;
}
int menu()
{
  std::cout <<
    "\n1. Insert a word into the translator\n"
    "2. Remove a word from translator\n"
    "3. Search for a word\n"
    "4. Print the words\n"
    "5. Load a new file\n"
	"6. Save the file\n"
	"7. Quit\n"
    "Enter menu number: ";
  int n;
  std::cin >> n;
  return n;
}

int main()
{
	cout<< "Welcome to English to Klingon translator\n";
	load();
  bool done = false;
  do
  {
    switch (menu())
    {

    case 1:
      insert(); //inserting a word
      break;
    case 2:
      remove(); //remove a word
      break;
    case 3:
      search(); // search for a word
      break;
    case 4:
      print(); //printing the tree
      break;
	case 5:
      load(); //load data from a file
      break;
	case 6:
      out(); //updating the file
      break;
	case 7: //exit
      done = true;
      break;
    }
  } while (!done);

}

Tree.h

//////////////////////////////////////////////////////////////
//////Tree.h
/////////////////////////////////////////////////////////////
//////Author:xxxxxxxxxxx
/////////////////////////////////////////////////////////////
//////Student number:xxxxxxxxx
/////////////////////////////////////////////////////////////
//////Date of creation:July 14,2011
/////////////////////////////////////////////////////////////
#pragma once
#include "Order.h"

class OrderTree
{
//private members of the class
private:

    struct Node  // BST as a reference structure made up of nodes
    {
        Node *left;
        Order data;
        Node *right;
        Node(): left(0), right(0) {}
        Node &operator=(const Node &v)
        {
          left = v.left;
          data = v.data;
          right = v.right;
          return *this;
        }
    };

  Node *root;

  void insert_(Node *&tree, const Order &v) // inserting in the binary tree
  {
    if (tree)
    {
      if (v < tree->data)  // the node's left subtree has values which are less than it .
		insert_(tree->left, v);
      else
		insert_(tree->right, v);  // the node's right subtree has values which are greater than or equal to it .
    }

	else   //crating the first element of the tree
    {
      tree = new Node;
      tree -> left = 0;
      tree -> right = 0;
      tree -> data = v;
    }
  }

  double remove_(Node *&tree, std::string v, bool &remove)  // to remove an element from the tree
  {
    if (tree)
    {
      if (v > tree -> data.English())
		return remove_(tree -> right, v, remove);  //going to the right of the tree if the number is greater

	  else if (v < tree -> data.English())
		return remove_(tree -> left, v, remove);  // going to the left of the tree if the number is smaller


	  else  //if the node to be deleted has only one child
      {
		double c=0;
		if ((!tree -> left) && (tree -> right))   // if it has only right child
		{
			 Node *foo = tree -> right;
			 *tree = *(tree -> right);
			 delete foo;
		}

		else if ((tree -> left) && (!tree -> right)) // if it has only left child
		{
			Node *foo = tree -> left;
			*tree = *(tree -> left);
			delete foo;
		}

	else if ((!tree -> left) && (!tree -> right))  // if the node to be deleted does not have any children
	{
	  delete tree;
	  tree = 0;
	}
	else   // if the node to be deleted has 2 children
	{
	  Node **p = &(tree -> right);
	  Node *m = tree -> right;
	  while (m -> left)
	  {
	    p = &(m -> left);
	    m = m -> left;
	  }

	  tree -> data = m -> data;
	  *p = m -> right;
	  delete m;
	}
	remove = true;  // return true if remove was successful
	return c;
	  }
	}
    else
    {
      remove = false;  // return false if remove was unsuccessful
      return 0;
    }
  }

  void removeAll_(Node *tree) // to delete all the nodes from the tree
  {
    if (tree)
    {
      removeAll_(tree->left);  //deleting the left subtrees
      removeAll_(tree->right); //deleting the right subtrees
      delete tree;
    }
  }

  Order *search_(Node *tree, std::string English) const  // to search the tree for a given contractor English
  {
    if (tree)
    {
      if (English == tree->data.English())
		return &(tree->data); // return the leaf if the contractor is found

	  if (English > tree->data.English())
		return search_(tree->right, English);   // search the right subtree if the English is greater than the node

	  if (English < tree->data.English())
		return search_(tree->left, English);  // search the left subtree if the English is lesser than the node
    }

      return 0; //return 0, if the contractor English is not found
  }

  void copy_(const Node *tree) //copy
  {
    if (tree)
    {
      insert(tree->data);
      copy_(tree->left);
      copy_(tree->right);
    }
  }

public:

  OrderTree(): root(0) {}

  OrderTree(const OrderTree &v) // copy constructor of the class OrderTree
  {
    copy_(v.root);
  }
  ~OrderTree() // destructor of the class - deletes the dynamically allocated memory
  {
    removeAll();
  }

  const Node* getRoot() const {return root;} //returns the root of the Tree

  void insert(const Order &v)  //inserting a word into the tree.
  {
    insert_(root, v);
  }

  double remove(std::string English)  //removing the word
  {
    bool foo;
    return remove_(root, English, foo);
  }

  double removeContractor(std::string English)
  {
    bool foo;
    double c = 0;
    do
    {
      c += remove_(root, English, foo);
    } while (foo);
    return c;
  }

  void removeAll()    // removing all the work orders of a contractor from the tree.
  {
    removeAll_(root);
    root = 0;
  }

  Order *search(std::string English) const   //searching for the contractor in the tree
  {
    return search_(root, English);
  }


  //Print the tree in order of traversal to an output stream
  std::ostream& inOrderPrint(const Node *tree, std::ostream& out) const
    {
        if (tree)
        {
            inOrderPrint(tree -> left, out);
            out << tree -> data;
            inOrderPrint(tree -> right, out);
        }
        return out;
    }

};

std::ostream& operator<<(std::ostream& o, const OrderTree& ordtree)
{
  ordtree.inOrderPrint(ordtree.getRoot(), o);
  return o;
}

Order.h

//////////////////////////////////////////////////////////////
//////Order.h
/////////////////////////////////////////////////////////////
//////Author:xxxxxxxxxxxxx
/////////////////////////////////////////////////////////////
//////Student number:xxxxxxxxxxxx
/////////////////////////////////////////////////////////////
//////Date of creation:July 14,2011
/////////////////////////////////////////////////////////////
#pragma once
#include <string>
#include <iostream>
#include <string>
#include <fstream>
#include <string>
#include <sstream>
class Order
{
// private members of the class
private:
  std::string English_;
  std::string translation_;

public:
  Order(const std::string &English = "", const std::string &translation = ""): English_(English), translation_(translation)  
	  //constructor to take the English
	{
//std::cout << "order......" << endl;
	}
  
	Order &operator=(const Order &v)  //copy constructor 
	{
		English_ = v.English_;
		translation_ = v.translation_;
		return *this;
    }

  std::string English() const 
  { 
	  return English_;  // return the English
  }

  std::string translation() const 
  { 
	  return translation_; // return translation
  }


  void settranslation(const std::string &v)
  {
    translation_ = v;
  } // getting an error message here 

  bool operator==(const Order& v) const { return English_ == v.English_; }
  bool operator!=(const Order& v) const { return English_ != v.English_; }
  bool operator<(const Order& v) const { return English_ < v.English_; }
  bool operator>(const Order& v) const { return English_ > v.English_; }
  bool operator<=(const Order& v) const { return English_ <= v.English_; }
  bool operator>=(const Order& v) const { return English_ >= v.English_; }
};

std::ostream &operator<<(std::ostream &s, const Order &o)  // print
{
  s << o.English() << ":" << o.translation() << std::endl;
  return s;
}

Thanks alot! its working :)

Now I am trying to use a hash table instead of tree to sort the words from input file ,display words and again put them back to an output file.I was wondering if you can help me start it.Thanks!

Hi there.
I was reading your topic, which is very useful since I am doing the exact same thing.
I only have one question, what's inside de text file? I mean, how do you insert all the terms (or words)... What's the structure used?

I know this post is like a year old, but maybe you're still around.

Thanks!

Here Click Here, maybe this would help you.
Also, on further posts, please make your own thread if in need of assistance, and also, if the thread is more than 3 months old, there is no need to post inside of it.

Thank you very much!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.