Merge sort the character in a std:string - c++

So I am trying to Merge Sort the letters of a string so that they are in order. Capitalization does not matter since the homework does not require it. For some reason I cannot get templet[index] = split[leftfirst]. I get an "no suitable conversion function from std::string to char exists". Heres my merge function
void merge(string *split, int leftfirst, int leftlast, int rightfirst, int rightlast)
{
string templet;
int index = leftfirst;
int savefirst = leftfirst;
while ((leftfirst <= leftlast) && (rightfirst <= rightlast))
{
if (split[leftfirst] < split[rightfirst])
{
templet[index] = split[leftfirst];
leftfirst++;
}
else
{
templet[index] = split[rightfirst];
rightfirst++;
}
index++;
}
while (leftfirst <= leftlast)
{
templet[index] = split[leftfirst];
leftfirst++;
index++;
}
while (rightfirst <= rightlast)
{
templet[index] = split[rightfirst];
rightfirst++;
index++;
}
for (index = savefirst; index <= rightlast; index++)
split[index] = templet[index];
}
Any help is appreciated.

split is a string*, which means split[some] will not get a character out of the string, it will rather get a string from a string array.
Easiest way to fix this is to change the function definition to have string &split, if you want to modify the variable.

Related

C++ Call string into function?

Not sure how to exactly explain this, sorry. I'm creating a function to find the first instance of a char in an array built by a given string. I have the function to create an array from the string and loop through the array, but not sure how to put it the array into the find function.
the tester is built like
stringName("Test test test");
stringName.find("e",0); //where 0 is the starting position, so it would return 1.
int SuperString::find(char c, int start) {
// put array grabber thing here
size = *(&data + 1) - data;
for(int i = start; i < size ; i++){
if(data[i] == c){
return i;
}
}
return -1;
}
This is what I have to make the string into an array.
SuperString::SuperString(std::string str) {
size = str.size();
data = new char[size];
for (int i = 0; i < size; i++) {
data[i] = str.at(i);
}
}
This is probably something easy I'm missing, but any help is appreciated.
You are passing a string literal, specifically a const char[2], where a single char is expected. Use 'e' instead of "e":
stringName.find('e', 0);
More importantly, size = *(&data + 1) - data; will only work when data is a (reference to a) fixed array (see How does *(&arr + 1) - arr give the length in elements of array arr?). It will not work when data is a pointer to an array, as it is in your case since you are allocating the array with new char[]. You will have to keep track of the array's size separately, which you appear to be doing, except that you are not actually using the size you obtained in the SuperString constructor. Just get rid of the line in find() that is trying to re-calculate size, use the value you already have:
int SuperString::find(char c, int start) {
// size = *(&data + 1) - data; // <-- GET RID OF THIS
for(int i = start; i < size; ++i){
if (data[i] == c){
return i;
}
}
return -1;
}
That being said, Your SuperString class can be greatly simplified if you just make its data member be a std::string instead of char*, eg:
#include <string>
class SuperString {
private:
std::string data;
...
public:
SuperString(const std::string &str);
int find(char c, int start = 0);
...
};
SuperString::SuperString(const std::string &str) : data(str) {
}
int SuperString::find(char c, int start) {
return (int) data.find(c, start);
}

Why am I getting string reversal wrong with a trailing space character?

