codetoad.com
  ASP Shopping CartForum & BBS
  - all for $20 from CodeToad Plus!
  
  Home || ASP | ASP.Net | C++/C# | DHTML | HTML | Java | Javascript | Perl | VB | XML || CodeToad Plus! || Forums || RAM 
Search Site:
Search Forums:
This 16 message thread spans 2 pages: [1]  2  > >  
  Lost!!!  newProgrammer19 at 04:41 on Sunday, December 03, 2006
 

so i have wrote this spreadsheet type program, and ran into some trouble. I need to be able to save the spreadsheet to file and then retrieve that file. I am new and know this a very basic project but any help would be very much a help to me. Cuz i am so lost on how to go about accomplishing it.


#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>

#include "CinReader.h"

using namespace std;

CinReader reader;

struct myCell
{
string currentValueOf;
string previousValueOf;
int myRow;
int myColumn;
myCell* referencesTo[100];
int sizeOfRef;
int theRefsUsed;
};

struct myRow
{
myCell* cells;
};

myRow* rows;



int sizeOfRow = 5;
int countOfRows = 5;
void cellContents (myCell& aCell);
void personalMainMenu ();
void editCell (myCell& aCell);
void print (myRow* rows, int size);
void print (myCell* myRow, int size);
void print (myCell aCell);
int main ()
{
rows = new myRow[countOfRows];
for (int j=0; j< countOfRows; j++)
{
rows[j].cells = new myCell[sizeOfRow];
for (int i=0; i< sizeOfRow; i++)
cellContents(rows[j].cells);
}

personalMainMenu();

delete [] rows;

return 0;
}
void personalMainMenu ()
{
int myRow = 0;
int myCell = 0;
int usersChoice = 0;
bool quit = false;
do
{
print(rows, countOfRows);
cout << "[1] Edit your cell\n";
cout << "[2] Save your spreadsheet\n";
cout << "[3] Retrieve your spreadsheet\n";
cout << "[0] Exit your spreadsheet \n";
cout << "Enter your choice: \n\n";
usersChoice = reader.readInt(true, 0, 3);
switch (usersChoice)
{
case 0:
quit = true;
break;
case 1:
cout << "Please enter a row number of your choice (1 - " << countOfRows << "): ";
myRow = reader.readInt(true, 1, countOfRows);
cout << "Please enter a cell number of your choice (1 - " << sizeOfRow << "): ";
myCell = reader.readInt(true, 1, sizeOfRow);
editCell(rows[myRow-1].cells[myCell-1]);
break;
case 2:// save to file
break;

case 3:// retreive from file
break;

}
} while (!quit);
}
void editCell (myCell& aCell)
{
int myRow = 0;
int myCell = 0;
bool quit = false;
cout << "[1] Data cell\n";
cout << "[2] Calculated cell\n";
cout << "your choice: ";
switch (reader.readInt(true, 1, 2))
{
case 1:
aCell.previousValueOf = aCell.currentValueOf;
cout << "\n\nCurrent value is -> \"" << aCell.currentValueOf << "\"\n\n";
cout << "Enter new data for the cell ->\t";
aCell.currentValueOf = reader.readString();
for (int i=0; i<aCell.currentValueOf.length(); i++)
{
if (aCell.currentValueOf == '\t')
aCell.currentValueOf = ' ';
}
break;
case 2:
if (aCell.theRefsUsed < aCell.sizeOfRef)
{
do
{
cout << "Enter your row #: ";
myRow = reader.readInt(true, 1, countOfRows);
cout << "Enter your cell #: ";
myCell = reader.readInt(true, 1, sizeOfRow);
aCell.referencesTo[aCell.theRefsUsed] = &rows[myRow-1].cells[myCell-1];
aCell.theRefsUsed++;
cout << "Would you like to edit another Cell (y/n)? ";
if (toupper(reader.readChar("YyNn")) == 'N')
quit = true;
} while (!quit && aCell.theRefsUsed < aCell.sizeOfRef);
}
break;
}

}
void print (myRow* rows, int size)
{
for (int i=0; i < size; i++)
print(rows.cells, sizeOfRow);
}
void print (myCell* myRow, int size)
{
for (int i=0; i<size; i++)
print(myRow);
cout << "\n\n";
}
void print (myCell aCell)
{
stringstream spreadSheet;
int theResultOf = 0;
if (aCell.theRefsUsed > 0)
{
for (int i=0; i<aCell.theRefsUsed; i++)
theResultOf += atoi(aCell.referencesTo->currentValueOf.c_str());
spreadSheet << theResultOf;
aCell.currentValueOf = spreadSheet.str();
}
string valueOfYourOutput = aCell.currentValueOf;
if (valueOfYourOutput.length() >= 10)
valueOfYourOutput = valueOfYourOutput.substr(0, 10);
else
{
int whatYaGotLeftOver = 10 - valueOfYourOutput.length();
stringstream strungOut;
int cushion = whatYaGotLeftOver/2;
for (int i=0; i < cushion; i++)
strungOut << " ";
if (whatYaGotLeftOver%2 == 1)
strungOut << " ";
strungOut << valueOfYourOutput;
for (int i = 0; i < cushion; i++)
strungOut << " ";
valueOfYourOutput = strungOut.str();
}
cout << "+ " << setw(10) << valueOfYourOutput << " +";
}

