-3

I wanted to write a function for tolower() in c++ without using STL. When I am giving small inputs like "Hello" , I am getting correct output with my code but when I am giving input with large paragraphs which has punctuations in it , then I am getting error. Can anyone help to fix and help to understand why I am getting Error?

My code :

#include <iostream>

using namespace std;

int main()
{ 
std::string str[] = ""Mymommaalwayssaid,\"Lifewaslikeaboxofchocolates.Youneverknowwhatyou'regonnaget.""

     int n ,i;
        string UP[str.size()];

        for(int i=0;i<=str.size();i++)
        {
            if(int(str[i])<=90 && int(str[i])>=65)
            { n = int(str[i]);
                n= n+32;
                UP[i]=char(n);
            }

            else 
                UP[i] = str[i];


        }

        cout<<UP<<endl;


    return 0;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 2
    The syntax for creating an array of `std::string` is not right. Does your code compile? – R Sahu Mar 19 '19 at 21:07
  • `string UP[str.size()];` shouldn't work A. because `str` is an array that you can't call member functions on and B. because the size of an array in C++ must be known at compile-time. – scohe001 Mar 19 '19 at 21:10
  • 1
    `string UP[str.size()];` -- This is not valid C++. Also -- *I wanted to write a function for tolower()* -- The `tolower` function does a lot more than assume the language being used is English and the collating sequence is ASCII, as your attempt is doing. – PaulMcKenzie Mar 19 '19 at 21:12
  • 2
    First, don’t use magic numbers. `str[i] <= ‘z’` is much clearer than `str[i] <= 90`. Also, be aware that not all the world is ASCII. In some character encodings there are non-letters mixed in among the letters. The standard library provides `tolower` so that you don’t have to roll your own. – Pete Becker Mar 19 '19 at 21:12
  • How portable do you want to be? Sure, in most character sets, lower case letters as well as uppercase letters are consecutive ranges – but that's not *always* the case... Apart from, instead of comparing to the numbers (90, 65), you can compare to the character literals (`'Z'`, `'A'`), these share the same value, but are safer to use. Similarly: `n += 'a' - 'A'` gets the appropriate difference. – Aconcagua Mar 19 '19 at 21:13
  • You need to iterate one position less: `for(int i = 0; i < size; ++i)` (instead of `<=`). – Aconcagua Mar 19 '19 at 21:14
  • Answer to question does your code compile ?? Yes! Actually, I am very new to programming that's why there are many mistakes. Thanks for your answers. I will rectify and then post it again. – gaurav pendhari Mar 20 '19 at 02:14
  • About [using namespace std](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua Mar 20 '19 at 06:53

2 Answers2

1

A definition close to your code and correcting the errors is :

#include <iostream>
#include <string>

using namespace std;

int main()
{ 
  string str = "Mymommaalwayssaid,\"Lifewaslikeaboxofchocolates.Youneverknowwhatyou'regonnaget.";
  string lower = str;

  for (size_t i = 0; i < lower.length(); ++i) // can also use an iterator
  {
    char c = lower[i];

    if ((c >= 'A') && (c <= 'Z'))
      lower[i] += ('a' - 'A');
  }

  cout << lower <<endl;

  return 0;
}

Compilation and execution

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra t.cc
pi@raspberrypi:/tmp $ ./a.out
mymommaalwayssaid,"lifewaslikeaboxofchocolates.youneverknowwhatyou'regonnaget.

But I do not understand because you say without using STL and you use std::string.

Without std::string (iostream can be replaced by stdio.h)

#include <iostream>

using namespace std;

int main()
{ 
  const char str[] = "Mymommaalwayssaid,\"Lifewaslikeaboxofchocolates.Youneverknowwhatyou'regonnaget.";
  char lower[sizeof(str) + 1]; // if str content unknown so sizeof unknown => strlen and new/malloc etc

  for (size_t i = 0 ; i != sizeof(str); ++i)
  {
    char c = str[i];

    if ((c >= 'A') && (c <= 'Z'))
      c += ('a' - 'A');

    lower[i] = c;
  }

  lower[sizeof(str)] = 0;

  cout << lower <<endl;

  return 0;
}

Compilation and execution

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra t.cc
pi@raspberrypi:/tmp $ ./a.out
mymommaalwayssaid,"lifewaslikeaboxofchocolates.youneverknowwhatyou'regonnaget.
bruno
  • 32,421
  • 7
  • 25
  • 37
  • By saying not using STL , I mean to say not using direct function for tolower() function from STL. – gaurav pendhari Mar 20 '19 at 02:16
  • 1
    @gauravpendhari `tolower` is not an "STL" function. Neither is `sqrt`, `abs`, `strcat`, etc. It is a library function, but it has nothing to do with STL. – PaulMcKenzie Mar 20 '19 at 10:02
1

Well, the question has several confusing points. First, the question asks for an example of tolower(), but the code seems to want to create a string called UP.

I went ahead and created a string_to_lower() function. I did not want to use the same name as tolower(char* str), though that would have worked.

#include <iostream>
#include <string>

std::string string_to_lower(std::string str) {
  const uint diff = 'a' - 'A';  // create a constant from the ascii chars

  std::string lower; // return string.  Could be done with an inline reference.
  lower.reserve(str.length());

  for (int i = 0; i < str.size(); i++) { // Use a ternary to set each char
    lower += (str[i] >= 'A' && str[i] <= 'Z') ? str[i] + diff : str[i];
  }

  return lower;
}

int main()
{
  std::string str = {"My momma always said, \"Life "
                     "is like a box of chocolates."
                     "You never know what you're gonna get.\""};

  std::string lower = string_to_lower(str);
  std::cout << lower << std::endl;
  return 0;
}
Gardener
  • 2,591
  • 1
  • 13
  • 22
  • 1
    You already use qualified STL objects (`std::...`), so you really should drop [using namespace std](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua Mar 20 '19 at 06:55
  • @Aconcagua: Agreed. I have deleted the `using namespace std;` which was copied from the OP's post. – Gardener Mar 20 '19 at 18:30
  • `lower.reserve(str.size() + 1)` would prevent internal re-allocations in the result. Admitted, I'm not sure about the necessity of the +1 offset, `std::string` already might consider the terminating null character appropriately; didn't find any relevant information on [cppreference](https://en.cppreference.com/w/cpp/string/basic_string) either... – Aconcagua Mar 21 '19 at 06:49
  • @Aconcagua, I don't think it would make sense for the C++ std library to create a string class complete with lengths and everything else we used to worry about in C, only to demand that we allocate an extra byte for the null termination character. I love C, but if I have to write in C++, it should at lease abstract away the need to worry about the extra byte for the null terminating char, I hope :-) – Gardener Dec 31 '21 at 20:59
  • '*I hope'* makes me feel uncomfortable... Tried another search, found some hints not at `reserve` but at [`capacity`](https://en.cppreference.com/w/cpp/string/basic_string/capacity) documentation: *'Returns the number of characters that the string has currently allocated space for.'* and *'Note that the null terminator is not an element of the basic_string.'* – which I'd interpret in your sense (but not putting the hand in fire for...). – Aconcagua Jan 01 '22 at 09:45
  • 1
    Oh, just noticing: You can do better: You accept the input parameter as *copy* anyway, not as (const) reference – so you might rather apply the changes *in place*! `for(auto& c : str) { if(c >= 'A' && c <= 'Z') { c += 'a' - 'A'; } }` – Aconcagua Jan 01 '22 at 09:54