0

我发誓我真的是一个体面的程序员,但是在用 Java 编程多年之后,我在 C 编程方面的冒险让我发疯了。

我正在尝试用一组 IP 地址/端口对填充二维字符数组。我正在从文件中读取它们。它们被正确地从文件中拉出,并且应该被正确地放入阵列中。问题是,由于某种原因,当第二组被放入数组时,它会覆盖第一组,而我终其一生都无法弄清楚原因。

文件的第一行是文件中 IP 地址/端口对的数量(我称它们为元组)。以下几行是用空格分隔的 IP 地址和端口。

这是代码:

 //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]);

这是我得到的输出:

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.

4

4 回答 4

2

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;
于 2013-10-09T19:49:02.987 回答
0

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.

于 2013-10-09T19:50:27.963 回答
0

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.

sizeof(char) is always one

于 2013-10-09T19:51:02.477 回答
0

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).

于 2013-10-09T20:16:08.430 回答