void cellContents (myCell& aCell)
{
aCell.currentValueOf = "";
aCell.previousValueOf = "";
aCell.myRow = 0;
aCell.myColumn = 0;
aCell.sizeOfRef = 100;
aCell.theRefsUsed = 0;
for (int i=0; i<aCell.sizeOfRef; i++)
aCell.referencesTo = NULL;
}


  Re: Lost!!!  Gord T at 18:20 on Sunday, December 03, 2006
 

You will first have to decide if you want to save the data as binary or text. Let's assume text for a momemt. Since your struct has int data in it, those numbers will
have to be converted to a string representation of a number with a function like itoa() before printing to a file.
I would print each line of the struct, line by line to a text file as well. The pointers can be cast to a long then
use ltoa() to convert long to a string. Your buffer to hold the string should also have a couple of extra bytes
to be padded with zero's. By using text, you can then open it with any text editor and check your data, as well as modifying
outside of your program. If you check recent postings in the c++ forum you will find several examples of how to handle reading/writing text files.(I posted some code in 'Reading Text Files Line By Line)
Printing to a file is very similar to printing to the screen. Unfortunatley I'm recovering from a major HD crash and will be down for several more days so I can't give you precise code today.But I'll be gald to help in more detail, it may be
a couple more days though. In the mean time, check out the code mentioned for ideas.
-Gord.

<Added>

Are you having trouble printing the correct data? The functions...
//.......................
void print (myRow* rows, int size)
{
for (int i=0; i < size; i++)
print(rows.cells, sizeOfRow);
}
//.......................
void print (myCell* myRow, int size)
{
for (int i=0; i<size; i++)
print(myRow);
cout << "\n\n";
}
//....................
//.....................
are giving me trouble. You are sending the same data over and over again.
But I don't think that is what you want. Maybe try...
//.............................
void print (myRow* rows, int size)
{
for (int i=0; i < size; i++)
{print(&rows.cells, sizeOfRow);}//Is sizeOfRow constant?
}
//.......................
void print (myCell* myRow, int size)
{
for (int i=0; i<size; i++)
{print(&myRow);}

cout << "\n\n";
}
//....................

<Added>

Oh no, the brackets with an i in them is not getting printed here. mmmm,
let me test... &test[j]

<Added>

okay so using j instead of i...
void print (myRow* rows, int size)
{
int j;
for (int j=0; j < size; j++)
{print(&rows.cells[j], sizeOfRow);}//Is sizeOfRow constant?
}
//.......................
void print (myCell* myRow, int size)
{
int j;
for (int j=0; j<size; j++)
{print(&myRow[j]);}

cout << "\n\n";
}


<Added>

second thought...
void print (myRow* rows, int size)
{
int j;
for (int j=0; j < size; j++) //print cells for this row
{print(rows[j].cells, sizeOfRow);}//Is sizeOfRow constant?
}


<Added>

// to help clarify...
void print_cells (myCell* cells, int size)
int j;
for (int j=0; j<size; j++)
{PrintCell(&cells[j]);}

cout << "\n\n";
}


<Added>

Well, I just got my compiler up and running so give me a day and I'll post a working solution for you.


<Added>

Ooookay. Here's what I came up with. I elected to just rewrite the entire thing. There are many ways of writing a database but I tried to choose a simple method. The program just writes/reads
text contained in cells. You will need to add code to handle the actual data manipulation after the data base has been read from a file (or writing to a file). At any rate, use any or all of the code as you see fit. It was just faster for me to rewrite something I could maybe explain better.
If there's any questions, just hollar. Also, error checking is minimal to keep program size here down. Anyways, written with Visual Studio 2005, console application, win32. Change _tmain() to main() if you have to....ect. I think you pretty much understand everything anyways...

Oh, heres a sample screen print-out of what to expect...
The (1,2) stuff is example data that represents (row,cell)
They could just as well be whole numbers or whatever you want.
//......................................

This is the preset data in our data base...
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)

Printing to file <C:\test_data_base.txt>...OK
Opening and reading file back...
Num rows = 3, cells_per_row = 6
Press c to continue, else abort...OK.
File read OK.
Reprinting read data...
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
Done, press any key...

//...................................
And here are the contents of the file. The first number is an ID so we know we have a valid data base file.
//.........................................
123456
3
6
(0,0)
(0,1)
(0,2)
(0,3)
(0,4)
(0,5)
(1,0)
(1,1)
(1,2)
(1,3)
(1,4)
(1,5)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(2,5)

//........................................................
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>
//...............................................
//......................................................
// Lost.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdlib.h"
#include "memory.h"
#include "string.h"
#include <iostream>
#include "conio.h"
#include "windows.h"
#include "stdio.h"
#include <fstream>
#include <sstream>

using namespace std;

