2

I can't fix a weird bug i have in my code.

I wrote a program to print a date originally written in format "MM/DD/YYYY" to format "Month DD, YYYY".

The program is simple enough: i store the date in a char array, then with strtok i obtain month, day, year individually and store pointers to them in a char * array. Eventually the portion of the string representing the month is converted to int , so as to use it as an index to print the month; day and year are printed separately.

The program works, but i really can't wrap my head around the fact that it doesn't if i input 08 (August) or 09 (September) as month.

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

    void read_date( char * const);
    void collect_data( char * const, char *[] );
    int convert_month( char * );

    int main() {

         char *months[12] = {"January", "February", "March", "April", "May", "June", "July","August", "September", "October", "November", "December" };
         char orig_date[11];
         char *date_elem[3];

         int month;

         read_date( orig_date );

         collect_data( orig_date, date_elem );

         month = convert_month( date_elem[0] );

         puts("\n*New format*\n");
         printf( "%s %s, %s\n", months[month - 1], date_elem[1], date_elem[2]);

    }

    void read_date( char * const date ) {

         int i = 0;
         char c;

         puts("Enter date in format MM/DD/YYYY:\n");

         while ( i < 11 && ( c = getchar() ) != '\n' ) {

              date[i++] = c;
         }

         date[i] = '\0';
     }

     void collect_data( char * const date, char *elem[] ) {

          char *ptr;
          int i = 0;

          ptr = strtok( date, "/" );

          while ( ptr != NULL ) {

               elem[i++] = ptr;
               ptr = strtok( NULL, "/" );
          }

      }

      int convert_month( char *m ) {

           char *rem;

           return strtol( m, &rem, 0);

      }
Talete
  • 81
  • 6
  • You've accepted an answer about the "octal/decimal" problem... But, this program would crash & burn if the user enters "1/2/3/4/5/6" as the date string... `collect_data()` will try to put 6 pointers into an array dimensioned for 3 maximum... No one else seems to be worried. – Fe2O3 Oct 07 '22 at 07:51
  • @Fe2O3 The program will crash in different ways on other inputs too. – n. m. could be an AI Oct 07 '22 at 08:07
  • @Fe2O3 yes i'm aware of that, i just wanted to solve this problem first, than work on verifying the input. – Talete Oct 07 '22 at 08:47
  • 1
    If you wanted to "solve this problem", then why not solve the problem working with a collection of "compile-time strings" that test the extremities of the logic... You've spent time asking of a single string of input (that could be rubbish), and now have to work around that to diagnose a bug in the lower level processing. Cart before the horse, that's called, and it's really inefficient... – Fe2O3 Oct 07 '22 at 08:50
  • @moooeeeep (Sorry if I seem a little ornery...) "The program works, but i really can't wrap..." Seems to me it's incumbent on those who see farther to tell the OP that "the program does NOT work", rather than putting on blinkers and ignoring bigger issues (eg: the likelihood of feeding strtol() an uninitialised 'pointer' value.) Low quality answers are low quality answers. – Fe2O3 Oct 07 '22 at 09:03

1 Answers1

7

You use base 0 for parsing integers from the month part:

return strtol( m, &rem, 0);

That means it will auto-detect the numeric base, which assumes base-8 (octal) representation for zero-prefixed input numbers. You might want to hard-code usage of base 10 there.

The numbers 08 and 09 do not exist with octal number representation. You receive 0 there, as it stops parsing at the first invalid character it encounters. See below link for how you could improve your error handling with strtol().

For reference:

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • 1
    I think you'll find you get `0` because the first digit is `0`, and `rem` points to the `8` or `9` digit. – Jonathan Leffler Oct 07 '22 at 07:04
  • @JonathanLeffler True. I added a link that expands on how to do the error handling with strtol. – moooeeeep Oct 07 '22 at 07:11
  • So, "caused by a typo" (mistyping 10 as 0)... Should be closed, no? – Fe2O3 Oct 07 '22 at 08:27
  • @Fe2O3 it wasn't a typo, it was the first time i used that function and i thought ```0``` as base was correct for decimals. – Talete Oct 07 '22 at 08:50
  • @Talete Well, thankfully SO answers come from people who've taken the time to read the man pages and don't work from 'guessing' and an attitude of "I think this should work." – Fe2O3 Oct 07 '22 at 08:55