Hi, I use char* for string handling because I read strings from a file and I don't know the length of these strings. The problem comes when I need to keep some strings in an array. I think char** is the best thing for that goal. But again since I don't know how many strings I will hold, I'm stuck in allocating memory for new strings to be hold. For example;

char* str;
    char** match_list;
while (fscanf(inp, "%s", str) != EOF) {
        if (matches(str)) {
            *match_list = (char**)malloc(sizeof(char*));
            *(match_list + i) = str;
            i++;
        }
    }

matches is the function checks the string for my intention. The line that malloc is included is a bit silly, I know :). I need to access the strings in future. I think I could explain my problem. I want to allocate a new char* space and bind my str to it. But how?
Thanks...

Let's start by clearing up an obvious misunderstanding about pointers.

>char *str;
>fscanf(inp, "%s", str);
This is broken. An uninitialized pointer does not mean a pointer to unlimited space. It means you're not allowed to dereference that pointer or compare it to anything until you initialize it.

You still need to guesstimate a size for reading strings from input, even if that size is a chunk and you append the chunks using dynamic memory. Get that right and then you can worry about an array of strings, because the solution is very similar.

Well I really couldn't get what you meant but I will answer to the point I think you asked...k

Well you can allocate two dimensional array as follows:

char **array; //Your two dimensional array
int str_nos=10; //No of strings you want to have
int str_len=60; //Maximum length of each string
array=malloc( str_nos * sizeof(char *) );
//Above st allocates memory for no of char pointers or strings
for(i=0;i<str_nos;i++)
{
a[i]=malloc( str_len * sizeof(char *) );
}

In this way you can dynamically allocate the number of strings and also their lengths by just altering he str_nos and str_len .I hope this helps :)

Just a tip: since you are reallocating new memory when you run out of space, you probably want to use realloc. This will keep all the data you had copied into your array previously.

instead of using malloc() (or realloc) poorly.... might i suggest sticking with the tried and true:

char stringblock[MAX_NUM_LINES][MAX_LINE_LEN];

because i'm fairly certain you're not doing an embedded application that is limited for RAM.

but mangling malloc() like you're doing will certainly find the limits of your computer memory after you fill it full of leaks.

@Narue:

>char *str;
>fscanf(inp, "%s", str);
This is broken. An uninitialized pointer does not mean a pointer to unlimited space. It means you're not allowed to dereference that pointer or compare it to anything until you initialize it.

thanks for reply. although you said it is broken I initialize the str every time I read a word from the file. After initialziation I work with str and matches function work properly.

@csurfer:

In this way you can dynamically allocate the number of strings and also their lengths by just altering he str_nos and str_len .I hope this helps

Thanks for reply but in your way I think i have to read file twice to have a correct size of match list. Isn't that a problem for performance when reading big files?

@jephthah:

char stringblock[MAX_NUM_LINES][MAX_LINE_LEN];

Thanks for reply. I don't know what will be the values of MAX_NUM_LINES and MAX_LINE_LEN values before I read the file and changing these values is not possible after run time I think.

@death_oclock:

Just a tip: since you are reallocating new memory when you run out of space, you probably want to use realloc. This will keep all the data you had copied into your array previously.

Is that possible I allocate one char* space beforehand and reallaocate space one by one after I found new words that matches my specifications? Using that way make sense but I have a char* named str and I want to keep that pointer in an array named match_list. As I wrote on the code it is char** type. I don't know how to tie these values. Thanks

>although you said it is broken I initialize the str every time I read a word from the file.
Hmm, I can interpret this one of two ways:

  1. You're saying the code you posted isn't equivalent to the code you're actually using.
  2. You're saying that I'm wrong and the code you posted isn't broken.

If it's the first case then I would highly recommend that you post equivalent examples to your real code if you want any useful help. If it's the second case then I pity you, because I'm very rarely wrong when it comes to the standard language/library, and when I am it's not the people asking beginner questions who are able to correct me successfully.

Arbitrary length input takes more work, and often the basic input functions are weak without a bit of scaffolding around them to get what you want. For example, here's a delimited string input function that can be used to read words:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define GROW_BY 32 /* Arbitrary size */

char *reads ( FILE *in, char *delim )
{
    char *result = NULL;
    size_t size = 0;
    size_t capacity = 0;
    int ch;

    while ( ( ch = getc ( in ) ) != EOF ) {
        if ( size == capacity ) {
            char *temp;

            capacity += GROW_BY;
            temp = realloc ( result, capacity + 1 );

            if ( temp == NULL ) {
                /*
                  This is a weak solution because it results in
                  loss of data. Recommend better error handling
                */
                free ( result );
                result = NULL;
                break;
            }

            result = temp;
        }

        /* Order is important here; run *after* the resize step */
        if ( strchr ( delim, ch ) != NULL )
            break;

        result[size++] = ch;
    }

    if ( result != NULL )
        result[size] = '\0';

    return result;
}

int main ( void )
{
    char *s;

    while ( ( s = reads ( stdin, " \n" ) ) != NULL ) {
        printf ( ">%s<\n", s );
        free ( s );
    }

    return 0;
}

Take careful note of how I handled the memory, this is a common pattern that you can reuse for an array of pointers to char. You can use this example to neatly fix your broken code and find the answer to the original problem of creating a dynamic array. You're welcome.

Comments
Excellent, as always

In fact it is 2nd case.

because I'm very rarely wrong when it comes to the standard language/library, and when I am it's not the people asking beginner questions who are able to correct me successfully.