//...................
// File structure:
// File begins with this information. Next
// follows the data base information.
#define FILE_ID "123456"
typedef struct file_header_s
{
long num_rows; //in data base
long cells_per_row; // in data base
}file_header_t;

//......................
//struct cell:
// Each cell in a row is comprised of this.
// I used a fixed array to hold the string. This keeps memory
//management easier and allows porting code to write binary files instead of text
//files.Size should be in multiples of 4 bytes.
//
#define SIZE_CELL_DATA 64
typedef struct cell_s
{
//a character array holds string representation of number
// only chData is stored in the file
char chData[SIZE_CELL_DATA];

// for reference if needed. Not stored in file.
//Not actually read in this example but is set.
long cell_number;
long row_number;

}cell_t;

//.......................
// struct data_base
// The header of where it begins.
//
typedef struct data_base_s
{
long num_rows;
long cells_per_row;

cell_t *cells; //all cells used in data base

}data_base_t;
//............................
//
// Prototypes
//
data_base_t * CreateDataBase(long num_rows,long cells_per_row);
void SetData(data_base_t * db,long row_num, long cell_num, char * chData);
cell_t *GetCell(data_base_t * db,long row_num, long cell_num);
void FreeDataBase(data_base_t * db);
void PrintDataToScreen(data_base_t * db);
void PrintDataToFile(data_base_t * db, char *file_path);
data_base_t * ReadDataFile(char * file_path);
//..........................
//
// main() or _tmain()
// whatever your compiler wants.
//
int _tmain(int argc, _TCHAR* argv[])
{
data_base_t *myData = (data_base_t *)0;
long num_rows,cells_per_row;
char file_path[160];

//Create a file path for testing. You can get this
// from user or else where.
memset(file_path,0,160);
strcpy_s(file_path,"/forum/Ctest_data_base.txt");

//Allocate for a 3 rows by 6 cells data base.
//You could get this info from a file or user.
// For now I'll just hard code the numbers here.
num_rows = 3;
cells_per_row = 6;

cout.flush();//why not.

//Create our data base.
myData = CreateDataBase(num_rows,cells_per_row);

cout << "This is the preset data in our data base..." << endl;
PrintDataToScreen(myData);

//write data to a file.
cout << endl << "Printing to file <" << file_path << ">..." ;
PrintDataToFile(myData,file_path);

//Open the file and read back the data.
cout << "Opening and reading file back..." << endl;

//Free memory and let's start from scratch;
FreeDataBase(myData);
myData = (data_base_t *)0;//habit
myData = ReadDataFile(file_path);

if(!myData) return 0; //user abort

//Reprint the data to verify.
cout << "Reprinting read data..." << endl;
PrintDataToScreen(myData);

cout << "Done, press any key...";
_getch();

//Free memory
FreeDataBase(myData);

return 0;
}//

//.................................
//
// CreateDataBase:
// Returns a fully allocated data base.
//
data_base_t * CreateDataBase(long num_rows,long cells_per_row)
{
data_base_t *db = (data_base_t *)0;
long nRow,nCell;
char buffer[SIZE_CELL_DATA];



//allocate for header
db = (data_base_t *)malloc(sizeof(data_base_t));
memset(db,0,sizeof(data_base_t)); //set all bytes to zero.(habit)

db->num_rows = num_rows;
db->cells_per_row = cells_per_row;

//allocate for all of the cells we will need.
db->cells = (cell_t*)malloc(num_rows * cells_per_row * sizeof(cell_t));

//For each cell, fill in some info.
//for this example, I am going to assign row-cell number
// to the data. Like... row 1 cell 3 = (1,3)
for(nRow = 0; nRow < num_rows; nRow++)
{
for(nCell = 0; nCell < cells_per_row; nCell++)
{
//example data...
memset(buffer,0,SIZE_CELL_DATA);
sprintf_s(buffer,"(%d,%d)",nRow,nCell);

//set it assignes it.
SetData(db,nRow,nCell,buffer);
}//x
}//y

return db;
}//

