Home > Blockchain >  How To remove Reference to a variable in C
How To remove Reference to a variable in C

Time:03-21

I have a function parse() Which basically takes a string argument in the form of "X:0:Y;A:0:B;" and splits it into three GLOBAL arrays known_routers, Known_distances AND known_next_hop.

The function works fine when the arguments passed in it are DIFFERENT variables but it just replaces old values in the global arrays if the same argument variable is passed with a different value. (I BELIEVE THERE IS A REFERENCE CREATED, THUS EACH TIME THE ORIGINAL VARIABLE CHANGES, THE VALUES IN GLOBAL ARRAYS ALSO CHENGE BECAUSE THEY JUST POINT TO THE ORIGINAL ARGUMENT)

for example the following code works as expected:

int main(int argc , char *argv[])
{
    
  
    char receive_buf[10000]= "K:0:K;";
    parse(receive_buf);
    
    
    char receive_buf1[10000]= "C:0:C;";
    parse(receive_buf1);
   

    char receive_buf2[10000]= "D:0:D;";
    parse(receive_buf2);
  
    for(int i = 0; i < routers_added;   i)
    {
        printf("-------------------------\n");
        printf("%s\n",known_routers[i]);
        printf("%d\n",known_distances[i]);
        printf("%s\n",known_next_hop[i]);
        printf("-------------------------\n");
    }

    return 0;
 }

The code above gives expected value of :

K 0 K

C 0 C

D 0 D

BUT THE CODE BELOW WILL NOT WORK

int main(int argc , char *argv[])
{
    
  
    char receive_buf[10000]= "K:0:K;";
    char secondary_buf [10000];
    memcpy(secondary_buf, receive_buf, 6);
    parse(secondary_buf);
    
    strcpy(receive_buf, "C:0:C;");
    memcpy(secondary_buf, receive_buf, 6);
    parse(secondary_buf);
   

    strcpy(receive_buf, "K:0:K;");
    memcpy(secondary_buf, receive_buf, 6);
    parse(secondary_buf);
  
    for(int i = 0; i < routers_added;   i)
    {
        printf("-------------------------\n");
        printf("%s\n",known_routers[i]);
        printf("%d\n",known_distances[i]);
        printf("%s\n",known_next_hop[i]);
        printf("-------------------------\n");
    }

    return 0;
 }

THE CODE ABOVE GIVES AN OUTPUT:

D 0 D

(so basically any last value that is given to the variable "receive_buf")

in my original code i am using socket recv function to continously get new values to pass arguments in this function. (but it basically just changes the older values like the above example) the code i am trying to use for passing argument is shown below:

char receive_buf[10000];
while(1){
       
        int read_size ;
    
        if ((read_size=recv(sock, receive_buf, 10000-1, 0)) == -1) {
            perror("recv");
            exit(1);
            
        }
        else{
            parse(receive_buf);
        }


}
       

The function parse is shown below if needed. please help

char* known_routers[20];
int known_distances[20];
char* known_next_hop[20];
int check_if_a_router_exists_in_the_system(char * router);
int routers_added=0; 

void parse(char* packet){
    
 
    
    printf("\nstarting to parse the following pocket: %s\n",packet);
    
    
    int i = 0;
    int l = 0;
    char *p = strtok (packet, ";");
    char *array[20] ;
    char *array_2[20] ;

    while (p != NULL)
    {
        array[i  ] = p;
     
        p = strtok (NULL, ";");
    }

    for (int j = 0; j < i;   j){
        
        char *po = strtok (array[j], ":");
        

        while (po != NULL)
        {

            array_2[l  ] = po;
     
            po = strtok (NULL, ":");
        }
        
    }
    int is_it_next_hop=0;

    for(int k = 0; k < l; k  ){
        if(array_2[k][0]=='0'||array_2[k][0]=='1'||array_2[k][0]=='2'||array_2[k][0]=='3'||array_2[k][0]=='5'||array_2[k][0]=='6'||array_2[k][0]=='7'||array_2[k][0]=='8'||array_2[k][0]=='9'){
        }
        else{
            if (is_it_next_hop){
                is_it_next_hop=0;
            }
            else{
                is_it_next_hop=1;
                int is_it_in_the_system = check_if_a_router_exists_in_the_system(array_2[k]);
                printf("checking is : %s is in the system: %d",array_2[k],is_it_in_the_system);
                if(is_it_in_the_system==-1){ //if it isnt in the system
                    known_routers[routers_added]=array_2[k];
                    known_distances[routers_added]=atoi(array_2[k 1]) 1;
                    known_next_hop[routers_added]=array_2[0];
                    routers_added  ;
                    printf("\n\n---------routers increased-------\n\n");
                }
                else{
                    printf("\n\n---------routers remain same-------\n\n");
                    if(known_distances[is_it_in_the_system]>atoi(array_2[k 1]) 1){
                        known_distances[is_it_in_the_system]=atoi(array_2[k 1]) 1;
                        known_next_hop[is_it_in_the_system]=array_2[0];
                    }
                }
            }

        }

    }

    
}


