c++ formating error with cstrings when using tolower - c++

Hi so I am trying to take a cstring and make it lowercase, but when I am printing the cstring at the end I am getting a weird format box where some of the letters should be. Do anyone have any ideas?
#include <string>
#include <iostream>
#include <string.h>
using namespace std;
int main ()
{
int i=0;
char* str="TEST";
char c;
char* cstr = new char[strlen(str) + 1];
while (str[i])
{
c = str[i];
c = tolower(c);
strcat(cstr, &c);
i++;
}
cout << cstr << endl;
return 0;
}

The problem is that you are calling strcat incorrectly. The second parameter is not a null-terminated string.
You really don't need to call strcat at all. Just write directly to the output string:
Try:
while (str[i])
{
c = str[i];
c = tolower(c);
cstr[i] = c;
i++;
}
cstr[i] = 0;
or, equivalently:
while(str[i])
{
cstr[i] = tolower(str[i]);
i++;
}
cstr[i] = 0;

strcat expects a null-terminated char*, so by giving the address of a local char you are invoking undefined behavior.
Additionally, new char[std::strlen(str) + 1] does not initialize the array to 0s, meaning cstr won't be properly null-terminated either; adding () to the new[] causes the array to be value-initialized.
Try this instead:
#include <cstddef>
#include <cctype>
#include <cstring>
#include <ostream>
#include <iostream>
int main()
{
char const* str = "TEST";
char c[2] = { };
char* cstr = new char[std::strlen(str) + 1]();
std::size_t i = 0;
while (str[i])
{
c[0] = static_cast<char>(std::tolower(str[i++]));
std::strcat(cstr, c);
}
std::cout << cstr << std::endl;
delete [] cstr;
}

The second argument of strcat is supposed to be a null terminated string, not the address of a single character. strcat isn't appropriate for this use.
int main ()
{
const char* str="TEST";
char* cstr = new char[strlen(str) + 1];
cstr[strlen(str)] = 0;
for (int i = 0; str[i]; ++i) {
cstr[i] = tolower(str[i]);
}
cout << cstr << endl;
}

#include <cstddef>
#include <cctype>
#include <cstring>
#include <ostream>
#include <iostream>
#include <string>
int main()
{
std::string str = "TEST";
std::string cstr;
for (std::string::const_iterator it = str.begin(); it!= str.end(); ++it)
cstr.push_back(tolower(*it));
std::cout << cstr << std::endl;
}
Or even shorter:
#include <algorithm>
#include <iterator>
...
std::transform(str.begin(), str.end(), std::back_inserter(cstr), tolower);

Related

Why can't my loop detect \0 symbol in const string?

#include<iostream>
#include<string>
#include<sstream>
#include <typeinfo>
#include<cmath>
#include<vector>
#include <algorithm>
using namespace std;
class Mystring {
char *arr;
public:
Mystring(const char pointer[]) {
int i = 0;
while (pointer[i] != '\0') {
i++;
cout << pointer[i] << endl;
}
arr = new char[i];
i = 0;
while (pointer[i] != '\0') {
arr[i] = pointer[i];
i++;
}
}
friend ostream& operator<<(ostream& out, Mystring& str) {
int i = 0;
while (str.arr[i] != '\0') {
out << str.arr[i];
i++;
}
return out;
}
};
int main() {
Mystring string("Hello, world!");
cout << string << endl;
}
I'm trying to create my own string class. The length of "hello world!" is 13, but the length of arr turns out to be 17. It is filled with some strange chars for some reason I don't understand. When I'm trying to cout string it returns this: Hello, world!¤¤¤¤.
You forgot to add '\0' at the end of your arr[].
Moreover, the size or arrshould be increased to incorporate this \0, as noted in #user7860670's answer.
Moreover, using string as a variable name, in addition to using namespace std;, is confusing at least.
#include<iostream>
#include<string>
#include<sstream>
#include <typeinfo>
#include<cmath>
#include<vector>
#include <algorithm>
//using namespace std;
class Mystring {
char *arr;
public:
Mystring(const char pointer[]) {
int i = 0;
while (pointer[i] != '\0') {
i++;
std::cout << pointer[i] << std::endl;
}
arr = new char[i+1];
i = 0;
while (pointer[i] != '\0') {
arr[i] = pointer[i];
i++;
}
arr[i] = '\0';
}
friend std::ostream& operator<<(std::ostream& out, const Mystring& str) {
int i = 0;
while (str.arr[i] != '\0') {
out << str.arr[i];
i++;
}
return out;
}
};
int main() {
Mystring mstring("Hello, world!");
std::cout << mstring << std::endl;
}
Buffer size required to hold "Hello, world!" (including terminating null) is 14 while you only allocate space for 13 chars and completely omit terminating null. So during iteration inside of operator<< buffer index will go out of bounds which is Undefined Behavior.
You should allocate one extra byte and make sure that buffer ends with terminating null
arr = new char[i + 1];
i = 0;
while (pointer[i] != '\0')
{
arr[i] = pointer[i];
++i;
}
arr[i] = '\0';