//........................................
//
// SetData:
// Sets a string (chData) and info for a given cell.
//
void SetData(data_base_t * db,long row_num, long cell_num, char * chData)
{
cell_t * cell;

cell = GetCell(db,row_num,cell_num);

cell->row_number = row_num;
cell->cell_number = cell_num;

memset(cell->chData,0,SIZE_CELL_DATA); //clear first.
strcpy_s(cell->chData,chData);

}//
//...................................
//
// GetData:
// returns a pointer to the cell given a row and cell number
//
cell_t *GetCell(data_base_t * db,long row_num, long cell_num)
{
return &db->cells[row_num * db->cells_per_row + cell_num];

}//
//.............................
//
// PrintDataToScreen:
// Just to show what's happening.
//
void PrintDataToScreen(data_base_t * db)
{
long nRow,nCell;
cell_t *cell = (cell_t*)0;

for(nRow = 0; nRow < db->num_rows; nRow++)
{
for(nCell = 0; nCell < db->cells_per_row; nCell++)
{
cell = GetCell(db,nRow,nCell);
cout << cell->chData << " ";
}
cout << endl;
}


}//
//........................................
//
// PrintDataToFile
// Prints a text file with the data.
// This will overwrite file if already exists.
//
void PrintDataToFile(data_base_t * db, char *file_path)
{

ofstream myfile (file_path); //open the file.
char new_line = 10; //end of line characters.NEED THIS.
char buffer[64];
long max_cells;


if (!myfile.is_open())
{
cout << "Error opening <" << file_path << ">" << endl;
return;
}//if

//First we need to write the ID number and start a new line.
//then number of rows,
//then number of cells per row.
//Then we can write actual string (cell) data.

//Get a string of our file ID
//write it with new-line character at end.
sprintf_s(buffer,"%s%c",FILE_ID,new_line);
myfile.write(buffer,(long)strlen(buffer));

//Same for rows...
sprintf_s(buffer,"%d%c",db->num_rows,new_line);
myfile.write(buffer,(long)strlen(buffer));

//same for cells...
sprintf_s(buffer,"%d%c",db->cells_per_row,new_line);
myfile.write(buffer,(long)strlen(buffer));

//now write each cell.
long nCell;
cell_t *cell = (cell_t*)0;

max_cells = db->num_rows * db->cells_per_row;

for(nCell = 0; nCell < max_cells; nCell++)
{
//write the cell data.
cell = &db->cells[nCell];//just point to it.
myfile.write(cell->chData,(long)strlen(cell->chData));
//add an end of line character.
myfile.write(&new_line,1);

}//for

myfile.close();
cout << "OK" << endl;

}//
//..........................
//
// ReadDataFile:
// Allocates for and reads in a data base file.
// The data is stored in the cell variable chData.
// What you do with it from there is up to you.
//
data_base_t * ReadDataFile(char * file_path)
{

data_base_t *db = (data_base_t*)0;
ifstream myfile (file_path); //open input stream for the file.
string line;

long num_rows, cells_per_row;

//check file open state.
if (!myfile.is_open())
{
cout << "Error opening <" << file_path << ">" << endl;
return (data_base_t*)0;
}//if

//Read first line, should be == FILE_ID
getline(myfile,line);

if(line != FILE_ID)
{
cout << "File <" << file_path << "> is not a valid data base. Exiting." << endl;
myfile.close();
return (data_base_t*)0;
}

//OK,next line should be num rows, followed by cells_per_row.
getline(myfile,line);
num_rows = atol(line.data());

getline(myfile,line);
cells_per_row = atol(line.data());

//Show the results and ask abort...
cout << "Num rows = " << num_rows << ", cells_per_row = " << cells_per_row << endl;
cout << "Press c to continue, else abort...";
if(_getch() != 'c')
{
cout << "aborted." << endl;
return (data_base_t*)0;
}
else
{
cout << "OK." << endl;
}

// Allocate for the data base and read in all data.
db = CreateDataBase(num_rows,cells_per_row);

if(!db)
{ myfile.close();
return db; ///bad
}

//Try and read rest of file, the data cells.
long max_cells,nCell;

max_cells = db->num_rows * db->cells_per_row;
for(nCell = 0; nCell < max_cells; nCell++)
{
if(myfile.eof())
{ cout << "error. reached end of file before all cells read. aborting." << endl;
FreeDataBase(db);
return (data_base_t *)0;
}
getline(myfile,line); //line contains the chData.
strcpy_s(db->cells[nCell].chData,line.data());//copy into data base cell.
}//for

myfile.close();
cout << "File read OK." << endl;
return db;
}
//.....................................
//
// FreeDataBase:
// Frees allocated memory on cleanup.
//
void FreeDataBase(data_base_t * db)
{
free(db->cells);
free(db);

}//
//............................
//end of file.

  Re: Lost!!!  newProgrammer19 at 08:56 on Monday, December 04, 2006
 

my compiler is giving me a couple areas, seeing as the program i use is Dev c++.
here is a couple of them.

stdafx.h: No such file or directory.
`strcpy_s' undeclared (first use this function)
`sprintf_s' undeclared (first use this function)

these are the only ones i get as errors. dev c++ is weird i like visual studio but i was programming on a unix platform. and so for practice i have this compiler. ne ways i think that these must be visual studio keywords or something. hit me back on what you think also, and did you compile this code by any chance? thanks again

  Re: Lost!!!  Gord T at 09:23 on Monday, December 04, 2006
 