CodePudding user response:

First, a bit of pedantry: there's no such thing as a reference in C, references are a C feature. C has pointers, which can be used for similar purposes.

As far as your program goes, I believe the problem is this: your parse() function populates several global arrays with pointers into the memory-buffer that you passed in as an argument. That's all well and good, but in your second example you then overwrite that memory buffer with some other data:

parse(secondary_buf);
// at this point, your known_blah[] arrays contain pointers into (secondary_buf)

[...]
memcpy(secondary_buf, receive_buf, 6);  // here you overwrite secondary_buf

... so it isn't surprising that your pointers now point to different data than they did before -- you overwrote the data they were pointing to.

As for how you might avoid that problem, you might pass a different memory buffer to each call (as you did in your first example), or copy out the known_* data to a separate location (that won't be overwritten) before the subsequent call to parse(), or avoid the problem by refactoring your program so that it fully handles the data from the first parse() call before calling parse() a second time (and therefore doesn't need to access the old/overwritten data after the next call to parse())

CodePudding user response:

One of the comments answered my question. "strdup" was the function i needed. It created a completely new copy of argument everytime .

thank you so much.

CodePudding user response:

I don't really understand what you're trying to achieve, so I just went as far as parsing the input correctly. I would not bother with the second strtok(), since there should always(?) be three fields in each block. So I'd just split them separately.

Make sure you test your code with bad input like "", ";;", "A:0", ":::", etc.

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

#include <ctype.h>

void parse(char *packet)
{
    printf("\nstarting to parse the following pocket: %s\n",packet);

    // Parse a bunch of semicolon delimited fields, each of which is then
    // delimited by a colon into 3 parts, e.g.:
    //     K:0:K;C:0:C;
    //     D:0:D;
    char *triple = strtok( packet, ";" );
    while ( triple != NULL )
    {
        // there is something to parse
        char *field1 = triple;
        char *field2 = strchr( triple, ':' );
        char *field3 = strrchr( triple, ':' );

        if ( field2 != NULL && field3 != NULL && field2 != field3 )
        {
            // we have all 3 parts
            *field2 = '\0';   // trim the first field
            field2  = 1;
            *field3 = '\0';   // trim the second field
            field3  = 1;

            // Quickly validate the content of the fields by considering the first letter
            if ( isalpha( field1[0] ) && isdigit( field2[0] ) && isalpha( field3[0] ) )
            {
                // TODO: DO SOMETHING USEFUL WITH field1, field2, field3
                printf( "PARSED [%s], [%s], [%s]\n", field1, field2, field3 );
            }
            else
            {
                // Ignore, but nag
                printf( "Incorrect field(s) [%s], [%s], [%s]\n", field1, field2, field3 );
            }
        }
        else
        {
            // Ignore, but nag
            printf( "Malformed triple [%s]\n", triple );
        }

        triple = strtok( NULL, ";" );  // find the next field
    }
}


int main( int argc, const char **argv )
{
    int i;
    char *arg_copy;

    for ( i=1; i<argc; i   )
    {
        arg_copy = strdup( argv[i] );
        if ( arg_copy != NULL )
        {
            parse( arg_copy );
            free( arg_copy );
        }
    }

    return 0;
}
  • Related