How to reverese a c-style string

I would like to reverse a c-style string and came up with the following code.
Play with the code
#include <iostream>
void reverse_c_str(char *c)
{
char *new_c = c;
for (; *new_c; ++new_c){} // find '\0'
--new_c; // new_c is now at the actual last char, which is 'g'
while (c < new_c) // swap chars
{
char tmp = *c;
*c = *new_c; // crash
*new_c = tmp;
--new_c;
++c;
}
}
int main()
{
char *c = "my string";
reverse_c_str(c);
std::cout << c << '\n';
}
Unfortunately, my code has an error, which I marked with // crash. Why does this line crash?
"my string" is a string literal, it is const.
It can be cast to a non-const char * for reasons of compatibility with C, but modifying a constant invokes undefined behavior. In some cases the OS will prevent it (as when it's stored in a read-only section), which is probably what you're observing.
Make a copy of the string in automatic storage, then you'll be able to modify it:
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout << c << '\n';
}
And of course there is a templated soultion:
#include <cstring>
template<std::size_t N>
void reverse_c_str(char (&str)[N]) {
std::size_t len = N-1;
for (std::size_t i = 0; i < len/2; ++i) {
str[i] ^= str[len-i-1];
str[len-i-1] ^= str[i];
str[i] ^= str[len-i-1];
}
}
int main() {
char c[] {"123"};
reverse_c_str(c);
char c2[] {""};
reverse_c_str(c2);
char c3[] {"4321"};
reverse_c_str(c3);
return 0;
}
Use std::swap and std::strlen. I made example for you here.
#include <iostream>
#include <cstring>
void reverse_c_str(char *c) {
int length = std::strlen(c);
for (int i = 0; i < length / 2; i++)
std::swap(c[i], c[length - i - 1]);
}
int main()
{
char c[] { "my string" };
reverse_c_str(c);
std::cout<<c << std::endl;
return 0;
}
Output:
gnirts ym
Another one version of function reverse_c_str
void reverse_c_str(char *c) {
if(*c) {
for(auto begin = c, end = c + std::strlen(c) - 1;
begin < end; ++begin, --end
) {
std::swap(*begin, *end);
}
}
}

Goal is to find common prefix between two c strings (must use specific function header)

I encounter problems when i call the function in my main function
Function definition is const char and I am using strings which i can't pass
The last definition of the function "char prefix[]" no clue what to do with it
#include <iostream>
#include <string>
using namespace std;
void prefix(const char s1[], const char s2[], char prefix[]); //Don't know what's the use of char prefix[]
int main()
{
string s1;
string s2;
cout << "Enter two sentences to store in two different strings" << endl;
getline(cin, s1);
getline(cin, s2);
const char *char1 = &s1[0];
const char *char2 = &s2[0];
prefix(char1, char2, );
return 0;
}
void prefix(const char a[], const char b[], char prefix[])
{
int i = 0;
for (; a[i] != 0 /* not a null char */ && a[i] == b[i] /* chars are
equal */; ++i)
prefix[i] = a[i]; // copy char to prefix
prefix[i] = 0; // null terminate prefix
}
Allocate memory for the prefix and pass a pointer to this memory:
#include <iostream>
#include <memory>
#include <string>
using std::cin;
using std::cout;
using std::getline;
using std::string;
void prefix(const char s1[], const char s2[], char prefix[]);
int main()
{
string s1;
string s2;
cout << "Enter two sentences to store in two different strings\n";
getline(cin, s1);
getline(cin, s2);
const char *char1 = &s1[0];
const char *char2 = &s2[0];
std::unique_ptr<char[]> p = std::make_unique<char[]>(std::min(s1.length(), s2.length()));
prefix(char1, char2, p.get());
cout << p.get();
return 0;
}
void prefix(const char a[], const char b[], char prefix[])
{
int i = 0;
for (; a[i] != 0 && a[i] == b[i]; ++i)
prefix[i] = a[i];
}

insert string into vector character by character

