-4

I have written the program which intends to take an input and return the output in ascending order of characters.

Example:

Scenario 1: Given an input as "Hello Rohit", the method should return "ehHillooRt"

Scenario 2: Given an input as "Hello Rohit!", the method should return an error message ("Invalid character ! at position 12") specifying first occurrence and the position of an invalid character.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    string str;
    int i, count, n;
    cout << "Enter a sentence : ";
    getline(cin, str);
    for (i = 0; str[i] != '\0'; i++) {
        if (str[i] == ' ')
            count++;
    }
    string strWords[count + 1];
    short counter = 0;
    for (short i = 0; i < str.length(); i++) {
        if (str[i] == ' ') {
            counter++;
            i++;
        }
        strWords[counter] += str[i];
    }
    for (i = 0; i < strWords[i].length(); i++) {
        string temp = strWords[i];
        sort(temp.begin(), temp.end());
        cout << temp << " ";
    }
    return 0;
}

TylerH
  • 19,065
  • 49
  • 65
  • 86
Rohit Dubey
  • 43
  • 11
  • 4
    Please fix your indentation (do indent) and vertical spacing (you don't need all that vertical space). It will make the code easier to read. – JohnFilleau Mar 15 '20 at 16:24
  • 2
    Unrelated to your problem, but please take some time to read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Some programmer dude Mar 15 '20 at 16:27
  • 1
    Also note that C++ doesn't have [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array). Use e.g. [`std::vector`](https://en.cppreference.com/w/cpp/container/vector) instead. – Some programmer dude Mar 15 '20 at 16:28
  • The problem statement doesn't call for splitting the input into words. The example of `"Hello Rohit" -> "ehHillooRt"` clearly disregards word boundaries (note how the two `o`s are together in the output). Some four fifths of your code are dedicated to splitting into words. – Igor Tandetnik Mar 15 '20 at 16:29
  • 1
    And please take some time to refresh [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). What is the problem with the code you show? For the input you give as example, what is the *actual* output? What happens when you build or run your program? Have you tried to step through the code statement by statement in a debugger? – Some programmer dude Mar 15 '20 at 16:30
  • What output are you actually getting? Do you have a compilation error? A runtime error? Or is your output incorrect. Also I found a website where you can paste your c++ code and it will indent it for you, since your edit still suffers from strange indentation. https://codebeautify.org/cpp-formatter-beautifier – JohnFilleau Mar 15 '20 at 16:30
  • What does splitting the string into pieces on space have to do with sorting capital letters? I don't see how doing the former gets you any closer to solving the latter. – Igor Tandetnik Mar 15 '20 at 16:33
  • @IgorTandetnik I thought I would split the string, then consider each word and sort each word and then combine it all together – Rohit Dubey Mar 15 '20 at 16:38
  • What are you going to do if the word itself contains both capital and lowercase version of the same letter? E.g. `Donald` or `George`. You'd be right back where you started. – Igor Tandetnik Mar 15 '20 at 16:40

1 Answers1

1

You can use std::sort and a lambda where characters are compared using its lower case (std::tolower)

#include <algorithm>
#include <iostream>

int main()
{
  std::string str;
  std::cout << "Enter a sentence : ";
  getline(std::cin, str);

  std::sort(str.begin(), str.end(), [](const char& a, const char& b) {
    if (std::tolower(a) == std::tolower(b))
      return a > b;
    else
      return std::tolower(a) < std::tolower(b);
  });
  std::cout << str << std::endl;

  return 0;
}

This will show

Enter a sentence : Hello Rohit
 ehHillooRt

in the terminal. Note that the space is sorted in front of all the leters. If you want to delete the space you can do it with the the following line of code:

str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) { return std::isspace(x); }), str.end());

If you also want to check for unwanted elements, you can use:

std::vector<std::string> unwanted_elements{ "!" }; // Coma separed list of strings that you don't want in the input. Note that this are full strings so you could also reject "Hello" for instance.

for (size_t i = 0; i < unwanted_elements.size(); ++i)
{
  size_t idx = str.find(unwanted_elements[i]);
  if (idx != std::string::npos)
  {
    std::cout << "Unwnated element " << unwanted_elements[i] << " at position " << idx << std::endl;
  }
} 

Then the whole program would be:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
  std::string str;
  std::cout << "Enter a sentence : ";
  getline(std::cin, str);

  std::vector<std::string> unwanted_elements{ "!" }; // Coma separed list of strings that you don't want in the input. Note that this are full strings so you could also reject "Hello" for instance.

  for (size_t i = 0; i < unwanted_elements.size(); ++i)
  {
    size_t idx = str.find(unwanted_elements[i]);
    if (idx != std::string::npos)
    {
      std::cout << "Unwnated element " << unwanted_elements[i] << " at position " << idx << std::endl;
      return -1;
    }
  }

  str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) { return std::isspace(x); }), str.end());

  std::sort(str.begin(), str.end(), [](const char& a, const char& b) {
    if (std::tolower(a) == std::tolower(b))
      return a > b;
    else
      return std::tolower(a) < std::tolower(b);
  });
  std::cout << str << std::endl;

  return 0;
}

This solution works only for plain ascii characters.

Pete Becker
  • 69,019
  • 6
  • 64
  • 147
apalomer
  • 1,605
  • 11
  • 24
  • The lambda could easily have been written as: `return std::tolower(a) < std::tolower(b);` – PaulMcKenzie Mar 15 '20 at 16:49
  • No, then the capital would not appear after the lower case (that was in his examle: Hello Rohit -> ehHillooRt ) – apalomer Mar 15 '20 at 16:50
  • That's true, but note you're assuming that lowercase characters follow upper case in the collating sequence of the character set, which is not always the case if another character set is used. You should point that out in the answer. – PaulMcKenzie Mar 15 '20 at 16:54
  • I am not following you. Do you mean in the sequence of character that the user inputted (i.e. the ones in `std::string str`) or the numerical value that represents it? I always assumed a char comparison in c++ was done using the character [ascii](http://www.asciitable.com/) value. In this case, capital will always "be smaller" than lower case. – apalomer Mar 15 '20 at 16:59
  • Your solution is portable as long as you're using the `std::` functions for character determination. Once you take it on yourself to assume that character a is greater than character b by doing a strict comparison, i.e. `a > b`, you made the solution non-portable. Don't get me wrong, your solution works for ASCII, but may not work for other character sets (such as EBCDIC) – PaulMcKenzie Mar 15 '20 at 17:03
  • You are right, it just works for plain ascii characters. – apalomer Mar 15 '20 at 17:07