If your not using visual studio 2005 get rid of that line
(#include "stdafx.h") and dont use the stdafx header file.Use what you normally use.
Then replace
_tmain() ...with
int main()
and begin trying to compile to see what headers you need. Post the errors...

<Added>

also strcpy_s is sort of new, try using the standard strcpy() instead.

<Added>

probably, anything with an _s appended to a functin name like the above or
sprintf_s will cause you problems. Try removing the _s part from the name.
e.g sprintf.

<Added>

More, Yes the code was compiled, built and run with Visual Studio 2005.
The _s parts on the names are new variations of the standard functions. They have enhanced security features while some just handle unicode better. I can still compile using the standard functions, I just get warnings-function is declared deprecated, meaning they are to be obsoleted down the road.

<Added>

I just downloaded DevC++ 4.9.9.2 and made the following changes to the code:
1 used main() instead of _tmain()
2 got rid of #include "stdafx.h"
3 replaced all occurances of strcpy_s with strcpy
4 replaced all occurances of sprintf_s with sprintf

Compiled and ran fine.
Let me know how you make out...


<Added>

first add #include <cstdlib> if not already, at top of .cpp page.(just for the record.)

  Re: Lost!!!  newProgrammer19 at 10:14 on Monday, December 04, 2006
 

i didnt get any errors after the changes. i was looking at the output of your code, and what i was trying to do with my code was allow the user to pick a row and cell of thier choice and then give that cell a value, and with that save the values or spreadsheet itself to a filename of their choice. and then allow the user to retrieve that file. cuz i am new to c++ looking and comparing your code has already helped me and i apreciate it so much. but is there any that you could show the code for what i was orginally trying to do(allow the user to pick a row and cell of thier choice and then give that cell a value, and with that save the values or spreadsheet itself to a filename of their choice). again thanks for the help, most people look at beginning programmers as some sort of virus. and it nice that someone took sometime out to help

  Re: Lost!!!  Gord T at 10:38 on Monday, December 04, 2006
 

Yeah I can do that. I just thought I'd get the crux of the code done first. Now it's just a matter of replacing
a few fixed values with user input values. I guess we can use cin for all of that stuff. gimme 1/2 hr, I'll grab a coffee and start er up.

<Added>

Does it matter what type of data your cells contain. Is text okay or do you require solid numbers?

<Added>

Here's an update to the code we already have.
I still have to add more as I go.
After this the next step is to let user modify cells and final step to save data base. Till then add this....

// 1...replace all of the previous main() code with this:

//...................
//
// main
//
//
int main(int argc, char *argv[])
{


char file_path[160]; //user file path.
data_base_t *myData = (data_base_t *)0; //our data base

memset(file_path,0,160); //clear it first always.

//Get user info and alloc new data base or open existing.
myData = PromtUserDataBaseInfo(file_path);

if(!myData)
{ system("PAUSE");
return 0; //error or user abort
}//if

// At this point we either have a full read-in data base
//or a fully allocated one.

// To do...place more code here.


//.........end of more code


FreeDataBase(myData);
system("PAUSE");

return EXIT_SUCCESS;
}//
//..........................

// 2 Add the prototype functions here, to just below the other prototypes at
// top of page.

long GetUserNumber();
data_base_t * PromtUserDataBaseInfo(char * file_path);

//...........................

// 3 Stick this code in somewhere.

//..........................
//
// PromtUserDataBaseInfo:
// This functions queries the user for information and returns a data base.
// If user selects to open an existing file, that is returned.
// If user opts to create new data base, one is allocated and returned.
// A null pointer (0) is returned if any errors.
// filepath recieves the filename user selects or names and must be
// pre-allocated.
//
data_base_t * PromtUserDataBaseInfo(char * file_path)
{
char chUserKey;
long num_rows,cells_per_row;
data_base_t * db = (data_base_t *)0;

//See if user wants to open and edit a file or create a new data base.
cout << "Please choose one of the following:" << endl << endl;
cout << "1...Open an existing file to edit. (Press 1)" << endl;
cout << "2...Create a new data base. (Press 2)" << endl;
cout << "Press any other key to cancel." << endl;
chUserKey = _getch();


if(chUserKey == '1') //open an existing file
{
cout << "Enter name of file to open..." << endl ;
cin >> file_path;
//try and read the file
db = ReadDataFile(file_path);
if(!db)
{
cout << "Could not read file <" << file_path << ">" << endl;
return (data_base_t*)0;
} //if
}
else if (chUserKey == '2') //create new data base
{
cout << "Enter name of file to save as..." << endl ;
cin >> file_path;

//We need to know how big a data base user wants to create.
cout << "How many rows will your data base need?...";
num_rows = GetUserNumber();

cout << "How many cells per row will your data base need?...";
cells_per_row = GetUserNumber();

//Create new data base
db = CreateDataBase(num_rows,cells_per_row);

if(!db)
{
cout << "Error creating data base <" << file_path << ">" << endl;
return (data_base_t*)0;
} //if
cout << "Data base created." << db->num_rows << " rows,"
<< db->cells_per_row << " cells per row." << endl;
}
else
{ cout << endl << "User aborted.";
return (data_base_t*)0;
}

return db;
}//
//............................

//
// Gets a number from the user.
//
//
long GetUserNumber()
{
char temp[80];
long user_num;

memset(temp,0,80);

while(!user_num)
{
cin >> temp;
user_num = atol(temp);
if(!user_num) cout << "invalid number,please try again..." ;
}//while

return user_num; //if we are here there were no errors.

}//
//.................................

<Added>

one little miss, in function GetUserNumber() , right before the while loop, be sure to set
user_num = 1;
before entering the loop. (This code is really fresh off the press.)

<Added>

doh, should have been...
user_num = 0;

<Added>

Here's the rest of the code. There's alot of cout stuff for purpose of debugging and so forth. It should be tested for a few days first, but hey, I'm goin for a coffee.
Hope this is what you want. May have to tweak up some odds and ends. Let me know.

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// 1 Put these new function prototypes with the others.
void UserSaveData(data_base_t * db, char * file_path);
void GoUserEdit(data_base_t *db);

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//2 Put these functions in somewhere...
//................................
//
// GoUserEdit:
// Let user edit cells
// Assumes data base is valid.
//
void GoUserEdit(data_base_t *db)
{

char chUserKey;
long nRow,nCell;
cell_t *cell = (cell_t*)0;
char user_data[SIZE_CELL_DATA];


cout << "Row range is 1 to " << db->num_rows << endl;
cout << "Cells per row range is 1 to " << db->cells_per_row << endl;

while(1) //loop forever
{
cout << endl << "To edit more cells press 1, else proceed to save as." << endl;
chUserKey = _getch();
if(chUserKey != '1') return; //all done here


cout << endl << "Which row do you want to edit? (1 is first)" << endl;

while(1)
{
nRow = GetUserNumber();
//check range
if((nRow >= 1) && (nRow <= db->num_rows)) break; //okay
cout << "Row value is out of range. Please try again. " << endl;

}//while row


cout << "Which cell in that row do you want to edit?(1 is first)" << endl;
while(1)
{
nCell = GetUserNumber();
//check range
if((nCell >= 1) && (nCell <= db->cells_per_row)) break; //okay
cout << "Cell value is out of range. Please try again. " << endl;

}//while cell

//our values are actually +1 so decrement them for use in array.
nRow--;
nCell--;

cell = GetCell(db,nRow,nCell);
cout << "The current value for this cell is " << cell->chData << endl;
cout << "Change value? (1 = yes)...";

chUserKey = _getch();
if(chUserKey != '1') continue; // skip rest of code and loop back to top.

cout << "Enter new value...";
memset(user_data,0,SIZE_CELL_DATA);
cin >> user_data;
SetData(db,nRow,nCell,user_data);


}//while root
}//
//..................
//
//
//
void UserSaveData(data_base_t * db, char * file_path)
{
char chUserKey;

cout << endl << "Save file <" << file_path << "> ? (press 1)";
chUserKey = _getch();

if(chUserKey != '1')
{ cout << endl <<"File not saved." << endl;
return;
} //if

PrintDataToFile(db,file_path);

}//
//............................


//xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//3 In the function FreeDataBase(), add this line before the rest, for robustness.
if(!db) return;
//...............

<Added>

oh, lol, and add this into main() in the 'todo' part.

// To do...more code here.

GoUserEdit(myData);

UserSaveData(myData,file_path);

//..end to do

<Added>

Just cleaning up the source.
I never did use...
//...............
typedef struct file_header_s
{
long num_rows; //in data base
long cells_per_row; // in data base
}file_header_t;
//.....................
//so that can be deleted.

//Also for DevC++ the only header files needed are:
#include <iostream>
#include "conio.h"
#include <fstream>
using namespace std;
//.............
//and for visual studio 2005 they are...
#include "stdafx.h"
#include <iostream>
#include "conio.h"
#include <fstream>
#include <sstream>
using namespace std;
//............
//
// Since main() code is not that big, here is the final version of main(), again.
// as per DevC++

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


char file_path[160]; //user file path.
data_base_t *myData = (data_base_t *)0; //our data base

memset(file_path,0,160); //clear it first always.

//Get user info and alloc new data base or open existing.
myData = PromtUserDataBaseInfo(file_path);
if(!myData)
{ system("PAUSE");
return 0; //error or user abort
}

GoUserEdit(myData);//Allow user cell edit.

UserSaveData(myData,file_path);//Allow user save file

FreeDataBase(myData);
system("PAUSE");

//system("PAUSE");
return EXIT_SUCCESS;
}//
//............................

