Reputation: 61
I swear I really am a decent programmer but my adventures in C programming after programming in Java for years are driving me mad.
I'm trying to fill a two dimensional char array with a set of IP Address/Port pairs. I'm reading them in from a file. They are being pulled out of the file correctly, and, should be being placed into the array correctly. The problem is that for some reason when the second set is being placed into the array it's overwriting the first set and I cannot for the life of me figure out why.
The first line of the file is the number of IP Address/Port pairs in the file (I call them tuples). The following lines are the IP addresses and ports separated by a space.
Here is the code:
//read the top line with the number of items
fgets(line, sizeof line, fp);
numLines = atoi(line);
printf("%s %d\n","numLines:",numLines);
char* tuples[numLines][2];
char* rawLines[numLines];
//read each line and put it into array
for(currentLine=0; currentLine<numLines; currentLine++){
if(fgets(line, sizeof line, fp) == NULL){
perror("fgets");
return -1;
}
printf("%s %d \n","curentLine: ",currentLine);
char* port;
tuples[currentLine][0] = strtok(line, " ");
printf("%s %s \n", "IP Address: ", tuples[currentLine][0]);
//rawLines[currentLine] = line;
port = strtok(NULL, " ");
size_t ln = strlen(port) - 1;
if (port[ln] == '\n')
port[ln] = '\0';
tuples[currentLine][1]=port;
printf("%s %s\n","port: ", tuples[currentLine][1]);
}
//list created and stored in tuples
//now that list is created choose a random server from the file and strip the value chosen from the list
//choose random server
srand (time(NULL));
//randomServer = rand()%numLines;
randomServer = 0;
printf("%s %d\n", "randomServer: ", randomServer);
//connect to random server pulled
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//setup client socket
printf("%s %s \n", "Setting up connection to: ", tuples[randomeServer][0]);
printf("%s %s \n", "Setting up connection on port: ", tuples[randomServer][1]);
Here is the output I get:
numLines: 2
curentLine: 0
IP Address: 127.0.0.1
port: 3761
curentLine: 1
IP Address: 192.168.0.1
port: 3762
randomServer: 0
Setting up connection to: 192.168.0.1
Setting up connection on port: 1
What I expect to get is: Setting up connection to: 127.0.0.1 Setting up connection on port: 3761
If I only have one line in the file then I get the expected values.
Thank you in advance.
Upvotes: 0
Views: 258
Reputation: 1975
Instead of directly assigning strtok
return to your bidimensional array, copy the contents with strcpy
:
char *ipAddress = strtok(line, " ");
char *tuple0 = malloc(sizeof(char) * (strlen(ipAddress) + 1));
strcpy(tuple0, ipAddress);
tuples[currentLine][0] = tuple0;
Upvotes: 2
Reputation: 120079
It is worth remembering that there are no 2D arrays in C. A 2D array is an abstract concept which can be implemented in C with (at least) two different concrete constructs. There are arrays of arrays, and there are arrays of pointers.
When we are talking about arrays of pointers, we usually (not always) arrange them such that the individual pointers point to different chunks of memory, lest our abstract 2D array ends up containing duplicates of the same row. In order for this to happen, we normally allocate each row explicitly on the heap, then fill it with values. Note that strtok
doesn't allocate anything. It accepts a character array and returns pointers that point inside it (and destroys the original string that was there).
Upvotes: 0
Reputation: 5049
The problem is that you're not copying the data correctly. You have a variable named line
, which appears to be an array of char
, and you use fgets()
to read each line of the input into this variable. You then tokenize the input, and for each token, you're storing a pointer into the line
array to a location in the tuples
array, but this data gets overwritten as soon as you read in the next line. What you really need to be doing is allocating a new piece of storage, copying the data into that, and storing the pointer to that new storage into the tuples
array.
Upvotes: 0
Reputation: 1476
Seems like you did not allocate memory for your "saved" strings. Your declarations:
char* tuples[numLines][2];
char* rawLines[numLines];
declares arrays of pointers to char. Not "strings". So you are missing something like:
tuples[index_value][0] = malloc(number_of_characters);
And then you should write the lines you read in that memory with either strcpy or strncpy.
Upvotes: 0