Also if you have a big experience then you should know it is not a big deal that people can correct you. If you are uncomfortable with that using forums is not suitable for you. I'm not saying I am an expert but you are wrong about what you've written in previous post. Technically speaking, I initialize and reinitiaize str pointer with every word I read from file. It is not a char pointer array it is just a char pointer. After that I make comparison or whatever I need. At least I know that is possible and I suggest you to accept your fault. I don't want to be offending but if you want I could send you the code. Because it is one of my friend's project I prefer not to publish it here.

since you apparently don't know how to use malloc without mangling it, i suggested you use

char stringblock[MAX_NUM_LINES][MAX_LINE_LEN];

and you replied

I don't know what will be the values of MAX_NUM_LINES and MAX_LINE_LEN values before I read the file and changing these values is not possible after run time I think.

no, of course you cant change them at runtime. so since you dont know what the values are, use ridiculously high values that will cover any possible values. for instance

#define MAX_LINE_LEN     2024
#define MAX_NUM_LINES     512

memory is cheap. what's 1 Meg of memory when you've likely got 1 Gig of RAM? it's better than broken code full of memory leaks because so many programmers have no clue how to properly allocate dynamic memory.

but, really ... go on and use malloc to shoot yourself in the foot. i'm just sticking around for this:

In fact it is 2nd case.
Also if you [Narue] have a big experience then you should know it is not a big deal that people can correct you. If you are uncomfortable with that using forums is not suitable for you. I'm not saying I am an expert but you are wrong about what you've written in previous post. Technically speaking, I initialize and reinitiaize str pointer with every word I read from file. It is not a char pointer array it is just a char pointer. After that I make comparison or whatever I need. At least I know that is possible and I suggest you to accept your fault.

*grabs the popcorn*

:D


.

Thanks for explanation. Apparently I don't know usage of malloc :) I'm not a c programmer just helping one of my friends. I used c 3 years ago for just a project. After that I've never used it. I have a different question about my topic. I finished the work but I saw a weird thing while coding. I get segmentation fault after adding some new lines and I delete one by one (of course logically:)). But the segmentation fault happens when I declare a new variable.
It was just int k=0; but adding this caused segmentation fault. As I know segmentation fault occurs when I try to an unallowed/unallocated space in memory. For example like int i=array[5]; while array has the length of 4 causes segfault. But declaring a new variable causes that? I didn't understand anything :S

Apparently I don't know usage of malloc

welcome to Daniweb. i'd say of all the people who come in here asking questions that have malloc() somewhere in their code, 90% of them don't have any real concept of how to use it properly. But you're one of the lucky ones: admitting you're powerless is the First Step. now you can stop the abuse cycle, and start the recovery process.

As I know segmentation fault occurs when I try to an unallowed/unallocated space in memory.

then why are you arguing with NARUE about your use of uninitialized pointers?

oh, I see you misunderstood me. Pointers work properly. My problem is when I add a new variable I get segfault. I just add

int k=0;

line and segfault occurs. I didn't even use it. Just declared it. Am i using too much memory?

edit: I forgot to say I tried to change the name and type of the variable.

>Technically speaking, I initialize and reinitiaize str pointer with every word I read from file.
You clearly don't understand how memory works in C. Either you use static memory, in which case the compiler takes care of allocation and deallocation, or you have to take care of it yourself (dynamic memory). You can't just expect memory to be there if you're using pointers; if you want to store something with a pointer, the pointer needs to point to allocated memory. "Initializing the pointer" just isn't going to cut it. Afterward, it's your responsibility to deallocate the memory once you're done using it. If you can't handle this kind of responsibility, you shouldn't be using dynamic memory.

Bad memory management is just a segfault waiting to happen. Just because it doesn't occur with a sample of code doesn't mean that it's okay; often times another innocent declaration will be the final push to making your program crap out.

>Also if you have a big experience then you should
>know it is not a big deal that people can correct you.
It's not a big deal at all...when they're right. Just because you think you're right doesn't mean you are.

>I'm not saying I am an expert but you are wrong
>about what you've written in previous post.
Prove it. I can prove that until you initialize a pointer with an address to memory that you own (ie. an existing array or calling malloc), you invoke undefined behavior. Sometimes undefined behavior appears to work just fine, which is likely what's happening in your case. But "works for me" is a far cry from "correct and bug free".

So tell me, are you truly saying that you believe the following code is 100% correct, that scanf magically allocates memory to s or that s magically points to infinite memory, and that I'm completely wrong in saying that it's broken?

#include <stdio.h>

int main ( void )
{
  char *s;

  if ( scanf ( "%s", s ) == 1 )
    puts ( s );

  return 0;
}
Comments
you are the wind beneath my wings
char* str;
    char** match_list;
while (fscanf(inp, "%s", str) != EOF) {
        if (matches(str)) {
            *match_list = (char**)malloc(sizeof(char*));
            *(match_list + i) = str;
            i++;
        }
    }

You can try this one......

char* str;
    char** match_list;
     int len;
while (fscanf(inp, "%s", str) != EOF) {
        if (matches(str)) {
            len=strlen(str); 
            *(match_list+i) = (char*)malloc(len*sizeof(char*));
            strcpy(*(match_list+i),str);
            i++;
        }
    }
Comments
Nope.

You can try this one......
char* str;
while (fscanf(inp, "%s", str) != EOF) {

What size of memory is str pointing to? You don't know. You haven't given it any meaningful space of memory. Therefore you cannot use it with fscanf(), because it will overwrite unknown memory.

This article has been dead for over six months. Start a new discussion instead.