-2

The program is written to bubble sort the dates inputted by the user in dd/mm/yyyy format where the month can be a string or an integer. No error is shown after compilation but segmentation fault error shows up after inputting the dates during execution. I'm unable to figure out the mistake. Also, I'm relatively new to programming. Please help.

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

void readElements(char **date, int n) {
    printf("enter the dates in dd/mm/yyyy format where month can be a string or "
           "an integer\n");
    for (int i = 0; i < n; i++) {
        date[i] = (char *)malloc(50);
        scanf("%s", date[i]);
    }
}

char strcompare(char *a, char *b, int n, int length1, int length2) {
    char *sub1, *sub2, *sub3, *sub4;
    int c = 0, d = 0, e = 0, f = 0;
    // comparing year
    while (c < 4) {
        sub1[c] = a[length1 - 4 + c];
        c++;
    }
    while (d < 4) {
        sub2[d] = b[length2 - 4 + c];
        d++;
    }
    if (strcmp(sub1, sub2) > 0) {
        return 'o';
    } else if (strcmp(sub1, sub2) < 0) {
        return 'z';
    } else
        // comparing month
    {
        for (int i = length1 - 6; i > 2; i--) {
            sub3[e] = a[i];
            e++;
        }
        for (int i = length2 - 6; i > 2; i--) {
            sub4[f] = b[i];
            f++;
        }
        if (strcmp(sub3, sub4) == 0) {
            int g = 0, h = 0;
            // comparing day
            char *sub5, *sub6;
            while (g < 2) {
                sub5[g] = a[g];
                g++;
            }
            while (h < 2) {
                sub6[h] = b[h];
                h++;
            }
            if (strcmp(sub5, sub6) > 0) {
                return 'o';
            } else {
                return 'z';
            }
        } else {
            if (sub3 == "january") {
                strcpy(sub3, "01");
            }
            if (sub4 == "january") {
                strcpy(sub4, "01");
            }
            if (sub3 == "february") {
                strcpy(sub3, "02");
            }
            if (sub4 == "february") {
                strcpy(sub4, "02");
            }
            if (sub3 == "march") {
                strcpy(sub3, "03");
            }
            if (sub4 == "march") {
                strcpy(sub4, "03");
            }
            if (sub3 == "april") {
                strcpy(sub3, "04");
            }
            if (sub4 == "april") {
                strcpy(sub4, "04");
            }
            if (sub3 == "may") {
                strcpy(sub3, "05");
            }
            if (sub4 == "may") {
                strcpy(sub4, "05");
            }
            if (sub3 == "june") {
                strcpy(sub3, "06");
            }
            if (sub4 == "june") {
                strcpy(sub4, "06");
            }
            if (sub3 == "july") {
                strcpy(sub3, "07");
            }
            if (sub4 == "july") {
                strcpy(sub4, "07");
            }
            if (sub3 == "august") {
                strcpy(sub3, "08");
            }
            if (sub4 == "august") {
                strcpy(sub4, "08");
            }
            if (sub3 == "september") {
                strcpy(sub3, "09");
            }
            if (sub4 == "september") {
                strcpy(sub4, "09");
            }
            if (sub3 == "october") {
                strcpy(sub3, "10");
            }
            if (sub4 == "october") {
                strcpy(sub4, "10");
            }
            if (sub3 == "november") {
                strcpy(sub3, "11");
            }
            if (sub4 == "november") {
                strcpy(sub4, "11");
            }
            if (sub3 == "december") {
                strcpy(sub3, "12");
            }
            if (sub4 == "december") {
                strcpy(sub4, "12");
            }
            if (strcmp(sub3, sub4) > 0) {
                return 'o';
            } else {
                return 'z';
            }
        }
    }
}

void Bubblesort(char **date, int n) {
    int i, j;
    char *t;
    for (i = 0; i < n - 1; i++) {
        for (j = 0; j < n - i - 1; j++) {
            int length1 = strlen(date[j]);
            int length2 = strlen(date[j + 1]);
            if (strcompare(date[j], date[j + 1], n, length1, length2) == 'o') {
                t = date[j];
                date[j] = date[j + 1];
                date[j + 1] = t;
            }
        }
    }
}

void printarray(char **date, int n) {
    printf("Sorted array:\n");
    for (int i = 0; i < n; i++) {
        printf("%s\n", date[i]);
    }
}

void main() {
    int n;
    char *date[50];
    printf("enter the number of elements that are to be sorted\n");
    scanf("%d", &n);
    readElements(date, n);
    Bubblesort(date, n);
    printarray(date, n);
}
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
geedee
  • 45
  • 7

