Неверные значения, напечатанные при циклическом просмотре, и массив структур

#arrays #c #for-loop #struct

Вопрос:

Я читаю из файла и сохраняю значения из каждой строки в структуру. Значения, которые я сохраняю, — это символ, строка и два целых числа. Затем каждая структура сохраняется в массиве структур. Я хочу распечатать каждое из этих значений, чтобы убедиться, что они были сохранены правильно, и все, кроме строк, распечатывается правильно, когда я получаю доступ к каждой структуре из массива в цикле for. Я не понимаю, почему это происходит. Чтобы проверить, я распечатал строки сразу после добавления их в структуру, которая дала ожидаемый результат. Только когда я пытаюсь получить доступ к этим строковым элементам в цикле for, я получаю неправильные выходные данные. Вот мой код:

 char wordFirstLetter;  struct BankAccount arrAccounts[20];  struct TransactionRequest arrTransactions[20];  int numAccounts = 0;  int numTransactions = 0;  int currAccountIndex = 0;  int currClient = 1;   while(fgets(line, sizeof(line),fp))  {  // We will be getting the words on each line using strtok()  //Gets the first word in the line  char *word = strtok(line, " ");  wordFirstLetter = word[0];   // Checks if the first letter of the line is 'a'  // If it is, then we know we are setting up the account  if(wordFirstLetter == 'a')  {  //not related  }  // Otherwise we are dealing with a client  else  {  while(word != NULL)  {  if(word[0] == 'c')  {  // Move on to the next word if we see that we are  // dealing with a client  word = strtok(NULL, " ");  }  else  {  // Create a structure to represent the current request  struct TransactionRequest transaction;   // Append the client number of the client doing the transaction  transaction.client = currClient;     // Append the type of transaction and move to next word  char *transType = word;  transaction.requestType = transType;  printf("This is the value of word: %sn", word);  printf("%sn", transaction.requestType);  word = strtok(NULL, " ");     // Append the account number that will be altered and move to next word  transaction.account = word[1] - '0';  word = strtok(NULL, " ");     // Append the amount for the transaction and move to next word  int transAmount = atoi(word);  transaction.amount = transAmount;  word = strtok(NULL, " ");     // Append this transaction to an array containing all transactions in the file  arrTransactions[numTransactions] = transaction;  numTransactions  ;   }  }  // Each line represents a client, so when we are done with the  // line we move to the next client  currClient  ;  }  }   for(int i = 0; i lt; numTransactions; i  )  {  struct TransactionRequest transaction = arrTransactions[i];  printf("This is the client number: %dn", transaction.client);  printf("This is the request type: %sn", transaction.requestType);  printf("This is the account to be accessed: %dn", transaction.account);  printf("This is the amount: %dn", transaction.amount);  printf("n");  }  

Это структура, которую я использую:

 struct TransactionRequest {  // ID if the client doing the transaction  int client;  // Type of transaction the client is doing  char *requestType;  // Account number of the account the client is dealing with  int account;  // Amount of money that is boing moved around  int amount; };   

Я что-то неправильно сделал в цикле for при распечатке этих строковых элементов? Если нет, то почему возникает эта проблема.

Комментарии:

1. Было бы полезно иметь образец файла, на котором мы могли бы его запустить?

2. @Neil Как я могу загрузить свои файлы? Это всего 2 файла.

3. @MarcoAiello, вы можете разместить непосредственно в вопросе минимальный фрагмент вашего файла, скажем, с тремя или пятью строками, достаточно, чтобы воспроизвести проблему! В дополнение к этому, что вы подразумеваете под «неверными значениями»? Не могли бы вы привести пример?

Ответ №1:

word выходит за рамки после while цикла, поэтому ваша структура будет содержать указатель на недопустимые данные. Даже если вы объявили word перед циклом while, все экземпляры TransactionRequest будут содержать самое последнее значение word , которое, скорее всего, не соответствует предполагаемому поведению. Если вы знаете requestType , что не будет превышать определенной длины, то вы можете использовать массив символов фиксированной длины в своей структуре. Таким образом, независимо от того, выделены ли экземпляры вашей структуры в стеке или куче, requestType данные будут уникальными для каждого экземпляра и будут выделены/освобождены вместе со всей структурой.

 #define REQUEST_TYPE_MAX_LENGTH 256 struct TransactionRequest {  // ID if the client doing the transaction  int client;  // Type of transaction the client is doing  char requestType[REQUEST_TYPE_MAX_LENGTH];  // Account number of the account the client is dealing with  int account;  // Amount of money that is boing moved around  int amount; };  

Тем не менее, потребуется значительный редизайн вашего кода. Например, вы не можете использовать присваивание для переноса данных из word переменной в requestType поле TranscationRequest структуры. Вам нужно будет использовать такие функции, как strncat ручное завершение с нулевым значением.

Хотя это не совсем связано, я также хочу отметить, что номер учетной записи в TransactionRequest может принимать значения только от 0 до 9 (включительно), если только ваш исходный файл не содержит каких-либо странных символов ASCII. Это специально?