<Added>

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// JUST ONE MORE, PROMISE
//Another update....in function CreateDataBase()
// right after these two lines...

...//allocate for all of the cells we will need.
...db->cells = (cell_t*)malloc(num_rows * cells_per_row * sizeof(cell_t));

//add this line to initialize all cells to zero...
memset(db->cells,0,num_rows * cells_per_row * sizeof(cell_t));
//xxxxxxxxxxxxxxxxxxxxxxxxxxx
//
//
// If you just want this program to handle text strings, then
// ignore the following code. Else read on.In fact, run the above first
// and see if that's okay.
// (mmm, hope this is not getting too big.Better stop for awhile.)
//
//xxxxxxxxxxxxxxxxxxxxxxxxxxx
//I have added the capability to store data types including...
//strings, byte, int, long, float and double.

//To do that, add the following above the code for the cell struct.
#define DATA_TYPE_STRING 0 //default
#define DATA_TYPE_BYTE 1
#define DATA_TYPE_INT 2
#define DATA_TYPE_LONG 3
#define DATA_TYPE_FLOAT 4
#define DATA_TYPE_DOUBLE 5
//then rewrite the cell struct to include added members as follows...
typedef struct cell_s
{
//a character array holds string representation of number
// only chData is stored in the file
char chData[SIZE_CELL_DATA];

// for reference if needed. Not stored in file.
//Not actually read in this example.
long cell_number;
long row_number;

//Extended info...new
// if first char is '%' then next character defines what type of data variable is.
// if there is no '%' character, then data is just a plain string.
//else the actual value is converted and
//stored in one of the relative variables below.
char is_extended_data; //0 if just a string, else one of the following values.
unsigned char bData; //DATA_TYPE_BYTE
int iData; //DATA_TYPE_INT
long lData; //DATA_TYPE_LONG
float fData; //DATA_TYPE_FLOAT
double dData; //DATA_TYPE_DOUBLE

}cell_t;
//.........................
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//add the function prototype...
void UpdateExtendedInfo(data_base_t *db);

