0

i want to take a film name from user and change that to camel case , my code work if there is no numbers or spaces between letters

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int Count,Length=0;
    string Films;
    
    cout<<"Enter Film Count: ";
    cin>>Count;
    
    for(int i=0;i<Count;i++)
    {
        cout<<"Enter Film Names: ";
        cin>>Films;
        Length=0;
        while(Length<1000)
        {
            switch(Length)
            {
                case 0:       Films[Length]=toupper(Films[Length]); break;
                default:       Films[Length]=tolower(Films[Length]); break;
            }
            Length++;
        }
             cout<<"Results: "<<Films<<endl;
     }

    return 0;
}

i tried other topic solutions but i cant do it correctly.

Sam.a
  • 11
  • 4
  • 3
    Here's a simple way to figure out how to do this, and it never fails to work. Just take out a blank sheet of paper. Write down using short, simple sentences in plain English, a step-by-step process of doing this. When done, [call your rubber duck for an appointment](https://en.wikipedia.org/wiki/Rubber_duck_debugging). We don't write code for other people, on Stackoverflow. We always refer such questions to your rubber duck. After your rubber duck approves your proposed plan of action, simply take what you've written down and translate it directly into C++. Mission accomplished! – Sam Varshavchik Dec 31 '20 at 19:06
  • 1
    Think real, real hard about the exit condition in `while(Length<1000)`. Does it make sense to have a fixed number of iterations when you do not yet know the length of `Films`? Talk it through with the Rubber Duck Sam mentioned. – user4581301 Dec 31 '20 at 19:20
  • Hint: check for spaces. – Russ Dec 31 '20 at 19:21
  • [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Gary Strivin' Dec 31 '20 at 23:44

2 Answers2

0

Problem:

You've chosen the wrong approach to solve the problem. Your current code only changes the first character to uppercase and the rest to lowercase.

Solution:

Instead of using a while and a switch, use a for loop and an if statement that checks for spaces, delete them and change the following characters to uppercase.

Additional information:

  1. using namespace std; is considered a bad practice (More info here).
  2. The while loop can be replaced for a for loop to limit the Length scope and improve readability.
  3. It's a good practice to check whether the std::cin inputs are valid or not to prevent Undefined Behavior.

Full code:

#include <iostream>
#include <string>

int main()
{
    int count;

    std::cout << "Enter film count: ";
    std::cin >> count;
    if(std::cin.fail())
    {
        std::cout << "Invalid input." << std::endl;
        exit(0);
    }
    std::cin.ignore(10000,'\n');
    for(int i = 0; i < count; i++)
    {
        std::string film;
        std::cout << "Enter film name: ";
        std::getline(std::cin, film);
        if(std::cin.fail())
        {
            std::cout << "Invalid input." << std::endl;
            exit(0);
        }
        if(film.size() == 0)
            break;
        film[0] = tolower(film[0]);
        for(unsigned int i = 1; i < film.size() - 1; i++)
        {
            if(film[i] == ' ')
            {
                film.erase(i,1);
                film[i] = toupper(film[i]);
                i--;
            }
        }
        std::cout << "Result: " << film << std::endl;
     }

    return 0;
}

Example:

Enter film count: 1
Enter file name: Love live! the school idol movie
Result: loveLive!TheSchoolIdolMovie
Gary Strivin'
  • 908
  • 7
  • 20
0

I could see really a lot of code to solve a simple problem. I will later show a one-liner that converts a string with words to camel case.

As a side note, code should always contain tons of comments. Otherwise, nobody will understand it, and later, even you will not understand your own code.

Anyway. Let us look at the requirements. What shall we do?

  • User shal input the number of film titles to convert
  • Title for title shall be read from the user
  • Titles have to converted to camel case style and shown to the user

Now, we think an how we want to solve the problem:

  • We will always instruct the user what to do next
  • We will make sanity checks for the users input
  • We will get the number of titles from the user
  • Then, we create a loop and read title for title
  • The current read title will be converted to camel case
  • The result will be shown to the user

Ok, we need to go into details for "The current read title will be converted to camel case"

Let us think again. We get a string, that consists of words. So, we need to extract words from the string. We consider that everything is a word, that is separated by white space.

Then, depending on the camle case style, please see here, we convert all first letters of a word to uppercase and discard all white spaces. The first word will have a starting lower case letter (selectable).

But how to extract words from a string? We remember the extractor operator >> will discard all white spaces and only read the text. That is what we need. So, we will pack the string into an std::istringstream and then extract word for word.

And with a simple boolean condition, we decide, if the first letter of the first word shall be in upper- or lower case.

So, let us implement or thoughts into code:

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>

int main() {

    // Instruct user, what to do
    std::cout << "\nPlease end number of film titles to convert: ";

    // Read input from the user and check, if that was valid
    if (size_t numberOfFilms{}; std::cin >> numberOfFilms && numberOfFilms > 0) {

        // Now, in a loop, read all the film titles that the user wants to be processed
        for (size_t index{}; index < numberOfFilms; ++index) {

            // Instruct user, what to do
            std::cout << "\n\nPlease end film title " << index + 1 << ": \t";

            // Read a complete line and check, if that worked
            if (std::string line{}; std::getline(std::cin >> std::ws, line)) {

                // Put the complete string into an istringstream, so that we can extract the words
                std::istringstream lineStream{line};

                // Here we can select the style of our camel case
                bool wordShallHaveFirstLetterInUpperCase{ false };

                // Extract all words from the line stream and convert first letter
                for (std::string word{}; lineStream >> word; std::cout << word) {

                    // Depending on the camel case style
                    if (wordShallHaveFirstLetterInUpperCase) 
                        word[0] = std::toupper(word[0]);
                    else 
                        word[0] = std::tolower(word[0]);

                    // From now on all words shall start with an uppercase character
                    wordShallHaveFirstLetterInUpperCase = true;
                }
            }
            else std::cerr << "\n\n*** Error: Problem while a title\n\n";
        }
    }
    else std::cerr << "\n\n*** Error: Problem while reading the number of ilm titles\n\n";
    return 0;
}

This is a rather straight forward implementation of our detailed design. And after running some tests, we see that it will work.


Now, for the more advanced users.

In professional software development, people try to avoid loops and branch statements. Because this will increase the code complexity (usually measured via the cyclomatic complexity). And complex code needs more tests cases for C0, C1 or even MCDC code coverage.

Therefore, often algorithms from the standard library are used. And they hide the loops somehow inside. But that is OK, because the standard library is thoroughly tested and sometimes even qualified with a certification.

So, as one example, you can do the whole camel case conversion with one statement. With std::transform and by using std::regex and iterators and a stateful Lambda.

The downside is, that it is not so easy to understand for the reader . . .

Please see yourself:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <regex>
#include <string>
#include <cctype>

// The separator will be white space
const std::regex re{ R"(\s+)" };

int main() {

    // Instruct user, what to do
    std::cout << "\nPlease end number of film titles to convert: ";

    // Read input from the user and check, if that was valid
    if (size_t numberOfFilms{}; std::cin >> numberOfFilms && numberOfFilms > 0) {

        // Now, in a loop, read all the film titles that the user wants to be processed
        for (size_t index{}; index < numberOfFilms; ++index) {

            // Instruct user, what to do
            std::cout << "\n\nPlease end film title " << index+1 << ": \t"; 

            // Read a complete line and check, if that worked
            if (std::string line{}; std::getline(std::cin >> std::ws, line)) {
            
                // Convert to camel case and show output
                std::transform(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {}, std::ostream_iterator<std::string>(std::cout),
                    [firstIsUpper = 0U](std::string s) mutable {if (firstIsUpper++) s[0] = std::toupper(s[0]); else s[0] = std::tolower(s[0]); return s; });
            }
            else std::cerr << "\n\n*** Error: Problem while a title\n\n";
        }
    }
    else std::cerr << "\n\n*** Error: Problem while reading the number of ilm titles\n\n";
    return 0;
}

Ultra compact, but difficult to read . . .

In case of questions, please ask.

A M
  • 14,694
  • 5
  • 19
  • 44