views:

168

answers:

4

I'm trying to make a database and so far, I've been using strings to store my entries from a text file into an array, but this just isn't working out. Thus, I began thinking of a new way of doing it.

What I want to do:

Lets say I have a text file with the following database...

John Smith 00001 jsmith@email pw1

Rob Deniro 00002 rdeniro@email pw2

Al Pacino 00003 apacino@email pw3

Joe Pesci 00004 jpesci@email 307 pw4

Joaq Phoenix 00005 jphoe@email 208 pw5

John Madden 00006 jmadden@email 708 pw6

Alright, so basically what I'm stuck at is making this "inheritance" friendly. What's the best way to go about storing each entry? Individual strings? I've been thinking that the best way is to store each individual character until a whitespace occurs and then storing it into a string, but I'm not sure how that could be done.

A: 

Read one line at a time with ifstream and then use strtok to split each line, use the whitespace as the delimiter. You should use string except for the numeric values, which you can save as an int or a long if you need to support big values. It's also more wise to store the passwords in an encrypted way if you want security.

You might want to look for another solution to store your data instead of plain text for various reasons: Space, performance, security, ... It might be a good idea to try to use binary database files.

TomWij
I'm aware of ifstream, but when you say "read one line at a time" do you mean to use getline()?Also, I'm making a database, so passwords could be changed to anything, so int wouldn't work for them. Thanks for the reply
Yes, I mean using the module ifstream, and for reading a line getline() is indeed the method you want to call. I didn't state to save passwords as an int, only numeric values should be saved as ints. Besides that, another way of storing a password doesn't prevent it from being changed.
TomWij
Please note that I have added another paragraph to the answer.
TomWij
Sorry, misread you there. Anyway, would this work well with inheritance?
using white space for the delimiter would not work easily since the name can have multiple words as it is presented.
shoosh
It would only work if he decides to store the first name and last name apart, but indeed, another delimiter would be better. Reading data doesn't have much to do with inheritance, why would it affect that?
TomWij
strtok() not a good choice. It mutates the original string.
Martin York
+1  A: 

Usually the term "database" is reserved to the standard notion of a relational database such as MySQL, MS SQL Server, Oracle etc'

So this begs the question why don't you use a standard relational database?

you might want to try looking up TinySQL

shoosh
Exactly! Stop reinventing the wheel.
Joe Schneider
+3  A: 

As TomWij says, you do ifstream then strtok, but I'd recommend you escape your strings with "", not just spaces, that way you can store "something like this, for example a note about the user", that's how its done with CSV (comma separated values).

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;

void readCSV(std::istream &input, std::vector< std::vector<std::string> > &output)
{
    std::string csvLine;
    // read every line from the stream
    while( std::getline(input, csvLine) )
    {
     std::istringstream csvStream(csvLine);
     std::vector<std::string> csvColumn;
     std::string csvElement;
     // read every element from the line that is seperated by commas
     // and put it into the vector or strings
     while( std::getline(csvStream, csvElement, ',') )
     {
      csvColumn.push_back(csvElement);
     }  
     output.push_back(csvColumn);
    }
}

int main()
{
    std::fstream file("file.csv", ios::in);
    if(!file.is_open())
    {
     std::cout << "File not found!\n";
     return 1;
    }
    // typedef to save typing for the following object
    typedef std::vector< std::vector<std::string> > csvVector;
    csvVector csvData;

    readCSV(file, csvData);
    // print out read data to prove reading worked
    for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
    {
     for(std::vector<std::string>::iterator j = i->begin(); j != i->end(); ++j)
     {
      std::cout << *j << ", ";
     }
     std::cout << "\n";
    }
}

Which brings me to the real solution, why don't you use a CSV library like CSV module or better yet, SQLite, SQLite is dead easy to install and use, and its all around better than coding a database by hand, besides it shouldn't take you more than 1 hour to get SQLite into your codebase, since its API is REALLY easy.

#include <stdio.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
  int i;
  for(i=0; i<argc; i++){
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}

int main(int argc, char **argv){
  sqlite3 *db;
  char *zErrMsg = 0;
  int rc;

  if( argc!=3 ){
    fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
    exit(1);
  }
  rc = sqlite3_open(argv[1], &db);
  if( rc ){
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }
  rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
  if( rc!=SQLITE_OK ){
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  sqlite3_close(db);
  return 0;
}
Robert Gould
Hmmz, sad to see that sqlite3 doesn't throw exceptions to handle errors.
TomWij
Well SQLite is C compatible, so it can't throw errors, they don't exist in C, so you'd have to resort to longjmp, or errno (not thread safe) which aren't features many people like to use, thus errors must be handled like this. You should probably wrap it in C++ code.
Robert Gould
+1 for using SQLite
Dashogun
A: 
 #include<iostream>
 #include<conio.h>
 #include<fstream>
 using namespace std;




int main(int argc, char *argv[])



  {

     char Name[100];

     char FTE[100];
      cout<<"What is the file name?\n";
      cin>>FTE;

   ifstream myfile (FTE);     

   while(1)
    {


    myfile.getline(Name, 30, '|');
    cout<<line;
   cin.ignore();


 }
  }

all this does is read all your text entries seperated by the '|' Character. Good for making Flat File Databases in C++ and other using same methods.

H4cKL0rD