PDA

View Full Version : Saving Array to file Using Xcode.




Combinu
Jan 16, 2012, 05:51 PM
Hi to all.

Hereunder there is the code of a program that simply generates ascii codes for 0-9 and A-Z for serial numbers. for example it generates a line like this:
ABCDE-FGHIJ-KLMN0-12345-67899

I want to have 50,000 serial numbers to be generated and all saved to a single file output.txt

I first made the code and it only saved one thus the last one than i edited my code (as shown below) so that it opens the file and adds to a new line so that all serials are saved but it is not working. Can you please help me out with this procedure.
The code is as follows:
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>

void saveArray (char* array, int length);

int main (int argc, const char * argv[])
{
int n, l, ln;
int ascii[25] = {0};
char serial[25] = {0};

srand((unsigned)time(0));

for(int z=0; z<50000; z++)
{
for (int i =0; i < 25; i++)
{
ln = (rand()%2);

if (ln == 0)
{
n = (rand()%10)+48;
ascii[i] = n;
}
else if (ln == 1)
{
l = (rand()%26)+65;
ascii[i] = l;
}

serial[i] = static_cast<char>(ascii[i]);
}
saveArray(serial, 25);

}

}

void saveArray (char* array, int length)
{
std::fstream filestr;
std::ofstream output ("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt");

for (int j=0; j<length; j++)
{

//for (int k=0; k<5; k++)
// {
filestr.open ("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt", std::fstream::in | std::fstream::out | std::fstream::app);
filestr<<array[j]<<std::endl;

//}
}

}

Thanks & Regards
Combinu



lloyddean
Jan 16, 2012, 07:14 PM
#include <ctime>
#include <fstream>
#include <iostream>

const size_t COUNT_OF_SERIAL_NUMS = 50000;
const size_t LENGTH_SEGMENT * * * * = 5;
void generateNumericSeg(std::string& str, size_t count)
{
while ( count-- ) { str += ('0' + (rand() % (('9' - '0') + 1))); }
}

void generateAlphaSeg(std::string& str, size_t count)
{
while ( count-- ) { str += ('A' + (rand() % (('Z' - 'A') + 1))); }
}

int main(int argc, const char* argv[])
{
using std::string;
using std::ofstream;

srand(time(NULL));

ofstream ofs("ouput.txt");
if ( ofs.is_open() )
{
// example: ABCDE-FGHIJ-KLMN0-12345-67899
string str;
size_t sn = COUNT_OF_SERIAL_NUMS;
while ( sn-- )
{
str.clear();

generateAlphaSeg(str, LENGTH_SEGMENT); str += '-';
generateAlphaSeg(str, LENGTH_SEGMENT); str += '-';
generateAlphaSeg(str, LENGTH_SEGMENT); str += '-';
generateNumericSeg(str, LENGTH_SEGMENT); str += '-';
generateNumericSeg(str, LENGTH_SEGMENT); str += '\n';

ofs << str;
}

ofs.close();
}
}

thundersteele
Jan 16, 2012, 07:48 PM
I use fopen("path/to/file"), fprintf() to write stuff to files.

http://www.cplusplus.com/reference/clibrary/cstdio/fprintf/

example from that site:

/* fprintf example */
#include <stdio.h>

int main ()
{
FILE * pFile;
int n;
char name [100];

pFile = fopen ("myfile.txt","w");
for (n=0 ; n<3 ; n++)
{
puts ("please, enter a name: ");
gets (name);
fprintf (pFile, "Name %d [%-10.10s]\n",n,name);
}
fclose (pFile);

return 0;
}


just remove the puts() and gets() part of that example, and you have what you need.

Combinu
Jan 17, 2012, 02:34 AM
@lloyddean thanks for your reply with the code it works like a charm.
I showed it to my supervisors but it is not what they are looking for, instead i tried to work out on the type @thundersteele suggested.

This is the code i edited for my use:
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>
#include <stdio.h>


void saveArray (char* array, int length);

