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

#define MAX_input_size 100

struct RoutingInfo{	/* Structure to hold the IP entrys */
	unsigned int IPDestinationNetwork;
	unsigned int subnetMask;
	int prefix;
	unsigned int gateway;
	char* interface;
} entry[MAX_input_size];

int computePrefix (unsigned long decimSM){ /* computes the prefix of the Subnet Mask */
	int prefix = 0;
	while (decimSM){
		prefix += decimSM % 2;
		decimSM = decimSM / 2;
	}
	return prefix;
}

int main (int argc, char *argv[]){
	FILE *fpin;
	int i = 0;
	char buffer[50];
		
	if (argc < 2){	/* Checking for arguments */
		puts ("usage: ./a.out input.txt\n");
		return 1;
	}
	
	fpin = fopen (argv[1], "r");	/* Opening the file for reading*/
	if (fpin == NULL){/* File opening error */
		puts ("cannot open file\n");
		return 1;
	}
	/* File opened */
	while (fgets (buffer, 50, fpin) != NULL){	/* Reading input entrys in to the structure */
		entry[i].IPDestinationNetwork = inet_addr (strtok (buffer, "\t"));
		entry[i].subnetMask = inet_addr (strtok (NULL, "\t"));
		entry[i].prefix = computePrefix (entry[i].subnetMask);
		entry[i].gateway = inet_addr (strtok (NULL, "\t"));
		entry[i].interface = strtok (NULL, "\t");
		printf ("%u\t%u\t%d\t%u\t%s\n", entry[i].IPDestinationNetwork, entry[i].subnetMask, entry[i].prefix, entry[i].gateway, entry[i].interface);
		i++;
		printf ("---------------------%s\n", entry[0].interface);
	}
	fclose (fpin);
	return 0;
}

input file: input.txt

\t means there is a tab space in between

194.24.0.0 \t255.255.248.0 \t194.24.12.0 \tRouter_4
194.24.8.0 \t255.255.252.0 \t127.0.0.1 \tRouter_1
194.24.12.0 \t255.255.252.0 \t194.24.8.0 \tRouter_3
194.24.16.0 \t255.255.240.0 \t194.24.0.0 \tRouter_2
194.24.8.0 \t255.255.254.0 \t194.24.12.0 \tRouter_4
194.24.16.0 \t255.255.248.0 \t127.0.0.1 \tRouter_1

in the output for the above code, why the statement

printf ("---------------------%s\n", entry[0].interface);

is printing different values of entry[0].interface on successive iterations.

can any one please help me on this problem.

Thank you in advance.

Recommended Answers

All 6 Replies

What does strtok() return?
Given the answer to the that question, what does entry[i].interface = strtok (NULL, "\t"); do? Same for each call to strtok() .

for the input above,

first call to strtok(), entry[i].IPDestinationNetwork = inet_addr (strtok (buffer, "\t")); returns pointer to the token before the delimiter(\t) of (i+1)th line (usually starting one).

and successive calls return pointers to the successive next tokens of each line (one while loop iteration for each line).

and so, entry[i].interface = strtok (NULL, "\t"); returns 4th (i.e., last) token of (i+1)th line.

What does strtok() return?
Given the answer to the that question, what does entry[i].interface = strtok (NULL, "\t"); do? Same for each call to strtok() .

and so, entry.interface = strtok (NULL, "\t"); returns 4th (i.e., last) token of (i+1)th line.

All of the entry[i].interface pointers point to buffer . On each iteration of the loop, you change the contents of buffer . Do you see the problem now?

for the input above,

first call to strtok(), entry[i].IPDestinationNetwork = inet_addr (strtok (buffer, "\t")); returns pointer to the token before the delimiter(\t) of (i+1)th line (usually starting one).

and successive calls return pointers to the successive next tokens of each line (one while loop iteration for each line).

and so, entry[i].interface = strtok (NULL, "\t"); returns 4th (i.e., last) token of (i+1)th line.

As integers, floats, strings, characters, char*? What does it return? And are you putting the return into the correct variable type?

Methinks you need to write a test program to understand strtok() because you don't know what it's doing.

I am sorry, i tried to flush the buffer at the end of each iteration, and still having the same problem.

can you explain the problem completely (or) if any hint is also OK, I am not able to figure it out exactly.

As integers, floats, strings, characters, char*? What does it return? And are you putting the return into the correct variable type?

Methinks you need to write a test program to understand strtok() because you don't know what it's doing.

I am sorry, i tried to flush the buffer at the end of each iteration, and still having the same problem.

Since that solution is completely nonsensical for solving the problem at hand, you clearly don't understand what the problem is.

can you explain the problem completely (or) if any hint is also OK, I am not able to figure it out exactly.

You're essentially doing this:

#include <stdio.h>

int main(void)
{
    int value = 11;
    int *p1;
    int *p2;
    
    p1 = &value;
    value = 22;
    
    p2 = &value;
    value = 33;
    
    /* Why does it print 33 for both? */
    printf("%d\t%d\n", *p1, *p2);
    
    return 0;
}

It's an aliasing problem. When you point to an object, then change the value of the object, the pointer reflects that change. Your interface pointers should be copies of whatever is stored in buffer , not references into buffer . The reason for this is very simple: when buffer changes after reading a new line, all of your pointers get corrupted.

As mentioned before, this may be a misunderstanding of how strtok() works. strtok() doesn't make a copy of the tokens, it simply points to the contents of the original string. The string has to be modifiable because strtok() writes null characters as the method for creating tokens. Maybe an example implementation of strtok() will help:

#include <stdio.h>

char *my_strtok(char *src, char delim)
{
    static char *next = NULL;
    char *start = src;
    char *end;
    
    if (start == NULL && (start = next) == NULL)
        return NULL; /* We're done */
    else {
        /* Skip leading delimiters on a new source */
        while (*start == delim && *start != '\0')
            ++start;
    }
    
    /* Find the end of the token */
    for (end = start; *end != delim && *end != '\0'; end++)
        ;
        
    if (*end == '\0')
        next = NULL; /* This was the final token */
    else {
        /* Make a new token and prepare for the next one */
        *end = '\0';
        next = end + 1;
    }
    
    return start;
}

int main(void)
{
    char buf[] = "this is a test";
    char *p = my_strtok(buf, ' ');
    
    while (p != NULL) {
        printf(">%s<\n", p);
        p = my_strtok(NULL, ' ');
    }
    
    return 0;
}

Since strtok() doesn't copy the token, you need to include that as a separate step:

entry[i].interface = strdup(strtok(NULL, "\t"));

Note that strdup() isn't a standard function, but it's easy to simulate:

#include <stdlib.h>

char *my_strdup(const char *src)
{
    char *copy = malloc(strlen(src) + 1);

    if (copy != NULL)
        strcpy(copy, src);

    return copy;
}

Don't forget to free the pointer when you're done, since strdup() (or whatever facsimile you use) will be allocating the memory dynamically.

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.