//xxxxxxxxxxxxxxxxxxxxxxxxx
// add this function code...
//...........................
//
// UpdateExtendedInfo:
// updates the extended info stuff, like float-long-double data types.
// If first character in cell chData is '%' then the next character defines
// what type of data it is. Must be one of b,i,l,f,d else it is a standard string.
// If chData is an extended data type, then the appropriate data variable is set.
// e.g if chData contains %f3.14159 then it is a float and cell->fData contains 3.14159
// and cell->is_extended_data has a value of 4 or DATA_TYPE_FLOAT
//
void UpdateExtendedInfo(data_base_t *db)
{
if(!db) return ;

long j,max_cells;
cell_t *cell = (cell_t*)0;

max_cells = db->num_rows * db->cells_per_row;

for(j=0; j < max_cells; j++)
{
cell = &db->cells[j];

//if first character in chData is % then next character defines the data type.
cell->is_extended_data = 0; //should be anyways.
if(cell->chData[0] != '%') continue; //just a string.

//what type is it ?
switch (cell->chData)
{
case 'b': //byte
cell->is_extended_data = DATA_TYPE_BYTE;
cell->bData = cell->chData[2];
break;
case 'i': //int
cell->is_extended_data = DATA_TYPE_INT;
cell->iData = atoi(&cell->chData[2]);
break;
case 'l': //long
cell->is_extended_data = DATA_TYPE_LONG;
cell->lData = atol(&cell->chData[2]);
break;
case 'f': //float
cell->is_extended_data = DATA_TYPE_FLOAT;
cell->fData = (float)atof(&cell->chData[2]);
break;
case 'd': //double
cell->is_extended_data = DATA_TYPE_DOUBLE;
cell->dData = atof(&cell->chData[2]);
break;
default:
cell->is_extended_data = DATA_TYPE_STRING; //unknown, ignore


}//sw

}//for

}//
//.................................
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

//then in the main() function, place this line twice...
// before and after the GoUserEdit() function call like this...
UpdateExtendedInfo(myData); //new...get the extended info if any.
GoUserEdit(myData); //allow user cell edit.
UpdateExtendedInfo(myData); //do it again.
//...................
//
// no more unless asked, promise :)
//
//..................

<Added>

okay, this isn'tmy fault. Part of the code got mangled.
In function UpdateExtendedInfo(), at the switch() statement...
the code did not print properly.
So maybe this will print okay...
#define NUMBER_1 1

switch(cell->chData[ NUMBER_1 ])

  Re: Lost!!!  newProgrammer19 at 23:47 on Monday, December 04, 2006
 

ok i am getting some errors, i think cuz it is hard to see where to put in the new things and whatnot. is there any way you can copy and paste the updated code, with all the changes except for this part.

//xxxxxxxxxxxxxxxxxxxxxxxxxxx
//I have added the capability to store data types including...
//strings, byte, int, long, float and double.

//To do that, add the following above the code for the cell struct.
#define DATA_TYPE_STRING 0 //default
#define DATA_TYPE_BYTE 1
#define DATA_TYPE_INT 2
#define DATA_TYPE_LONG 3
#define DATA_TYPE_FLOAT 4
#define DATA_TYPE_DOUBLE 5
//then rewrite the cell struct to include added members as follows...
typedef struct cell_s
{
//a character array holds string representation of number
// only chData is stored in the file
char chData[SIZE_CELL_DATA];

// for reference if needed. Not stored in file.
//Not actually read in this example.
long cell_number;
long row_number;

//Extended info...new
// if first char is '%' then next character defines what type of data variable is.
// if there is no '%' character, then data is just a plain string.
//else the actual value is converted and
//stored in one of the relative variables below.
char is_extended_data; //0 if just a string, else one of the following values.
unsigned char bData; //DATA_TYPE_BYTE
int iData; //DATA_TYPE_INT
long lData; //DATA_TYPE_LONG
float fData; //DATA_TYPE_FLOAT
double dData; //DATA_TYPE_DOUBLE

}cell_t;
//.........................
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//add the function prototype...
void UpdateExtendedInfo(data_base_t *db);

