0

I have got this function which converts a month from 3 chars to 2 digits month:

int Extract_Month(char *pDestMonth, char *pMonth)
{
    char monthschar[12][4] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
    char monthsdigit[12][3] = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12" };
    int i = 0;

char tmpStr[4] = "";
tmpStr[0] = (pMonth[0] >= 'a' && pMonth[0] <= 'z') ? ('a' + pMonth[0] - 'A') : pMonth[0];
tmpStr[1] = (pMonth[1] >= 'a' && pMonth[1] <= 'z') ? ('a' + pMonth[1] - 'A') : pMonth[1];
tmpStr[2] = (pMonth[2] >= 'a' && pMonth[2] <= 'z') ? ('a' + pMonth[2] - 'A') : pMonth[2];
tmpStr[3] = 0;

for (i = 0; i < 12; i++)
{
    if (!strncmp(tmpStr, monthschar[i], 3))
    {
        StrMove((uchar *)pDestMonth, (uchar *)monthsdigit[i], 2);
        return 0;
    }
}
return -1;
}

I am running it with gdb and I'm getting a segmentation fault error. Does anyone knows what am i missing here?

I have made some research and I found that seg faults are due to memory mishandling.

gdb output points exactly to this function declaration

This is where the function is being called (reduced code): enter image description here

9
  • 2
    provide information on how to call the function with an working example. It might be the case that the input is already wrong. Commented Jan 22, 2019 at 13:48
  • (pMonth[0] >= 'a' && pMonth[0] <= 'z')? Don't you mean islower()? Or you can just use toupper(). Commented Jan 22, 2019 at 13:51
  • 1
    gdb will tell you which line is crashing if you compile with '-o0 -g'. Note also that your upper-case conversion is wrong - work it through for 'a', for example. Commented Jan 22, 2019 at 14:06
  • @AndrewHenle I am worried about segmentation fault. Commented Jan 22, 2019 at 14:06
  • 1
    What is StrMove? Commented Jan 22, 2019 at 14:09

2 Answers 2

5

You are making something really simple in an extremely complicated way..

Since you flagged it , you can just use a map and return by lookup like this:

std::string Extract_Month_As_Digits(const std::string& month)
{
  static std::map<std::string, std::string> monthToDigit = {{"JAN", "01"}};//omitted init.
  auto found = monthToDigit.find(month);
  return found  != monthToDigit.end() ? *found : "";
}

If you want an exception thrown on bad input/lookup, you may reduce it to return monthToDigit.at(month);

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

2 Comments

Nice one! If you choose to use monthToDigit.at(...), you get error handling for free, too.
At least OP is (trying to) doing it without multilevel dynamic memory allocation, exceptions, stl and relying on dynamic initialization and finalization. This solution would be definitely a better match to be called "making something really simple in an extremely complicated way"
1

You're making it very complex. Simplifying the solution may result in a function that does no strcpy whatsoever:

int month_index(const char *threeDigitMonth) {
    static const char *names[] = {"JAN", "FEB", NULL};
    const char** name = names;
    while(name && strcmp(threeDigitMonth, *name)){ ++name; }
    return name - names;
}

Now your problem is reduced to converting an int into a two-digit string, something snprintf is very capable of.

Or you could use C++:

auto month_index(const std::string& threeDigitMonth) {
  static const std::unordered_map<
     std::string, std::string> months = {{
       {"JAN", "01"},
       {"FEB", "02"},
       ...
    }};
    return months.at(threeDigitMonth);
  }

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.