0

I was about to write a C++ function doing the following:

1 ---> "1st"
2 ---> "1nd"
3 ---> "3rd"
...
17657 --> "17657th"
...

i.e. produces the ordinal extension string for that number (it doesn't have to do an itoa() of the number itself). But then I thought "surely something in the standard library or boost does this already?"

Notes:

  • I know it's not hard to write this, there's an implementation in Python right here on SO, I just don't want to duplicate code.
  • I need this in English, obviously. A multi-language version would be nice for political-correctness considerations, not more than that...
Community
  • 1
  • 1
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 2
    I doubt that, this is very language-specific. – Luchian Grigore Feb 04 '14 at 09:11
  • It's NOT terribly hard to write such a function. You need a "int to string", some simple math/string work to figure out the "low end of the number" and a couple of if/case statements. But like Luchian says, this is different in different languages (and in some languages depends on the "gender" of the object being counted - e.g. if you are counting cows, it's one way, if you count bulls, it's a different way - I believe this is the case in Spanish for example). – Mats Petersson Feb 04 '14 at 09:15
  • @LuchianGrigore True, but in fairness, so is (for example) the symbol used as the decimal separator. –  Feb 04 '14 at 09:16
  • @MatsPetersson: Eventually I wrote something myself. It's strange how people can come up with such weird answers for this, with a million if's, or with sprintf'ing :-) – einpoklum Oct 31 '16 at 20:45

6 Answers6

1

Here's what I ended up writing:

const char* ordinal_suffix(int n)
{
        static const char suffixes [][3] = {"th", "st", "nd", "rd"};
        auto ord = n % 100;
        if (ord / 10 == 1) { ord = 0; }
        ord = ord % 10;
        if (ord > 3) { ord = 0; }
        return suffixes[ord];
}

The code golf solutions are cute, but - they really do optimize for terseness, not anything else. This is faster (although it could be made even faster by putting the suffixes in a .cpp out of the function body and making the code inlinable), much clearer, and still more terse than most other answers here.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
1
// Returns numbers with ordinal suffix as string
// Based on https://stackoverflow.com/questions/3109978/display-numbers-with-ordinal-suffix-in-php
std::string NumberToOrdinal(size_t number) {
  std::string suffix = "th";
  if (number % 100 < 11 || number % 100 > 13) {
    switch (number % 10) {
      case 1:
        suffix = "st";
        break;
      case 2:
        suffix = "nd";
        break;
      case 3:
        suffix = "rd";
        break;
    }
  }
  return std::to_string(number) + suffix;
}
oguz
  • 81
  • 1
  • 4
0

I'm pretty sure you can adapt the four line solution at Display numbers with ordinal suffix in PHP. Unfortunately, I don't think there is such a thing in a common C++ lib.

Community
  • 1
  • 1
hivert
  • 10,579
  • 3
  • 31
  • 56
0

try this...

#include <iostream>
using namespace std;

void suffix(int n, char suff[]);
// creates the ordinal suffix
// for a given number

int main()
{
  char s[5];
  int x;

  cout << "Enter a number to find the ordinal suffix for ";
  cin >> x;
  suffix(52111,s);
}

void suffix(int n, char suff[])
{
   if(n%100 == 11 || n%100 == 12 || n%100 == 13)
    {
      cout << "suffix is: " << n << "th";
      cout << endl;
    }
  else
    {
      if(n%10 == 1)
    {
      cout << "Suffix is: " << n << "st";
      cout << endl;
    }
      else
    {
      if(n%10 == 2)
        {
          cout << "Suffix is: " << n << "nd";
          cout << endl;
        }
      else
        {
          if(n%10 == 3)
        {
          cout << "Suffix is: " << n << "rd";
          cout << endl;
        }
          else
        {
          if(n%10 == 4 || n%10 == 5 || n%10 == 6 || n%10 == 7 || n%10 == 8 || n%10 == 9 || n%10 == 0)
              {
            cout << "Suffix is: " << n << "th";
            cout << endl;
              }
        }
        }
    }
    }
}
Indra Yadav
  • 600
  • 5
  • 22
  • How will your code work for "100"? Or "147"? (And the code could be written MUCH simpler!) – Mats Petersson Feb 04 '14 at 09:23
  • In other words, there are bugs in the above code, but conceptually resembles how I would solve it. – Mats Petersson Feb 04 '14 at 09:24
  • @hvd: Really? Have you tried it? Even stepping through the code, I've identified that it won't do that. (Well, not 147th, at least - just spotted the odd placement of zero in the last if. Won't work for 120 tho') – Mats Petersson Feb 04 '14 at 09:25
  • @MatsPetersson It really does work for `100`, but it wouldn't work for `147`, you're right, I missed that. I incorrectly read some of the `%100`s as `%10` (as no doubt intended). –  Feb 04 '14 at 09:29
  • This is way too verbose. – einpoklum Oct 31 '16 at 20:40
-1

I used the following string function to accomplish it.

#include <string>
#include <iostream>
using namespace std;

string ordinal(int i)
{
    if(i==1)
    { 
        return "First";
    }
    if(i==2)
    { 
        return "Second";
    }
    if(i==3)
    { 
        return "Third";
    }
    if(i==4)
    { 
        return "Fourth";
    }
    if(i==5)
    { 
        return "Fifth";
    }
    if(i==6)
    { 
        return "Sixth";
    }
    if(i==7)
    { 
        return "Seventh";
    }
    if(i==8)
    { 
        return "Eighth";
    }
}

int main()
{
    for(int i=0; i<8; i++) 
    {
        cout << ordinal(i+1) << " number: ";
    }
    return 0;
}
-1

#include <iostream>
#include <string>

std::string number_to_ordinal(int number)
{
  // Convert number to string
  std::string ordinal = std::to_string(number);
  
  // Get the last character of the number to later determine ordinal indicator
  char last_char = ordinal.back();
  
  // Get the last two characters of the number to deal with ordinal indicator conditions
  std::string last_two_char;
  if(ordinal.size() > 1)
    last_two_char = ordinal.substr(ordinal.size() - 2, ordinal.size());
    
  // Determine ordinal indicator. Each number with a last character ending in '1', '2',
  // and '3' require ordinal indicators of 'st', 'nd', and 'rd', respectively. However,
  // numbers with the last two characters ending in '11', '12', and '13' require 'th' 
  // as the ordinal indicator.
  if(last_two_char != "11" && last_char == '1')
    ordinal += "st";
  else if (last_two_char != "12" && last_char == '2')
    ordinal += "nd";
  else if (last_two_char != "13" && last_char == '3')
    ordinal +="rd";
  else
    ordinal += "th"; // All other numbers require 'th' as the ordinal indicator
    
  return ordinal;
}

///////////////////////////////////////////////////////////////////////
//  Main Program
///////////////////////////////////////////////////////////////////////

int main()
{
  // Test number to ordinal
  for(int i = 17657; i < 17725; i++)
    std::cout << number_to_ordinal(i) << std::endl;

  return 0;
}
Jelroy
  • 1