//xxxxxxxxxxxxxxxxxxxxxxxxx
// add this function code...
//...........................
//
// UpdateExtendedInfo:
// updates the extended info stuff, like float-long-double data types.
// If first character in cell chData is '%' then the next character defines
// what type of data it is. Must be one of b,i,l,f,d else it is a standard string.
// If chData is an extended data type, then the appropriate data variable is set.
// e.g if chData contains %f3.14159 then it is a float and cell->fData contains 3.14159
// and cell->is_extended_data has a value of 4 or DATA_TYPE_FLOAT
//
void UpdateExtendedInfo(data_base_t *db)
{
if(!db) return ;

long j,max_cells;
cell_t *cell = (cell_t*)0;

max_cells = db->num_rows * db->cells_per_row;

for(j=0; j < max_cells; j++)
{
cell = &db->cells[j];

//if first character in chData is % then next character defines the data type.
cell->is_extended_data = 0; //should be anyways.
if(cell->chData[0] != '%') continue; //just a string.

//what type is it ?
switch (cell->chData)
{
case 'b': //byte
cell->is_extended_data = DATA_TYPE_BYTE;
cell->bData = cell->chData[2];
break;
case 'i': //int
cell->is_extended_data = DATA_TYPE_INT;
cell->iData = atoi(&cell->chData[2]);
break;
case 'l': //long
cell->is_extended_data = DATA_TYPE_LONG;
cell->lData = atol(&cell->chData[2]);
break;
case 'f': //float
cell->is_extended_data = DATA_TYPE_FLOAT;
cell->fData = (float)atof(&cell->chData[2]);
break;
case 'd': //double
cell->is_extended_data = DATA_TYPE_DOUBLE;
cell->dData = atof(&cell->chData[2]);
break;
default:
cell->is_extended_data = DATA_TYPE_STRING; //unknown, ignore


}//sw

this would help big time for clarity

  Re: Lost!!!  newProgrammer19 at 01:25 on Tuesday, December 05, 2006
 

[Linker error] undefined reference to `UserSaveData(data_base_s*, char*)'
is the only error i am getting. did you get this one too?

  Re: Lost!!!  newProgrammer19 at 01:41 on Tuesday, December 05, 2006
 

ok no more errors, after it compiles and runs when you press 2 to create a database. after you put how many cells per row you need and press enter. the program crashes and i am told there was an error with it. any suggestions?

<Added>

where do i set the user_num to 0?

  Re: Lost!!!  newProgrammer19 at 05:50 on Tuesday, December 05, 2006
 

it keeps crashing at that same point, i dont know why? any idea

  Re: Lost!!!  Gord T at 06:38 on Tuesday, December 05, 2006
 

There were some parsing issues when the code I pasted was converted to what you see here now but I think I noted all of them. I did not have any crashing problems or errors in testing but you may have missed something. One missed line could cuase problems,sooo, I can paste the entire updated version in a few minutes but first I will remove the extended-info code so that the program just handles text. I had also been making the user interface a little less ugly and working between two compilers so it'll take a few moments to recheck what I've got, then I'll post it and we'll go from there.


  Re: Lost!!!  newProgrammer19 at 07:15 on Tuesday, December 05, 2006
 

ok sounds good ya paste all the code i must have missed something. ne ways thanks again

  Re: Lost!!!  Gord T at 07:46 on Tuesday, December 05, 2006
 

I'll post in just a couple minutes, just making a UI change, just a visual thing, but before I do that...
what do you think about you starting a new thread called Lost Part 2, and I'll post the new code there and we can start fresh. Might be less confusing overall?

<Added>

Just testing unicode parsing...
test test (test) test[ 1 ]
Done test.
I'll just wait for your reply so I know where to post the code....

<Added>

another test...
test[ i ]

  Re: Lost!!!  newProgrammer19 at 07:50 on Tuesday, December 05, 2006
 

ok sounds good, also the values going into the cells are they numbers or anything user wants

  Re: Lost!!!  Gord T at 08:09 on Tuesday, December 05, 2006
 

The values going into the cells are strings only. The size of the string is fixed using constant SIZE_CELL_DATA which is currently set at 64 characters. Changing that value allows you to make the string (cells length) any length you want. It also allows storing string representations of numbers like floats.
Currently, I removed the conversion code that allowed changing these string-numbers back into numbers for manipulating but that is an code easy add-in if you want it later.

This 16 message thread spans 2 pages: [1]  2  > >  







CodeToad Experts

Can't find the answer?
Our Site experts are answering questions for free in the CodeToad forums
//








Recent Forum Threads
•  Re: Security - Code verify
•  Job @ EarlySail
•  Job @ EarlySail (perl)
•  IPC problem
•  Re: import contacts of msn/yahoo
•  Cookies and Threads C++
•  right justify a background in a table?
•  Help with Loop (C++/MFC)
•  Help with Loop (C++/MFC)


Recent Articles
ASP GetTempName
Decode and Encode UTF-8
ASP GetFile
ASP FolderExists
ASP FileExists
ASP OpenTextFile
ASP FilesystemObject
ASP CreateFolder
ASP CreateTextFile
Javascript Get Selected Text


© Copyright codetoad.com 2001-2007