How to captalize and title a string - c++

If I was given a string, I need to either capitalize or title the string. For example:

There are some problems with your code. Here is the modified version of your code that works fine. Here:
std::string Capitalize(const std::string &str) {
std::string Ret;
for (int i = 0; i < str.length(); i++){
char c = str[i];
if (i == 0){
Ret += toupper(c);
}
else if (i != 0){
Ret += (tolower(c));
}
}
return Ret;}
Condition in for loop needs to be str.length() not Ret.length() and here :
std::string Title(const std::string &str) {
std::string Ret;
int i=0;
for (int i=0;i<str.size();i++) {
if(!(i==0 && str[i]==' '))
Ret += tolower(str[i]);
}
int size = Ret.length();
for (int i = 0; i < size; i++) {
if (i==0 || Ret[i - 1] == ' ')
{
Ret[i] = toupper(Ret[i]);
}
}
return Ret;}
Check if i is 0 to prevent out of range access to string.

Use a stringstream to first split all words, so that you can do this easily with a vector. This is an implementation of the Title function:
std::string Title(const std::string &str) {
std::vector<string>words;
words.clear();
std::string res = str, std::ans = "";
// It's better to pass the string AFTER you convert it all lowercase. Or you can only work with the capitalized characters:
for(int i = 0; i < res.size(); ++i){
if(res[i] >= 'A' && res[i] <= 'Z'){
res[i] = tolower(res[i]);
}
}
istringstream ss(res); // We push the modified string into a stringstream.
do{
res = "";
ss >> res;
words.push_back(res); // We split the string at " " and push each word in the vector.
} while(ss)
for(int i = 0; i < words.size(); ++i){
res = words[i];
res[0] = toUpper(res[0]); // For each word, we capitalize it
ans += res; // We add the word to our return string.
if(i < words.size() - 1){
ans += " "; // If this is not the last word, add a space
}
}
return ans;
}
As for the capitalization, you can do something like this:
std::string Capitalize(const std::string &&str){
std::string res = str;
res[0] = toupper(res[0]);
for(int i = 1; i < res.size(); ++i){
if(res[i] >= 'A' && res[i] <= 'Z'){
res[i] = tolower(res[i]); // converting if only an uppercase character.
}
}
return res; // If you pass a reference, the original will be modified so no return required.
}

Related

Difficulty writing run length encoder in c++

