Saving Array to file Using Xcode.

Discussion in 'Mac Programming' started by Combinu, Jan 16, 2012.

  1. macrumors newbie

    Joined:
    Sep 24, 2011
    #1
    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:
    Code:
    #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
     
  2. lloyddean, Jan 16, 2012
    Last edited: Jan 17, 2012

    macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #2
    Code:
    #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();
        }
    }
    
     
  3. macrumors 68030

    Joined:
    Oct 19, 2011
    Location:
    Switzerland
    #3
    I use fopen("path/to/file"), fprintf() to write stuff to files.

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

    example from that site:
    Code:
    /* 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.
     
  4. thread starter macrumors newbie

    Joined:
    Sep 24, 2011
    #4
    @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:
    Code:
    #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
     
  5. macrumors 68030

    Joined:
    Oct 19, 2011
    Location:
    Switzerland
    #5
    The following works, at least on my machine:

    Code:
    //#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:
    Code:
            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.
     
  6. thread starter macrumors newbie

    Joined:
    Sep 24, 2011
    #6
    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
     
  7. macrumors 603

    Joined:
    Aug 9, 2009
    #7
    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.
     
  8. macrumors member

    naples98

    Joined:
    Sep 9, 2008
    Location:
    Houston
    #8
    lloyddean gave you the code to do this. You should study his code and figure out exactly what it is doing.
     
  9. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #9
    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?
     
  10. lloyddean, Jan 17, 2012
    Last edited: Jan 17, 2012

    macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #10
    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.

    Code:
    #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));
        }
    }
    
     
  11. macrumors 68030

    Joined:
    Oct 19, 2011
    Location:
    Switzerland
    #11
    Try something like this:

    Code:
    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.
     
  12. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #12
    thundersteele,

    If I'm not mistaken that has already been integrated into my modification of his code among several other improvements.
     
  13. chown33, Jan 18, 2012
    Last edited: Jan 18, 2012

    macrumors 603

    Joined:
    Aug 9, 2009
    #13
    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().
     
  14. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #14
    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 ...
     
  15. macrumors 68030

    Joined:
    Oct 19, 2011
    Location:
    Switzerland
    #15
    Yeah, right. Not sure why one would fix those parts that are not broken first - but who cares ;)
     
  16. macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #16
    Perhaps because it had already been discussed and the stuff I addressed hadn't.
     

Share This Page