0

Adding the printf("Hi!\n") statements allows the code to work. It also works if the bound initial bound is improper and the user enters a new one. When I ran some tests calculate divers sometimes returned a character instead of an integer. I'm thinking it has something to do with my memory allocation. I also noticed that ./a.out 6 10 "|" would work but ./a.out 6 25 "|" would not causing an infinite loop when printing the lines of "|".

enter image description here

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

// Structs
typedef struct data_struct {
    int lineNumber;
    int divisorSum;
    char type[10];
}data;

// Prototypes
int calculateDivsors(int integer);

// Functions
int main (int argc, char *argv[]) {

    int lowerBound;
    int upperBound;
    char character;

    // Gets the values from command-line
    sscanf(argv[1], "%d", &lowerBound);
    sscanf(argv[2], "%d", &upperBound);
    sscanf(argv[3], "%c", &character);

    // Check to see if bound is proper
    while (upperBound <= lowerBound || lowerBound < 2) {
        printf("Error, please enter a new range (positive increasing).\n");
        scanf("%d %d", &lowerBound, &upperBound);
    }

    // Structure calls
    data* info = NULL;
    int totalData = upperBound - lowerBound;

    // Allocate the memory
    info = (data*)malloc(totalData * sizeof(data));

    printf("Hi!\n");

    if (info != NULL) {
        // Iterate through all the digits between the two bounds
        for (int i = lowerBound; i <= upperBound; i++) {
            int sum = calculateDivsors(i);


            // Write data to indiviual structures
            info[i].lineNumber = i;
            info[i].divisorSum = sum;

            // Check to see if the sum is greater than, less than, or equal to the original
            if (sum == i) {
                strcpy(info[i].type, "Perfect");
            }

            else if (sum > i) {
                strcpy(info[i].type, "Abundant");
            }

            else if (sum < i) {
                strcpy(info[i].type, "Deficient");
            }

            // Line n# has a column width of 4, string of 10
            printf("%4d is %-10s\t", info[i].lineNumber, info[i].type);

            // Generate Pictogram
            for (int j = 0; j < info[i].divisorSum; j++) {
                printf("%c", character);
            }
            printf("\n");
        }

    }
}

// Adds up the sum of diviors
int calculateDivsors(int integer) {

    int sum = 0; 

    for (int i = 1; i < integer; i++) {
        // Add to sum if perfectly i is a sum of integer
         if (integer % i == 0) {
            sum += i;
        }
    }

 return sum; // Returns the sum of diviors
}
13
  • Can you please give the output as text? Commented Nov 23, 2019 at 1:01
  • it neither functions with the printf nor without it. Commented Nov 23, 2019 at 1:03
  • 3
    You have at least one out of range causing heap overrun in this code. The index i used for info[i] indexing of your allocation is not zero based, but the allocation size, totalData, is (correctly, btw). Therefore, as i increases it will breach totalSize and in so doing, you're program invokes undefined behavior. Also totalData should be sized as int totalData = upperBound - lowerBound + 1; Commented Nov 23, 2019 at 1:07
  • Its working for me on my Mac OS terminal. Why would that be? Commented Nov 23, 2019 at 1:08
  • Undefined behavior doesn't mean it gets an error. Anything can happen, including the appearance of working. Commented Nov 23, 2019 at 1:10

1 Answer 1

4

You are accessing data outside its allocated buffer whenever lowerBound doesn't start with 0.

info[i].lineNumber = i;

Ideally, you should become...

info[i - lowerBound].lineNumber = i;

To ensure that the indexing starts at 0. Further, your window between lowerBound and upperBound is inclusive. That means it includes both ending boundaries. Therefore, totalData is undersized by one element. Even if you fix the indexing problem, your code will still be wrong with this:

int totalData = (upperBound - lowerBound) + 1;

Failing to do both of the above causes your code to invoke undefined behavior (UB), and thus unpredictable results thereafter. It may even appear to work. That, however, is a red herring when your code has UB. Don't confuse defined behavior with observed behavior. You can trust the latter only once you have the former; the two are not synonymous.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.