int main (int argc, const char * argv[])
{
int n, l, ln;
int ascii[25] = {0};
char serial[25] = {0};

srand((unsigned)time(0));

for(int z=0; z<50000; z++)
{
for (int i =0; i < 25; i++)
{
ln = (rand()%2);

if (ln == 0)
{
n = (rand()%10)+48;
ascii[i] = n;
}
else if (ln == 1)
{
l = (rand()%26)+65;
ascii[i] = l;
}

serial[i] = static_cast<char>(ascii[i]);
}
saveArray(serial, 25);

}

}

void saveArray (char* array, int length)
{

FILE * pFile;

pFile = fopen("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt", "r+");
for (int i; i<length; i++)
{
fprintf (pFile, "%c",array[i]);
}
fprintf(pFile, "\n");
fclose (pFile);

}

But still there seems to be a problem, when i open the output text file i only find 1 serial number not 50,000 there seems to be a problem with the saving, seems its saving only the last one.

Can you please help me out with this?

Thanks for both of you for your time!
Regards
Combinu

thundersteele
Jan 17, 2012, 03:39 AM
The following works, at least on my machine:


//#include <iostream>
#include <time.h>
#include <stdlib.h>
//#include <fstream>
#include <stdio.h>


int main (int argc, const char * argv[])
{
int n, l, ln;
int ascii[25] = {0};
char serial[25] = {0};

srand((unsigned)time(0));
FILE * pFile;

pFile = fopen("./crap.txt", "w");

for(int z=0; z<50000; z++)
{
for (int i =0; i < 25; i++)
{
ln = (rand()%2);

if (ln == 0)
{
n = (rand()%10)+48;
ascii[i] = n;
}
else if (ln == 1)
{
l = (rand()%26)+65;
ascii[i] = l;
}

serial[i] = static_cast<char>(ascii[i]);
fprintf (pFile,"%c",serial[i]);

}
fprintf(pFile,"\n");

}
fclose(pFile);

}

I'm not exactly sure what caused your problem. But the code was very non-optimal. For every serial, you opened and closed pFile, which is unnecessary. Doesn't exactly mean that my code is better... just different.

The most simple solution is to write every char to the console with printf(), and then execute the program as ./program > output.txt

If you must have a separate function to write the serial, you could consider to pass the pFile as an argument to the function (might need a pointer there).

You could also get away with just calling rand once:

ln = (rand()%36);

if (ln <10)
{
ascii[i] = ln+48;
}
else if (ln >10)
{
ascii[i] = ln+65;
}

That would also distribute the serials more evenly between numbers and characters... if that is desired.

Combinu
Jan 17, 2012, 04:31 AM
thanks very much i worked out the code you gave me it works fine now i have to save them in this format
xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
thus having a - between every group of 5 just like a serial number.

can you please help me out on this and very very thanks for you help it worked like a charm

chown33
Jan 17, 2012, 09:57 AM
void saveArray (char* array, int length)
{

FILE * pFile;

pFile = fopen("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt", "r+");
for (int i; i<length; i++)
{
fprintf (pFile, "%c",array[i]);
}
fprintf(pFile, "\n");
fclose (pFile);

}
When you fopen a file, it opens at location 0, which is the first byte of the file. Since you don't fseek() anywhere else, like to the end of the file, everything you write is simply rewriting the first bytes of the file.

There is different mode than "r+" you can pass to fopen that will open at the end of the file. That way you can avoid a separate fseek().

If you read the reference doc for fopen(), you should learn this. Any reference doc for fopen should tell you this, because fopen is a standard C function.

naples98
Jan 17, 2012, 10:35 AM
thanks very much i worked out the code you gave me it works fine now i have to save them in this format
xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
thus having a - between every group of 5 just like a serial number.

can you please help me out on this and very very thanks for you help it worked like a charm

lloyddean gave you the code to do this. You should study his code and figure out exactly what it is doing.

lloyddean
Jan 17, 2012, 11:37 AM
@lloyddean thanks for your reply with the code it works like a charm.
I showed it to my supervisors but it is not what they are looking for, instead i tried to work out on the type @thundersteele suggested.


So, they don't want something that works, is modular and simple.

What is wrong with something that works and is simple and easily modified?

For my own curiosity perhaps you can tell us more of your requirements?

