Home > Mobile >  Incorrect values printed when looping through and array of structs
Incorrect values printed when looping through and array of structs

Time:11-22

I am reading from a file and saving values from each line to a struct. The values I am saving are a char, a string and two integers. Each struct is then saved to an array of structs. I want to print out each of these values to make sure they were saved properly, and everything except the strings print out properly when I access each struct from the array in a for loop. I don't understand why this is happening. To check I printed out the strings immediately after adding them to the struct which gave the expected output. It is only when I try to access these string elements in my for loop that I get the incorrect outputs. Here is my code:

    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: %s\n", word);
                    printf("%s\n", 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 < numTransactions; i  )
    {
        struct TransactionRequest transaction = arrTransactions[i];
        printf("This is the client number: %d\n", transaction.client);
        printf("This is the request type: %s\n", transaction.requestType);
        printf("This is the account to be accessed: %d\n", transaction.account);
        printf("This is the amount: %d\n", transaction.amount);
        printf("\n");
    }

This is the struct I am using:

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;
};

Have I done something incorrectly in my for loop when printing out these string elements? If not, why is this issue occurring.

CodePudding user response:

word goes out of scope after the while loop, so your structure will contain a pointer to invalid data. Even if you declared word before the while loop, all instances of TransactionRequest would contain the most recent value of word, which is likely not the intended behavior. If you know requestType won't exceed a certain length, then you can use a fixed-length char array in your structure. This way, whether your structure instances are allocated on the stack or heap, the requestType data will be unique to each instance and will be allocated/freed along with the entire structure.

#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;
};

Nonetheless, a significant redesign of your code will be required. For instance, you cannot use assignment to transfer data from the word variable into the requestType field of the TranscationRequest struct. You will need to use functions such as strncat with manual null termination.

Though it is not strictly related, I also want to point out that the account number in TransactionRequest can only take on values between 0 and 9 (inclusive) unless your original file contains some strange ASCII characters. Is this intended?

  • Related