2 Answers2

1

The segfault is due to using uninitialized memory. When I compile this program looking for warnings, two major categories of issues are indicated: the uninitialized memory accesses and the string comparisons.

$ clang-3.8 -c -Wall -fPIE  -fsanitize=memory sorting_.c -o sorting.o
sorting_.c:59:16: warning: result of comparison against a string literal is unspecified (use strncmp instead) [-Wstring-compare]
      if (sub3 == "january") {
               ^  ~~~~~~~~~
sorting_.c:62:16: warning: result of comparison against a string literal is unspecified (use strncmp instead) [-Wstring-compare]
      if (sub4 == "january") {
               ^  ~~~~~~~~~
sorting_.c:65:16: warning: result of comparison against a string literal is unspecified (use strncmp instead) [-Wstring-compare]
      if (sub3 == "february") {
               ^  ~~~~~~~~~~

...omitted repeats...

sorting_.c:38:7: warning: variable 'sub4' is uninitialized when used here [-Wuninitialized]
      sub4[f] = b[i];
      ^~~~
sorting_.c:15:34: note: initialize the variable 'sub4' to silence this warning
  char *sub1, *sub2, *sub3, *sub4;
                                 ^
                                  = NULL
sorting_.c:34:7: warning: variable 'sub3' is uninitialized when used here [-Wuninitialized]
      sub3[e] = a[i];
      ^~~~
sorting_.c:15:27: note: initialize the variable 'sub3' to silence this warning
  char *sub1, *sub2, *sub3, *sub4;
                          ^
                           = NULL
sorting_.c:50:9: warning: variable 'sub6' is uninitialized when used here [-Wuninitialized]
        sub6[h] = b[h];
        ^~~~
sorting_.c:44:24: note: initialize the variable 'sub6' to silence this warning
      char *sub5, *sub6;
                       ^
                        = NULL
sorting_.c:46:9: warning: variable 'sub5' is uninitialized when used here [-Wuninitialized]
        sub5[g] = a[g];
        ^~~~
sorting_.c:44:17: note: initialize the variable 'sub5' to silence this warning
      char *sub5, *sub6;
                ^
                 = NULL
sorting_.c:23:5: warning: variable 'sub2' is uninitialized when used here [-Wuninitialized]
    sub2[d] = b[length2 - 4 + c];
    ^~~~
sorting_.c:15:20: note: initialize the variable 'sub2' to silence this warning
  char *sub1, *sub2, *sub3, *sub4;
                   ^
                    = NULL
sorting_.c:19:5: warning: variable 'sub1' is uninitialized when used here [-Wuninitialized]
    sub1[c] = a[length1 - 4 + c];
    ^~~~
sorting_.c:15:13: note: initialize the variable 'sub1' to silence this warning
  char *sub1, *sub2, *sub3, *sub4;
            ^
             = NULL
sorting_.c:163:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
void main() {
^
sorting_.c:163:1: note: change return type to 'int'
void main() {
^~~~
int
Brian Cain
  • 14,403
  • 3
  • 50
  • 88
  • I've incorporated the recommended changes into my program-used strcmp, initialised *sub1,*sub2...etc=NULL, and changed void main to int main and added a return 0. No error on compilation. Inputted 01/01/2018,01/01/2015,01/01/2020 and got a segmentation fault on execution. – geedee Aug 08 '16 at 07:28
  • @geedee, it's good that `subN` variables are initialized -- now I would expect it to segfault every time instead of depending on whatever's in the uninitialized memory. (BTW you must put as many `NULL`s as there are N `subN` variables). Also, `subN` must be allocated before you can use them. You initialized them to not point anywhere by assigning `NULL`. – Brian Cain Aug 08 '16 at 14:22
  • I've allocated memory to the subN variables(no more segmentation fault), corrected a few other errors and the program works! – geedee Aug 09 '16 at 06:28
0

Change you code from,

void readElements(char **date,int n)
{printf("enter the dates in dd/mm/yyyy format where month can be a string or an integer\n");
for(int i=0;i<n;i++)
{date[i]=(char*)malloc(50);
scanf("%s",date[i]);
printf("%d %s \n",i, str);
}}

to ,

void readElements(char **date,int n)
{printf("enter the dates in dd/mm/yyyy format where month can be a string or an integer\n");

for(int i=0;i<n;i++)    
{
        char *str ;
        str = (char*)malloc(60);

        date[i]= str;

scanf("%s",str);

printf("%d %s \n",i, str);
    }}

This will work..

Wickkiey
  • 4,446
  • 2
  • 39
  • 46