lloyddean
Jan 17, 2012, 12:34 PM
NOTE: Modified my original code above to reflect actual stated original requirement.

Your code modified slightly to reduce dependancy upon hardcoded hard to decipher numbers.

Not tested nor compiled.


#include <cstdio>
#include <cstdlib>
#include <ctime>

#include <fstream>
#include <iostream>

#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))

const size_t COUNT_OF_SERIAL_NUMS = 50000;

const size_t COUNT_SEGMENTS = 5;
const size_t LENGTH_SEGMENTS = 5;
const size_t SIZE_BUFFER = ((COUNT_SEGMENTS) * (LENGTH_SEGMENTS)) + ((COUNT_SEGMENTS) - 1);

void saveArray(char* array, int length)
{
FILE* fp;
fp = fopen("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt", "r+");
for ( int i; i < length; i++ )
{
fprintf(fp, "%c", array[i]);
}

fprintf(fp, "\n");

fclose(fp);
}


int main(int argc, const char* argv[])
{
char ch;
char serial[SIZE_BUFFER] = { 0 };

srand(time(NULL));

for ( int z = 0; z < COUNT_OF_SERIAL_NUMS; z++ )
{
size_t counter = 0;
for (int i = 0; i < ARRAY_SIZE(serial); )
{
// although this doesn't appear to meet your original spec of:
// ABCDE-FGHIJ-KLMN0-12345-67899
if ( rand() % 2 )
{
// number chosen
ch = ('0' + (rand() % (('9' - '0') + 1)));
}
else
{
// letter chosen
ch = ('A' + (rand() % (('Z' - 'A') + 1)));
}

serial[i++] = ch;

if ( 0 == ((++counter) % LENGTH_SEGMENTS) )
{
serial[i++] = '-';
}
}

saveArray(serial, ARRAY_SIZE(serial));
}
}

thundersteele
Jan 18, 2012, 01:45 AM
thanks very much i worked out the code you gave me it works fine now i have to save them in this format
xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
thus having a - between every group of 5 just like a serial number.

can you please help me out on this and very very thanks for you help it worked like a charm

Try something like this:


if (i%5 == 0){
fprintf(pFile,"-");
}

Now, the tricky part would be to make sure that no serial number appears twice... because right now it's not a serial number... it's a random number. Of course, with 25 "digits" and 50k serials, the chance of getting the same number twice is quite small.


@chown33
Thanks for explaining why fprintf kept overwriting the serial instead of writing it in the next line.

lloyddean
Jan 18, 2012, 01:51 AM
thundersteele,

If I'm not mistaken that has already been integrated into my modification of his code among several other improvements.

chown33
Jan 18, 2012, 09:52 AM
void saveArray(char* array, int length)
{
FILE* fp;
fp = fopen("/users/manuelportelli/Documents/C++ Projects/Serial_Generator/Serial_Generator/ouput.txt", "r+");
for ( int i; i < length; i++ )
{
fprintf(fp, "%c", array[i]);
}

fprintf(fp, "\n");

fclose(fp);
}


Please read the reference doc for fopen().

This has the same problem I already pointed out. It opens at the beginning of the file. It doesn't seek to the end. Therefore, the fprintf() will always write to the beginning of the file. The result at the end of the program's run is one line in the file, the last line written.

On an efficiency note, if you can't think of a faster way to write chars to a FILE* than fprintf() and %c, you should look at fputc(). Or since the chars are in an array, see fwrite().

lloyddean
Jan 18, 2012, 11:05 AM
I suspect he's got something that works and we'll not hear from him again.

My mods to his code was never meant to correct bugs but simply to show how hard coded numbers could be replaced with something more meaningful and adaptable.

This really is a simple problem and shouldn't have taken much time at all to complete - which makes me think it was a test that he may not've ...

thundersteele
Jan 19, 2012, 02:32 AM
thundersteele,

If I'm not mistaken that has already been integrated into my modification of his code among several other improvements.

Yeah, right. Not sure why one would fix those parts that are not broken first - but who cares ;)

lloyddean
Jan 19, 2012, 11:28 AM
Perhaps because it had already been discussed and the stuff I addressed hadn't.