Thread: Pass 2d array to function

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    216

    Pass 2d array to function

    Hello, I'm having a problem with the following code. I need to be able to pass several functions the data from a 2d array. I will be passing filenames. Here is the code.

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BUFFER_SIZE 4096
    
    // Error function for outputting error
    void Error(char *output)
    {
        MessageBox(NULL, output, "Error", MB_OK);
        //PostQuitMessage(1);
        exit(1);
    }
    
    // Functions to obtain file information
    long int GetFileSize(char **fileName)
    {
        long int fileSize;
    
        FILE *fp = fopen(fileName, "rb");
    
        fseek(fp, 0, SEEK_END);
        fileSize = ftell(fp);
        fclose(fp);
        return fileSize;
    }
    
    int min3(size_t a, size_t b, size_t c)
    {
          if (a < b)
             return a < c ? a : c;
          else
             return b < c ? b : c;
    }
    
    FILE *OpenVolumeFile(char **archiveName, int volume)
    {
          char volumeName[256];
          printf("Volume: %i\n", volume);
    
          FILE *fArchive;
    
          if (volume > 0)
              sprintf(volumeName, "%s-%d", archiveName, 0);
    
          else
             sprintf(volumeName, "%s", archiveName);
    
          if (!(fArchive = fopen(volumeName, "wb"))) Error("No file handle\n");
    
          return fArchive;
    
    }
    
    size_t ReadBuffer(FILE *fin, char *buffer, size_t bytesToRead)
    {
          size_t bytesRead;
    
          bytesRead = fread(buffer, 1, bytesToRead, fin);
          if(bytesRead < bytesToRead) Error("fread failure");
    
          return bytesRead;
    
    }
    
    // Write file header
    void WriteArchiveHeaderRecord(FILE* out, char **fileName, int fileNameLen, int fileSize)
    {
         // write filesize to bin
         if( fwrite(&fileSize, sizeof(fileSize), 1, out) != 1) Error("Could not write filesize header\n");
    
         // write filename length to bin
         if( fwrite(&fileNameLen, sizeof(fileNameLen), 1, out) != 1) Error("Could not write filename length to header\n");
    
         // write filename to header
         if( fwrite(fileName, 1, fileNameLen, out) != fileNameLen) Error("Could not write filename to header\n");
    
    }
    
    size_t WriteArchiveHeader(FILE *fArchive, size_t volSize, int numFiles,
                              char **fileNames, size_t *fileSizes)
    {
          size_t headerSize = sizeof numFiles + sizeof volSize +
                              numFiles * (sizeof *fileSizes + sizeof (size_t));
          int i;
    
          if( fwrite(&numFiles, sizeof(numFiles), 1, fArchive) != 1) Error("Error writing number of files to bin\n");
    
          if( fwrite(&volSize, sizeof(volSize), 1, fArchive) != 1) Error("Error writing volume size to bin\n");
    
          for(i = 0; i < numFiles; i++)
          {
                    size_t fileNameLen = strlen(&fileNames[i]);
    
                    WriteArchiveHeaderRecord(fArchive, &fileNames[i], fileNameLen, fileSizes[i]);
    
                    printf("Filename: %s\tSize: %i\tFilename Length: %i\n", &fileNames[i], fileSizes[i], fileNameLen);
    
                    headerSize += fileNameLen;
    
          }
    
          printf("Wrote file header -> Size: %d\n\n", headerSize);
    
          return headerSize;
    }
    
    // Write file to bin
    void WriteBuffer(FILE* out, char *buffer, size_t size)
    {
        // write data to outfile
        if( fwrite(buffer, 1, size, out) != size)  Error("Error writing file to bin\n");
    
    }
    
    void CreateArchive(char **archiveName, size_t  volSize, int numFiles, char *fileNames)
    {
          FILE   *fArchive;
    
          size_t  volBytesLeft;
          size_t  headerSize;
          size_t  fileSizes[numFiles]; // I got rid of the "file" struct
    
          int     i;
          int     volume = 0;
    
          for(i = 0; i < numFiles; i++)
                fileSizes[i] = GetFileSize(&fileNames[i]);
    
          fArchive = OpenVolumeFile(archiveName, volSize); // volSize>0 ? ++volume : 0
    
          headerSize = WriteArchiveHeader(fArchive, volSize, numFiles, fileNames, fileSizes);
    
          if (volSize > 0)
             volBytesLeft = volSize - headerSize;
    
          else
             volBytesLeft = BUFFER_SIZE + 1; // ensure that it's greater than buffer size
    
          for(i = 0; i < numFiles; i++)
          {
                    size_t fileBytesLeft = fileSizes[i];
    
                    FILE *fData = fopen(&fileNames[i], "rb");
                    if(fData == NULL)  Error("Error opening file\n");
    
                    printf("File %i: %.2f MB\n", i + 1, (double)fileSizes[i] / 1024 / 1024);
    
                    do
                    {
                                  char buffer[BUFFER_SIZE];
                                  size_t bytesToRead, bytesRead;
    
                                  if(volBytesLeft <= 0)
                                  {
                                                    fclose(fArchive);
    
                                                    fArchive = OpenVolumeFile(archiveName, ++volume);
    
                                                    volBytesLeft = volSize;
                                  }
    
                                  bytesRead = ReadBuffer(fData, buffer, bytesToRead);
    
                                  bytesToRead = min3(sizeof buffer, fileBytesLeft, volBytesLeft);
    
                                  WriteBuffer(fArchive, buffer, bytesRead);
    
                                  fileBytesLeft -= bytesRead;
    
                                  if (volSize > 0)
                                     volBytesLeft -= bytesRead;
    
                    }
                    while(fileBytesLeft > 0);
    
                    fclose(fData);
    
                    printf("Wrote file %i: %s\n\n", i + 1, &fileNames[i]);
    
          }
    
          fclose(fArchive);
          printf("Success!");
    }
    
    
    int main()
    {
        char fileNames[][100] = {"Test1.zip", "Test2.rar"}; // Array to pass
        int volSize = 5;
    
        printf("%s\t%s\n",fileNames[0],fileNames[1]);
    
        CreateArchive("ArchiveName.bin", (size_t)volSize*1024*1024, 2, *fileNames); // Where I want to pass it too
    
        getchar();
        return 0;
    }
    If you look closely, you can see that when I pass it to CreateArchive, CreateArchive also passes the array to several other functions for file handling.

    This program is suppose to archive files into a single volumes or multi volume archives.

    Thanks for your help.

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    There's just so much wrong...

    Start here:

    Code:
    // Functions to obtain file information
    long int GetFileSize(char **fileName)
    {
        long int fileSize;
     
        FILE *fp = fopen(fileName, "rb");
     
        fseek(fp, 0, SEEK_END);
        fileSize = ftell(fp);
        fclose(fp);
        return fileSize;
    }
    There is absolutely no need to pass a ** to this function. It should take be long int GetFileSize(const char *fileName).

    Same here:
    Code:
    FILE *OpenVolumeFile(char **archiveName, int volume)
    Code:
    size_t  fileSizes[numFiles]; // I got rid of the "file" struct
    Variable length array? Is it supported?

    Too tired to go further than that.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    something like this?
    Code:
    #include <stdio.h>
    
    void f(char s[][100],int size)
    {
            // 'size' lets you know the first dimension of 's'
            printf("%s\n",s[0]);
            printf("%s\n",s[1]);
    }
    
    int main(int argc,char *argv[])
    {
            char s[2][100] = {
                    "abc","xyz"
            };
    
            f(s,2);
    
            return 0;
    }

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    Yes, something like that. So I would just need to specify the max length of each string, but I'd still be able to make calls like this?

    Code:
    size_t fileBytesLeft = fileSizes[i];

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    since you declared the array as char 'fileNames[][100]' that sets a fixed maximum size for each string of 100 char (99 characters plus a 0 terminator). if you have shorter strings (like my example) the extra space is unused but still there but doesn't hurt anything. just be sure your filenames are not longer than 99 characters. (don't worry about wasted space unless it really matters. using a fixed size array like you did is much easier than separately allocating the exact space for each string).

    passing the size of the array is so you can do a bounds check if you need to.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    216
    So I've gotten my code to run, and it runs well except it only writes 1.10 mb's to the archive and then it stops. Is there a noticable problem with this code?

    Code:
    /* Uses the same code from above for the most part */
    
    void CreateArchive(char *archiveName, size_t  volSize, int numFiles, char fileNames[][256])
    {
          FILE   *fArchive;
    
          size_t  volBytesLeft;
          size_t  headerSize;
          size_t  fileSizes[numFiles]; // I got rid of the "file" struct
    
          int     i;
          int     volume = 0;
    
          for(i = 0; i < numFiles; i++)
                fileSizes[i] = GetFileSize(fileNames[i]);
    
          fArchive = OpenVolumeFile(archiveName, volSize>0 ? ++volume : 0);
    
          headerSize = WriteArchiveHeader(fArchive, volSize, numFiles, fileNames, fileSizes);
    
          if (volSize > 0)
             volBytesLeft = volSize - headerSize;
    
          else
             volBytesLeft = BUFFER_SIZE + 1; // ensure that it's greater than buffer size
    
          volume = 0;
    
          for(i = 0; i < numFiles; i++)
          {
                    size_t fileBytesLeft = fileSizes[i];
    
                    FILE *fData = fopen(fileNames[i], "rb");
                    if(fData == NULL)  Error("Error opening file\n");
    
                    printf("File %i: %.2f MB\n", i + 1, (double)fileSizes[i] / 1024 / 1024);
    
                    do
                    {
                                  char buffer[BUFFER_SIZE];
                                  size_t bytesToRead, bytesRead;
    
                                  if(volBytesLeft == 0)
                                  {
                                                    fclose(fArchive);
    
                                                    volume++;
    
                                                    fArchive = OpenVolumeFile(archiveName, volume);
    
                                                    volBytesLeft = volSize;
                                  }
    
                                  bytesToRead = min3(sizeof buffer, fileBytesLeft, volBytesLeft);
    
                                  bytesRead = ReadBuffer(fData, buffer, bytesToRead);
    
                                  WriteBuffer(fArchive, buffer, bytesRead);
    
                                  fileBytesLeft -= bytesRead;
    
                                  volBytesLeft -= bytesRead;
    
                    }
                    while(fileBytesLeft > 0);
    
                    fclose(fData);
    
                    printf("Wrote file %i: %s\n\n", i + 1, &fileNames[i]);
    
          }
    
          fclose(fArchive);
          printf("Success!");
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 10-21-2007, 07:44 AM
  2. Can't pass array to function
    By yougene in forum C Programming
    Replies: 9
    Last Post: 08-19-2007, 04:09 PM
  3. Is it possible to pass an array to a function?
    By Loic in forum C++ Programming
    Replies: 20
    Last Post: 05-06-2007, 10:04 PM
  4. how can i pass this array to my function?
    By kosodo in forum C Programming
    Replies: 4
    Last Post: 04-14-2006, 09:40 PM
  5. Replies: 3
    Last Post: 04-02-2002, 01:39 PM