Hi,

The below is my situation,
Input String : abc 123$ abc 123$ abc123$abcabcabc 123$
From the above string i want to store the starting index of "123$" code and the "123$" string.
When i debugged and found, for first iteration(codecount=0) i'm able to store both index and string but for the second time(when codecount =1) its crashing. Can anyone suggest me to proceed further???

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

struct _MyStruct
{
    char Mycode[10];
    int Index;
};
void MyFun(char *String, _MyStruct *MyStruct[] )
{
    char      *TempString;  
    int   i=0,j=0, code = 0, codecount = 0;

    while(String[i])
    {
        if((String[i] == L'1') && (String[i+1] == L'2'))
        {
            //store the starting index of 123$ code
            MyStruct[codecount]->Index =i; //its crashing when it go for second time (say codecount=1)
            while(String[i] != L'$')
            {
                //storing 123 code
                MyStruct[codecount]->Mycode[code++] = String[i];    
                i++;
            }
            MyStruct[codecount]->Mycode[code++] = String[i];//add $ with 123
            i++;
            codecount++; // increment the count of 123 code
        }       
        i++; j++;
    }   
}

int main()
{
    char *a = "abc 123$ abc 123$ abc123$abcabcabc 123$";

    _MyStruct *MyStruct;
    MyStruct = (_MyStruct*)calloc(1,sizeof(struct _MyStruct));//Allocating MyStruct 

    printf("String with 123 code: %s", a);
    MyFun(a,&MyStruct);

    printf("\123 code is: %s",MyStruct[0].Mycode);  //here i'm trying to print 123 first occurence

    return 0;
}

The reasons why it is crashing is quite simple: first off, you are only allocating one structure's worth of memory in your call to calloc(). When you try to access the (non-existent) second structure, you run off the end of the allocated array, causing a memory protection violation. My recommendation is to keep track of the size of the allocated array, and pass it as an argument to MyFun(). This way, you can tell how larger the array is, and even reallocated if need be.

Second, the way you are passing the array of _MyStruct is wrong. Right now, you are declaring the argument as an array of _MyStruct pointers, which is not what you are allocating. You want to pass it as an array of _MyStruct, nothing more. This also means that you want to use the member notation (dot notation) to access the elements of MyStruct, rather than member indirection notation (-> notation).

My version of your code comes out to be:

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

struct _MyStruct
{
    char Mycode[10];
    int Index;
};

unsigned int MyFun(char *String, struct _MyStruct MyStruct[], unsigned int MyStructSize );


unsigned int MyFun(char *String, struct _MyStruct MyStruct[], unsigned int MyStructSize )
{
    unsigned int i = 0, j = 0, code = 0, codecount = 0, array_size = MyStructSize;

    for (i = 0, j = 0; i < strlen(String); i++, j++)
    {
        if((String[i] == '1') && (String[i+1] == '2'))
        {
            /* store the starting index of 123$ code */
            MyStruct[codecount].Index = i;
            while(String[i] != '$' && i < strlen(String))
            {
                /* storing 123 code */
                MyStruct[codecount].Mycode[code++] = String[i];
                i++;
            }


            MyStruct[codecount].Mycode[code++] = String[i]; /* add $ with 123 */
            i++;
            codecount++; /* increment the count of 123 code */

            if (codecount == array_size)
            {
                array_size += MyStructSize;  /* increase it by the original block size again */
                if(realloc(MyStruct, array_size * sizeof(struct _MyStruct)) == NULL)
                {
                    printf("\nMemory error: could not allocate new space\n");
                    exit(-1);
                }
            }
        }
    }

    return array_size;
}

int main()
{
    char *a = "abc 123$ abc 123$ abc123$abcabcabc 123$";
    struct _MyStruct *MyStruct;
    unsigned int array_size = 16, final_size;

    MyStruct = (struct _MyStruct*)calloc(array_size, sizeof(struct _MyStruct)); /* Allocating MyStruct */
    if (MyStruct == NULL)
    {
        printf("Memory error: could not initialize the array.\n");
        exit(-1);
    }

    printf("String with 123 code: %s\n", a);
    final_size = MyFun(a, MyStruct, array_size);
    printf("\n123 code is: %s\n", MyStruct[0].Mycode); /* here i'm trying to print 123 first occurence */
    printf("Final structure array size: %d\n", final_size);
    free(MyStruct);

    return 0;
}

You'll note a few other minor corrections, mostly made because I am using a particularly high level of compiler warnings (-Wall -Wextra -pedantic -Wunreachable-code). HTH.

Thanks Schol-R-LEA for ur quick reply. Let me try ur corrections.

Hi Schol-R-LEA,
When i debugged ur modified code and found no crashing from second iteration. But the below statement didnt executed at all i tried to create breakpoint in the below line but it didnt stopped at that line.but it is executing as expected.
Still i'm not getting the use of allocation done in this if statement.

if (codecount == array_size)
 {
     array_size += MyStructSize; /* increase it by the original block size again */
     if(realloc(MyStruct, array_size * sizeof(struct _MyStruct)) == NULL)
     {
         printf("\nMemory error: could not allocate new space\n");
         exit(-1);
       }
}

The CodeCount will increment whenever it finish parse "123$" string. so in my given string the number of "123$" is 4 and the CodeCount will increment upto 4.
"abc 123$ abc 123$ abc123$abcabcabc 123$"

Correct me if i'm wrong.

Actually, I wouldn't expect it to execute in this case; that was mostly a bit of defensive programming, in case you later had a much larger data string to process which happened to have more than (in this case) 16 occurences of the 123 code. If you change the value of array_size in main() to, say, 2, you'll see what it does when it goes over the size of the current block.

In the existing code, the block size is 16, whereas the string you are using right now only has 4 instances of the 123 code you are looking for. So, why use such a large block size, if you don't need it? Because you don't want to reallocate very often, and if possible, you want to avoid it completely. With the four occurences in your existing string, it shouldn't ever reallocate the memory; but having the test and reallocation code there is a good practice, as you may end up re-using this code on a larger dataset, and then have to worry about resetting the size manually, etc. It is better, IMAO, to take care of it up front, just to be safe, while at the same time avoiding having far too large a starting block size.

Thanks Joseph for good explanation.

Now i got the code "123$" and the index where it encountered. When i try to insert in respective index with new string say "mynewstring" i'm losing my existing strings.

Where are you inserting the new strings to? If you are trying to insert them into the existing String variable, that won't work; you would end up overwriting the part of the string you are putting it into, and possibly (if the insertion point is close to the end of the string) overrunning the end of the string.

So what do you need to do? Well, that depends on what you're going to do with the string after you have inserted the string values into it. If this is going to be local to MyFun(), then you can simply declare a large-ish buffer, and copy the part of the original string you want to keep into the buffer, interleaved with the new data you are adding to it. OTOH, if you want to return or pass back a copy of the new string, well, you will still want to have a large static buffer local to the function, but once you've finished processing the old string, you'd get the length of the final string using strlen(), and allocate a suitable char array that you can then copy the string into, and return that.

I suspect that we're not getting the full picture, here. This program has the feeling of a test program, something intended to help you work out how to do something for some larger program later on. What is your final goal with this?

Thanx Joseph for ur explanation and help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.