I am unable to get why there is a space and it is getting me wrong.
Below is the code I wrote for the solution
Why there is blank space char at the end of the string at the end even after reversing my string.
Question
class Solution {
public:
string minRemoveToMakeValid(string s) {
string str = "";
int n = s.length();
int open=0;
for(int i=0;i<n;i++){
if(s[i]=='('){
open++;
}else if(s[i]==')'){
open--;
if(open<0){
open=0;
continue;
}
}
str+=s[i];
}
open=0;
string s2="";
for(int i=n-1;i>=0;i--){
if(str[i]==')'){
open++;
}else if(str[i]=='('){
open--;
if(open<0){
open=0;
continue;
}
}
s2=s2+str[i];
}
reverse(s2.begin(),s2.end());
return s2;
}
};
Leetcode Submission getting wrong
The length of str may be less than one of s, but you are using the length of s while iterating within str. You must use correct length.
string s2="";
n = str.length(); // add this
for(int i=n-1;i>=0;i--){

Counting blank spaces to get word count

I have a homework assignment in which I have to return the number of words in a string based on the number of blank spaces. Here is my code, I am not sure what is wrong with it but I keep getting error messages when I try to compile it.
string getWordCount(string sentence){
int count = 1;
for(int i = 1; i < sentence.length(); i++){
if (s[i]==' '){
count++;
}
}
return count;
}
The error messages are:
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To compile your code, you must ensure that return type (count is an int) is compatible with the declared return type of the function (you said it would return string). So instead of:
string getWordCount(string sentence)
declare your function as :
int getWordCount(string sentence)
Note also that you use s[i], but s is not declared. You probably mean sentence[i].
Consider also solving the different algorithmic errors mentionned in the comments (i.e. wrong result for an empty string, for a string with only blank, and depending on the exercise narative, for a string where several consecutive spaces are used between two words) to finish your homework and improve your skills.
You are passing in a variable named sentence but parsing on a variable named s. Also, count is an int but your return type is string. Try this:
int getWordCount (string sentence)
{
int count = 1;
for (int i = 0; i < sentence.length (); i++)
{
if (sentence[i] == ' ')
count++;
}
return count;
}
What they said.
Plus ...Avoid indexing with square brackets. Use range-based for loops. Be careful about trivial input (no words, or even an empty string, in this case). Do not assume that white space is only spaces, or that it only comprises one character. Input parameters that a function does not modify can be declared const-reference, to avoid making an un-needed copy. Use #include <algorithm> for common tasks.
SPOILER ALERT. Read no more until you after you have finished the assignment.
#include <cctype>
#include <string>
int get_word_count(const std::string &sentence)
{
int count = 0;
bool scanning_a_word = false;
for (auto ch : sentence) {
if (!std::isspace(ch)) {
if (!scanning_a_word) {
count += 1;
scanning_a_word = true;
}
} else {
scanning_a_word = false;
}
}
return count;
}
Bonus (and better) solution. The following does not use a state-variable (scanning_a_word). I call that kind of code "bread crumb programming". You leave bread crumbs along the trail to show where you've been. Sometimes birds eat the bread crumbs. Look Ma, no crumbs!
#include <algorithm>
int get_word_count(const std::string &sentence)
{
int count = 0;
auto next = sentence.begin();
const auto done = sentence.end();
while(done != next) {
next = std::find_if_not(next, done, std::isspace);
if (done != next) {
count += 1;
next = std::find_if(next, done, std::isspace);
}
};
return count;
}
Generally, when a variable is not declared within a scope you defined it inside something locally and it does not exist after that block of code (i.e. for loop) has finished executing. Or, you have not declared the variable at all.
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
Assuming you were trying to iterate through the parameter you passed in, which is a string called sentence, I either change the variable name to s of the parameter, copy the string into another string called s, or change s to sentence in the loop. The different variations are shown below:
// change parameter name to s
string getWordCount(string s)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
// change s to sentence inside the loop
string getWordCount(string sentence)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (sentence[i]==' ')
count++;
}
return count;
}
// create a string s, and copy sentence into string s
string getWordCount(string sentence)
{
int count = 1;
string s = strcpy(s, sentence);
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
For your second error, generally this error occurs when there is an issue with casting a variable type to another type. In your case, the below error occurs because you are declaring a function will return a string, however, you are trying to return an int.
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To fix this error, simply change the return type to int. However, if you really want to return the count as a string for some reason, convert the integer to a string before returning. Both variations are shown below.
// Change return type to int to match count's type
int getWordCount(string sentence)
{
int count = 1;
...
...
return count;
}
// If you really need to send count back as a string for some reason, convert the int to string
string getWordCount(string sentence)
{
int count = 1;
...
...
return itoa (count);
}
Please note: this is only describing why your compilation errors are occurring and how to fix them so that you can continue on with your homework assignment. This is not describing what is wrong, logically, with your code.

Char pointer objects and respective char array element comparisons

I am programming my custom string class with multiple methods. The issue is that the comparison method does not work as I intend. Instead of doing nothing when the two char arrays differ, an if conditional still proceeds in my main function.
There are no errors given when I compile with g++. The code is syntactically correct, however logically faulty. I know this because I can give the compare method two char arrays which differ in content, and it will not matter whether they differ this way, as the main function will run the if conditional for "s8.compare(s7) == 1" regardless if the result in the compare method is not true.
I will post the entire code below. Any help is greatly appreciated.
string.h
class Str {
private:
char *value;
int length;
int capacity;
//Doubles the size of the string when called.
void growArray();
//If the two strings are uneven, get absolute value of difference in length.
int difference(int a, int b);
//Calculates the size of a character array, passed in as an argument
int getCharArrSize(const char *v);
public:
Str();
explicit Str(const char *STR);
void copy(Str s);
void concatenate(Str s);
bool compare(Str s);
void print();
};
//Str constructor
Str::Str() {
//Assign value, capacity, and length to any new Str object
value = new char[100];
capacity = 100;
length = 0;
}
//Pass STR object as a pointer to string object constructor
Str::Str(const char *STR) {
length = getCharArrSize(STR);
capacity = 100;
value = new char[capacity];
//Copy contents from STR to string object
for (int i = 0; i < length; i++)
value[i] = STR[i];
}
//Doubles the size of the string when called.
void Str::growArray() {
const char *tmp = value;
capacity *= 2;
value = new char[capacity];
for (int i = 0; i < length; i++)
value[i] = tmp[i];
}
//If the two strings are uneven, get absolute value of difference in length.
int Str::difference(int a, int b) {
int d = 0;
if (a > b) d = a - b;
else if (b > a) d = b - a;
return d;
}
//Calculates the size of a character array, passed in as an argument
int Str::getCharArrSize(const char *v) {
int c = 0;
while (v[c] != '\0') {
c++;
}
return c;
}
//Overwrites the data of the string array with the data contained in s
void Str::copy(Str s) {
//Check ability for empty string object to hold Str s contents
if (capacity > s.length) {
//Copy over each element until s length is reached
for (int i = 0; i < s.length ; i++)
value[i] = s.value[i];
//Set string object length to copy's size
length = getCharArrSize(value);
} else { growArray(); }
}
//Concatenate Str s onto string object
void Str::concatenate(Str s) {
//Check ability for string object to hold itself and concatenated chars
if (capacity > length + s.length) {
//Fill string object with s object until end of combined lengths if necessary
for (int i = 0; i < length + s.length; i++)
value[length + i] = s.value[i];
//Set length based on chars in concatenated string object
length = getCharArrSize(value);
} else { growArray(); }
}
//Compare each element in Str s against string for similarities
bool Str::compare(Str s) {
if (length == s.length) {
if (*value == *s.value) {
while ((*value != value[length]) && (*s.value != s.value[s.length])) {
value++;
s.value++;
}
return true;
} else return false;
} else {
difference(length, s.length);
}
}
//Print function
void Str::print() {
std::cout << value << std::endl;
}
main.cpp
#include"string.h"
int main() {
Str s1("Hello ");
Str s2("World");
Str s3(", my ");
Str s4("Name ");
Str s5("is ");
Str s6("Chad!");
Str s7;
s7.copy(s1);
s7.concatenate(s2);
s7.concatenate(s3);
s7.concatenate(s4);
s7.concatenate(s5);
s7.concatenate(s6);
s7.print();
std::cout << "\n\n";
Str s8("Hello World, My Name is Chad!");
if (s8.compare(s7) == 1) {
std::cout << "They Match!" << std::endl;
}
Str s9("I dont match....");
if (s9.compare(s8) == 0) {
std::cout << "I differ by " << s8.compare(s6) << " characters" << std::endl;
}
}
The above code returns a result that appears correct, however changing (s8.compare(s7) == 1) to something like (s8.compare(s5) == 1) returns 'They match!' when I am trying to check each individual element in the char arrays against one another, and only return true if they are the same length and each character matches in the arrays.
Your program has undefined behavior since Str::compare does not have a return statement in one of the branches.
bool Str::compare(Str s) {
if (length == s.length) {
...
} else {
// Missing return statement.
difference(length, s.length);
}
}
Perhaps you want to change that line to:
return (difference(length, s.length) == 0);
Your loop is running without a comparison. You compare the initial values in the char array and then loop through the rest without comparison. So you will return true every time the initial values are equal.
Below the loop runs after the same length is determined then every char is compared. If they are not equal then the function will return false. Otherwise the function will return true.
bool Str::compare(Str s) {
if (length == s.length) {
while ((*value != value[length]) && (*s.value != s.value[s.length])) {
if (*value == *s.value) {
value++;
s.value++;
} else {
return false;//will return false as soon as a comparison is false
}
}
return true;
} else {
difference(length, s.length);
}
}
You also need to return a boolean from the difference function. If you want to return ints from that function switch to a int return on the compare function and use 0 and 1s as their boolean counterparts.

Searching a array of strings

Basically the purpose of this program is to read up to 100 names from file, sort with a bubblesort, and then search for a entered name by binary search.
All seems to be working except when I enter a name that is in the list, nothing happens, I'm just prompted to enter a name again.
Say a name in the list in Elvis Presley. I am prompted to enter a name. I type in Elvis Presley. I SHOULD recieve Elvis Presley is your friend. Not happening. Any help appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void bubblesort(string[], const int);
void search(string[], const int);
int sub = 0;
int main()
{
const int maxsize = 100;
string friendArray[maxsize];
ifstream friends;
friends.open("myFriends.dat");
while (sub < maxsize && getline(friends, friendArray[sub]))
sub++;
bubblesort(friendArray, sub);
search(friendArray, maxsize);
system("pause");
return 0;
}
void bubblesort(string *array, const int size)
{
bool swap;
string temp;
do
{
swap = false;
for (int count = 1; count < (size - 1); count++)
{
if(array[count-1] >array[count])
{
temp = array[count-1];
array[count-1] = array[count];
array[count] = temp;
swap = true;
}
}
}
while(swap);
}
void search(string *array, int size)
{
int first = 0;
int last = size - 1;
int middle;
string name;
bool friends = false;
do
{
cout<<"Please enter a name or END to terminate:";
cin>>name;
}
while(!friends && first <= last && name != "END");
{
middle = (first + last) / 2;
if (array[middle] == name)
{
friends = true;
cout<<array[middle]<<" is my friend."<<endl;
}
else if (array[middle] > name)
last = middle - 1;
else
last = middle + 1;
}
}
In your search() function, the do { } while; { } construct is flawed. It will compile but it doesn't do what you want. I made a few changes and rearranged your code so it makes more sense.
void search(string *array, int size)
{
string name;
for (;;)
{
cout<<"Please enter a name or END to terminate:";
getline(cin, name);
if (name == "END") break;
int first = 0;
int last = size - 1;
bool friends = false;
while (!friends && first <= last)
{
int middle = (first + last) / 2;
if (array[middle] == name)
{
friends = true;
cout<<array[middle]<<" is my friend."<<endl;
}
else if (array[middle] > name)
last = middle - 1;
else
first = middle + 1;
}
}
}
int main () // test the search() function
{
string array[] = { "bird", "cat", "dog", "horse", "loon", "zebra" };
search(array, 6);
}
SO, is this too much homework help? Should I delete this?
I find it interesting that you set last in both cases where you don't find a match.
The first thing you should do is think about what that means, nudge, nudge, wink, wink :-)
You should also pass the number of used elements to search as well, rather than the size of the array (since you may not be using the full array).
I suppose that
search(friendArray, maxsize);
should be
search(friendArray, sub);
Binary search's input condition is that the searched-in array is sorted. Your array looks like this:
Aaron Burr
Bill Cosby
Celine Dion
...
Zachary Taylor
""
""
""
""
etc.
Since an empty string is not less than a non-empty string, friendArray[0..maxsize] is not sorted, while the array friendArray[0..sub] is.
EDIT: I also just noticed that your binary search algorithm is flawed. Look again at your source material (text book, wikipedia, whatever). Isn't first supposed to be updated inside your loop?
Operator >> reads formatted data from the stream, i.e. discards white spaces. When you say cin >> name; and enter "Elvis Presley", only "Elvis" get stored in name.
What you need is getline(cin, name);
Think what will happen if the length of your friends array would be 3. If I'm not mistaken there will be a problem.
Also it is recommended to use safer data types, like vector<string> for example, then you do not need to care about too much data in the input file. Also your life will get easier in the search function, since you can use iterators and do not need to pass the size of the array.
Take a look at what people say in the other answers about cin.
This is one do-whie loop:
do
{
cout<<"Please enter a name or END to terminate:";
cin>>name;
}
while(!friends && first <= last && name != "END");
The code will basically loop forever (friends will never be true and first will never be > last), prompting you for a name until you either kill the program or type in "END".
This:
{
middle = (first + last) / 2;
if (array[middle] == name)
{
friends = true;
cout<<array[middle]<<" is my friend."<<endl;
}
else if (array[middle] > name)
last = middle - 1;
else
last = middle + 1;
}
will not get a chance to execute until the loop condition is false (in this case, until you type in "END").
You say that all seems to be working except when you entered a name to be searched. Actually , you stepped into point.There is a mistake in your binary search code. And the first answer in this topic is toward this way.
If array is used in binary search , it must be split into two parts in each stage of search.
For example in a stage if current part is marked as follows : first - middle - last on the next stage the parts will be either between first - middle-1 or middle+1 - last.
So
else if (array[middle] > name)
last = middle - 1;
else
last = middle + 1;
must be
else if (array[middle] > name)
last = middle - 1;
else
first = middle + 1;
You have an off-by-one error in your sort.
The problem is in function search. move the } after cin>>name to the end of the function to look like:
void search(string *array, int size)
{
int first = 0;
int last = size - 1;
int middle;
string name;
bool friends = false;
do
{
cout<<"Please enter a name or END to terminate:";
cin>>name;
while(!friends && first <= last && name != "END");
{
middle = (first + last) / 2;
if (array[middle] == name)
{
friends = true;
cout<<array[middle]<<" is my friend."<<endl;
}
else if (array[middle] > name)
last = middle - 1;
else
last = middle + 1;
}
}
}