Trying to write this run length encoder, and it basically works but it is not passing test cases because of a '/0'.
Code
std::string run_length_encode(const std::string& str)
{
std::string encoded = "";
char prevch;
char newch;
int count = 1;
prevch = str[0];
for (int i = 0; i <= str.length(); i++)
{
newch = str[i];
if (prevch == newch)
{
count++;
}
else
{
encoded += prevch;
if (count > 1)
{
encoded += std::to_string(count);
}
prevch = newch;
count = 1;
}
}
if (prevch == newch)
{
encoded += newch;
if (count > 1)
{
encoded += std::to_string(count);
}
}
return encoded;
Error message:
Expected equality of these values:
run_length_encode("A")
Which is: "A\0"
"A"
Answer should be A but my code returns A\0.
for (int i = 0; i <= str.length(); i++)
should be
for (int i = 0; i < str.length(); i++)
In C++ string indexes start at zero and finish one before the length of the string.

Going ones through string to count length takes longer time, than moving string a couple of times?

I wrote the following two functions. In the second function, I used reserve() so that there is no memory reallocation, but unfortunately the second function is slower than the first.
I used release mode and this CPU profiler in Visual Studio to count time. In the second function, reallocation takes place 33 times. So my question is: Really? Going one length string to count length takes longer time, than moving this string 33 times?
string commpres2(string str)
{
string strOut;
int count = 0;
for (int i = 0; i < str.length(); ++i)
{
++count;
if (i < str.length() - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut += to_string(count);
count = 0;
}
}
else
{
strOut += str[i] + to_string(count);
}
}
return strOut.length() < str.length() ? strOut : str;
}
string commpres3(string str)
{
int compressedLength = 0;
int countConsecutive = 0;
for (int i = 0; i < str.length(); ++i)
{
++countConsecutive;
if (i + 1 >= str.length() || str[i] != str[i + 1])
{
compressedLength += 1 +
to_string(countConsecutive).length();
countConsecutive = 0;
}
}
if (compressedLength >= str.length())
return str;
string strOut;
strOut.reserve(compressedLength);
int count = 0;
for (int i = 0; i < str.length(); ++i)
{
++count;
if (i < str.length() - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut += to_string(count);
count = 0;
}
}
else
{
strOut += str[i] + to_string(count);
}
}
return strOut;
}
int main()
{
string str = "aabcccccaaa";
//str.size ~ 11000000;
for (int i = 0; i < 20; ++i)
str += str;
commpres2(str); //107ms //30,32% CPU
commpres3(str); //147ms //42,58% CPU
}
The 2nd function is doing more work than the 1st function, so of course it is going to take longer. Profiling the code should have shown you exactly where the code is spending its time. For instance, the 1st function loops through the str at most 1 time, but the 2nd function may loop through the same str 2 times, which by definition takes longer.
And you haven't eliminated all memory allocations from the 2nd function, either. to_string() allocates memory, and you are calling it many times before and after calling reserve(). Eliminating all of the to_string() allocations is fairly simple, using std::snprintf() into a local buffer and then std::string::append() to add that buffer to your output std::string.
You could forgo all of the pre-calculating and just reserve() the full str length even if you don't end up using all of that memory. You are not going to use up more than the original str length in the worse case scenario (no compression possible at all):
inline int to_buffer(size_t number, char *buf, size_t bufsize)
{
return snprintf(buf, bufsize, "%zu", number);
}
string commpres3(const string &str)
{
string::size_type strLen = str.length();
string strOut;
strOut.reserve(strLen);
size_t count = 0;
char buf[25];
for (string::size_type i = 0; i < strLen; ++i)
{
++count;
if (i < strLen - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
count = 0;
}
}
else
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
}
if (strOut.length() >= strLen)
return str;
}
return strOut;
}
Or, if you must pre-calculate, you can replace the 1st set of to_string() calls with something else that returns the needed length without allocating memory dynamically (see this for ideas). When calculating the size to reserve, you don't need to actually convert an integer 123 to an allocated string "123" to know that it would take up 3 chars.
inline int to_buffer(size_t number, char *buf, size_t bufsize)
{
return snprintf(buf, bufsize, "%zu", number);
}
inline int to_buffer_length(size_t number)
{
return to_buffer(number, nullptr, 0);
}
string commpres3(const string &str)
{
string::size_type strLen = str.length();
string::size_type compressedLength = 0;
size_t countConsecutive = 0;
for (string::size_type i = 0; i < strLen; ++i)
{
++countConsecutive;
if (i < (strLen - 1))
{
if (str[i + 1] != str[i])
{
strOut += 1 + to_buffer_length(countConsecutive);
countConsecutive = 0;
}
}
else
{
strOut += 1 + to_buffer_length(countConsecutive);
}
}
if (compressedLength >= strLen)
return str;
string strOut;
strOut.reserve(compressedLength);
size_t count = 0;
char buf[25];
for (string::size_type i = 0; i < strLen; ++i)
{
++count;
if (i < strLen - 1)
{
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
count = 0;
}
}
else
{
strOut += str[i];
strOut.append(buf, to_buffer(count, buf, sizeof(buf)));
}
}
return strOut;
}
33 memory allocations vs ~11000000 extra if statements.
You are doing if (i < str.length() - 1) check in every iteration but you need to do it only once.
Consider the following:
if (str.empty()) return str;
const auto last = str.length() - 1;
for (size_t i = 0; i < last; ++i)
{
++count;
if (str[i + 1] != str[i])
{
strOut += str[i];
strOut += to_string(count);
count = 0;
}
}
strOut += str[last] + to_string(count);
Some optimization hints:
You can avoid adding count if it equals to one. Otherwise, your algorithm "compresses" "abc" to "a1b1c1".
Add an indicator that the following byte is a count not a regular character to distinguish between "a5" and "aaaaa". For instance, use 0xFF. Hence, "a5" gets encoded to "a5", but "aaaaa" -> {'a', 0xFF, 5}
Store count in binary form, not ASCII. For instance, you can write 3 (0x03) instead of '3' (0x33). You can use one byte to store count up to 255.
constexpr char COMPRESS_COUNT_SEPARATOR = 0xFF;
string compress(const string &str)
{
string strOut;
if (str.empty()) return strOut;
unsigned char count = 0;
const auto last = str.length() - 1;
for (size_t i = 0; i < last; ++i)
{
++count;
if (str[i + 1] != str[i] || count == 255)
{
strOut += str[i];
if (count > 1) {
strOut += COMPRESS_COUNT_SEPARATOR;
strOut += static_cast<char>(count);
}
count = 0;
}
}
strOut += str[last];
if (count) {
strOut += COMPRESS_COUNT_SEPARATOR;
strOut += static_cast<char>(count+1);
}
return strOut;
}
Or you can even use 0x00 as COMPRESS_COUNT_SEPARATOR because C-strings cannot contain null terminators but std::string can.

Recieving "string subscript out of range" error

Doing this assignment where I parse information into a struct and I keep recieving an error saying "string subscript out of range" when trying to test. Cant figure out where I went wrong.
here is the struct
struct baby_type {
std::string name;
std::vector<int> yearsCount;
int total;
} ;
here is my function
baby_type Parse_Line(const std::string line )
{
baby_type baby;
std::string name;
std::string year;// = "0000";
std::string total;
int i = 0;
int k = 1;
int LengthOfOccurences = 0;
int DigitOfOccurences = 0;
while (line.at(i) != ',') {
name[i] = line.at(i);
i++;
}
baby.name = name;
i++;
while (k < 100) {
if (line.at(i) == ',') {
year.resize(LengthOfOccurences);
baby.yearsCount.at(k) = std::stoi(year);
//year = "0000";
i++;
k++;
DigitOfOccurences = 0;
LengthOfOccurences = 0;
}
else {
year.at(DigitOfOccurences) = line.at(i);
i++;
LengthOfOccurences++;
}
}
int m = 0;
int LengthOfLine = line.length();
while (i < LengthOfLine) {
total.at(m) = line.at(i);
m++;
i++;
}
baby.total = std::stoi(total);
return baby;
}
If you create empty std::string objects and then assign characters to specific positions. std::strings don't work that way.
In your first while loop, use
name.append(1,line.at(i));
The '1' is necessary because there is no simple std::append with just a character as parameter.

Why is this function printing an x instead of 1?

I have written a small program for run length encoding.
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1, count=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(k);
}
When I call this function using
string s = "wwwwaaadexxxxxx";
runLengthEncoding (s);
cout << endl << s;
It is printing - "w4a3d1e1x"
It should print - "w4a3d1e1x6"
My doubt is why it is not printing the last count?
Instead of using
str.resize(k)
i need to use
str.resize(k+1);
If you delete for count initialization, and resize correctly, you got it:
void runLengthEncoding (string& str)
{
int k=0;
int count =1;
for (unsigned i=1; i<str.size(); ++i)
{
if ( str[i] == str[k])
{
count +=1;
}
else
{
str[++k] = count+'0';
str[++k] = str[i];
count = 1;
}
}
str[++k] = count + '0';
str.resize(++k);
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html