String-length of an multi-dimensional array

This is a discussion on String-length of an multi-dimensional array within the C Programming forums, part of the General Programming Boards category; Hi, How is it possible to get a string-length of an multi-dimensional array? I need it to reallocate memory for ...

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    8

    String-length of an multi-dimensional array

    Hi,

    How is it possible to get a string-length of an multi-dimensional array? I need it to reallocate memory for an array that's meant to store strings, each in their own individual element. My current alternative is to use malloc() but this does no good - I'm getting segfaults...Here's my code:

    Code:
    File *file;
    int h,i,j,fileSize;
    
    if(!(file = fopen(FILENAME, "r"))) exit(1);
    
    fseek(file,0,SEEK_END);
    fileSize = ftell(file);
    fseek(file,0,SEEK_SET);
    
    char *readString = malloc(fileSize+1);
    
    fread(readString,fileSize,1,file);
    fclose(file);
    
    char **lines = (char **) malloc(strlen(readString+1));
    
    i = j = 0;
    
    for (h=0;h<fileSize+1;h++) {
      if (readString[h] == '\n') {
        i++;
        j=0;
      }
      else {
        lines[i][j] = readString[h];
        j++;
      }
    }
    Any help largely appreciated. Thanks.

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,556
    You cannot get the length of an array -- this you must keep track of of yourself.
    But ask yourself this: how would you create an array of strings? And how much memory should be allocated for that?
    You are currently not doing this the right way.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Wanna see a cool trick?

    Example:
    Code:
    char **ftoarray(FILE *file)
    {
      size_t size, lines;
      char **array, *whole, *delim;
    
      fseek(file, 0, SEEK_SET);
      fseek(file, 0, SEEK_END);
      size = ftell(file);
      fseek(file, 0, SEEK_SET);
    
      if(!(whole = malloc(size)))
        return NULL;
    
      if(fread(whole, 1, size, file) != size)
      {
        free(whole);
        return NULL;
      }
      
      for(lines = 0, delim = strtok(whole, "\n"); delim; delim = strtok(NULL, "\n"))
        ++lines;
    
      if(!(array = malloc((lines+1) * sizeof(*array) + size)))
      {
        free(whole);
        return NULL;
      }
    
      array[lines] = NULL; /* NULL terminator */
      memcpy(array + lines + 1, whole, size);
      free(whole);
    
      for(size = 0, delim = array[lines + 1]; *delim; delim += strlen(delim) + 1, ++size)
        array[size] = delim;
    
      return array;
    }
    The last element of the array will be NULL.
    Last edited by master5001; 10-28-2008 at 12:16 PM.

  4. #4
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    Elysia, master5001, thank you for your answers.

    master5001, I tried your function but couldn't get it to work properly. Here's what I did first:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "ftoarray.h"
    
    main () {
    
      FILE *file;
    
      if (!(file = fopen("testi.apps","r"))) {
        puts("\nerror opening file\n");
        exit(1);
      }
    
      if ((ftoarray(file))==NULL) {
        puts("\nerror reading file to an array\n");
        exit(1);
      }
    
      fclose(file);
    ...and got a segfault. Inspecting the function further I noticed that the size of size_t size was not assigned correctly. From
    Code:
      fseek(file, 0, SEEK_SET);
      size = fseek(file, 0, SEEK_END);
      fseek(file, 0, SEEK_SET);
    I changed the code to
    Code:
      fseek(file, 0, SEEK_SET);
      fseek(file,0,SEEK_END);
      size = ftell(file);
      fseek(file,0,SEEK_SET);
    After I fixed this another problem arised - the fread() fails:
    Code:
    if(fread(whole, size, 1, file) != size)
        {
          free(whole);
          return NULL;
        }
    However, I don't really understand why the return value of fread is being compared to size since as far as I understand it fread is supposed to return the nitems read not characters read(where the number of items read would be the third argument of fread). Checking that fread returns nitems instead of size to make it pass, the function still fails to a segmentation fault.

    Please advise. Thanks.

  5. #5
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    ah ok. Well I usually use open(), lseek(), read(), and write() so sometimes I dyslexify things a bit. Fixed.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    No good. Still a segfault. Fails in the last for-loop.

  7. #7
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,556
    First, you need to get rid of implicit main: http://cpwiki.sourceforge.net/Implicit_main
    Second, you must check if fopen succeeded. If it fails, then you will get a segfault when trying to use fseek, fread, etc on it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    Quote Originally Posted by Elysia View Post
    First, you need to get rid of implicit main
    Aww, man...That was a bad n00bian mistake. Well, anyway I had already checked that the file opens properly. Here's the complete code in all it's beauty:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "ftoarray.h"
    
    int main (int argc, char **argv) {
    
      FILE *file;
    
      if (!(file = fopen("testfile","r"))) {
        puts("\nerror opening file\n");
        exit(1);
      }
    
      if ((ftoarray(file))==NULL) {
        puts("\nerror reading file to an array\n");
        exit(1);
      }
    
      fclose(file);

  9. #9
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Invariably you will need to free() the return of ftoarray().

  10. #10
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    Invariably you will need to free() the return of ftoarray().
    That doesn't help either...

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    I actually found another problem with master5001's code. This loop
    Code:
     for(lines = 0, delim = strtok(whole, "\n"); delim; delim = strtok(NULL, "\\
    n")) ++lines;
    utilises strtok-function which(as stated in here http://www.cs.utah.edu/dept/old/texi...library_5.html, at least) may corrupt the parsed string. I used a temporary string copying the contents of whole to it but doesn't prevent the segmentation fault.

    Frankly speaking I don't really understand what's the purpose of the last for-loop and why is memcpy used here. Could you please explain?
    Last edited by doxii; 10-29-2008 at 03:18 PM.

  12. #12
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    No.. you want strtok to "corrupt" the memory. And it won't cause another seg fault since it is null terminating things. The last for loop simply copies the memory locations of each string over to the beginning of the buffer. The memcpy() function just copies the buffer over the "whole" buffer over to the one that is returned to the user. Its kind of important.

  13. #13
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,506
    The only problem I see with master5001's cool trick is the lack of space for (and assignment of) a \0 to mark the end of the really long string read using fread()

    But then again, the excess size of the 2nd malloc and the memcpy is unnecessary as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  14. #14
    Registered User
    Join Date
    Oct 2008
    Posts
    8
    Let's see. Say we have a file with four lines, each containing characters. First we get the number of lines in file like this:
    Code:
    for(lines = 0, delim = strtok(whole, "\n"); delim; delim = strtok(NULL, "\n"))
        ++lines;
    Then we assign null to the 4th element of 'array':
    Code:
     array[lines] = NULL; /* NULL terminator */
    Then(if I finally got it right) we copy the contents of 'whole' to 5th element of 'array' :
    Code:
    memcpy(array + lines + 1, whole, size);
    If that's the way it's supposed to go, puts(array[5]) should return what we just copied with memcpy . Only it doesn't, even though enough memory is allocated for 'array' with malloc.
    Last edited by doxii; 10-30-2008 at 02:31 PM.

  15. #15
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Ah yes, Salem, you are right about the lack of a final null terminator. I will fix that. The reason for the larger buffer is so that no memory is leaked. And although one could technically just remove that portion of the code they would have to both free the memory pointed to by array[0] and then free array. This way just freeing array accomplishing deleting the whole thing.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem within multi dimensional array
    By lolguy in forum C Programming
    Replies: 5
    Last Post: 12-26-2008, 07:02 AM
  2. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  3. string into 2 dimensional array - basic stuff
    By mellisa in forum C++ Programming
    Replies: 11
    Last Post: 01-18-2003, 02:08 AM
  4. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM
  5. length of string etc.
    By Peachy in forum C Programming
    Replies: 5
    Last Post: 09-27-2001, 12:04 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21