I'm trying to insert the characters of the string into a char vector but place the letters in reverse order . can anyone tell me why this doesn't work
int main()
{
string a = "Hello";
vector<char> arr(5);
for(int i = 4 ; i == 0 ; i--)
{
arr.push_back(a[i]);
cout << arr[i];
}
return 0;
}
im trying to push back the character in reverse order 1 by 1
Their are several problems with your code:
you are creating a vector whose size is initially 5, and then you are attempting to push 5 additional chars into it, for a total of 10 chars. You need to either:
initialize it's capacity instead of its size.
initialize the size as you are, but use arr[4-i] instead of arr.push_back() inside your loop.
your loop is never entered at all, since i == 0 is never true.
Try something more like this instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
size_t len = a.size();
vector<char> arr;
arr.reserve(len);
for(int i = len-1; i >= 0; i--) {
arr.push_back(a[i]);
}
for(size_t i = 0; i < len; ++i) {
cout << arr[i];
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
size_t len = a.size();
vector<char> arr(len);
for(int i = len-1; i >= 0; i--) {
arr[len-1-i] = a[i];
}
for(size_t i = 0; i < len; ++i) {
cout << arr[i];
}
return 0;
}
Another way to deal with this in a more C++-ish way is to use iterators instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr;
arr.reserve(a.size());
for(auto iter = a.rbegin(); iter != a.rend(); ++iter) {
arr.push_back(*iter);
}
for(auto ch : arr) {
cout << ch;
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.size());
auto arr_iter = arr.begin();
for(auto a_iter = a.rbegin(); a_iter != a.rend(); ++a_iter, ++arr_iter) {
*arr_iter = *a_iter;
}
for(auto ch : arr) {
cout << ch;
}
return 0;
}
And then you can get rid of the manual loops altogether:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr;
arr.reserve(a.size());
copy(a.rbegin(), a.rend(), back_inserter(arr));
cout.write(arr.data(), arr.size());
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.size());
copy(a.rbegin(), a.rend(), arr.begin());
cout.write(arr.data(), arr.size());
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.rbegin(), a.rend());
cout.write(arr.data(), arr.size());
return 0;
}
I'm not sure why you're complicating matters when a vector is perfectly capable of taking an iterator in the constructor? The vast majority of your code can therefore be replaced with a simple:
vector<char> arr(a.rbegin(), a.rend());
The complete program below shows this in action:
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string; using std::vector;
int main() {
string a = ")-: yug emosdnah a si xaP";
vector<char> arr(a.rbegin(), a.rend());
for (auto ch: arr) cout << ch;
cout << '\n';
}
for(int i = 4 ; i == 0 ; i--)
That means to keep going while i is equal to zero - but i starts out at four, so the for loop terminates immediately.
You probably meant
for(int i = 4 ; i >= 0 ; i--)

How to split char pointer with multiple delimiters & return array of char pointers in c++?

In the duplicate of this question Split char* to char * Array it is advised to use string rather than char*. But I need to work with LPWSTR. Since it's a typedef of char*, I prefer to use char*. I tried with the following code, which gives the wrong output:
char**splitByMultipleDelimiters(char*ori,char deli[],int lengthOfDelimiterArray)
{
char*copy = ori;
char** strArray = new char*[10];
int j = 0;
int offset = 0;
char*word = (char*)malloc(50);
int length;
int split = 0;
for(int i = 0; i < (int)strlen(ori); i++)
{
for(int k = 0; (k < lengthOfDelimiterArray) && (split == 0);k++)
{
if(ori[i] == deli[k])
{
split = 1;
}
}
if(split == 1)//ori[i] == deli[0]
{
length = i - offset;
strncpy(word,copy,length);
word[length] = '\0';
strArray[j] = word;
copy = ori + i + 1;
//cout << "copy: " << copy << endl;
//cout << strArray[j] << endl;
j++;
offset = i + 1;
split = 0;
}
}
strArray[j] = copy;
// string strArrayToReturn[j+1];
for(int i = 0; i < j+1; i++)
{
//strArrayToReturn[i] = strArray[i];
cout << strArray[i] << endl;
}
return strArray;
}
void main()
{
char*ori = "This:is\nmy:tst?why I hate";
char deli[] = {':','?',' ','\n'};
int lengthOfDelimiterArray = (sizeof(deli)/sizeof(*deli));
splitByMultipleDelimiters(ori,deli,lengthOfDelimiterArray);
}
Are there any other ways to split LPWSTR?
Wait, what are you talking about? I don't see LPWSTR anywhere in your code. Are you trying to convert to LPWSTR? If so, there's a standard library function for that. There's also a standard library-based solution for splitting over multiple chars. So all together, your code might look like this:
#include <codecvt>
#include <cstdio>
#include <locale>
#include <sstream>
#include <string>
using std::string;
using std::wstring;
wstring toWide(const string &original)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(narrow_utf8_source_string);
}
std::vector<wstring> splitMany(const string &original, const string &delimiters)
{
std::stringstream stream(original);
std::string line;
while (std::getline(original, line))
{
std::size_t prev = 0, pos;
while ((pos = line.find_first_of(delimeters, prev)) != std::string::npos)
{
if (pos > prev)
wordVector.push_back(line.substr(prev, pos-prev));
prev = pos + 1;
}
if (prev < line.length())
wordVector.push_back(line.substr(prev, std::string::npos));
}
}
int main()
{
string original = "This:is\nmy:tst?why I hate";
string separators = ":? \n"
std::vector<wstring> results = splitMany(original, separators);
}
This code uses the standard library for these functions and is much less error-prone than doing it manually.
Good luck!
Edit: To be clear, wstring == LPWSTR == wchar_t*.
Edit 2: To convert a string to a wstring:
#include <codecvt>
#include <locale>
#include <string>
using std::string;
using std::wstring;
string toMultiByte(const wstring &original)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(original);
}