C++ char-by-char comparison of a string - c++

I'm trying to work on a string comparison check for an introductory C++ course; it's an online course and unfortunately the instructor is not very responsive. For a current lab, I need to perform a number of manipulations on string data.
Currently, I'm working on a step to check if a string has any repeated characters, and if a repetition is found, to delete the repeated characters at their present spot and move one copy of the letter to the beginning of the string. This is only to be done for the first double to be found.
I've set up a basic counter to move through the string looking for matches, checking a stored character (updated on each iteration) to the current position in the string.
I tried multiple string functions (comparing the current inputString[i] to the previous such, stored as a second string tempStore), but those always gave char conversion errors. I've tried the below instead, but this is now giving an error: "invalid conversion from 'char' to 'const char*'.
inputString is given by the user, testA and testB are defined as type char
Any ideas?
while (opComplete == false) {
if (i == 0) {
i++;
}
else if (i == inputString.size()) {
//Not Found
opComplete = true;
}
else if (i > 0) {
testA = inputString[i-1];
testB = inputString[i];
if (strcmp(testA,testB) != 0) {
i++;
}
else {
inputString.insert(0,inputString[i]);
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}

Your problem is in this line:
inputString.insert(0,inputString[i]);
The std::string.insert() function the way you call it here has the following signature:
string& insert ( size_t pos1, const char* s );
so it expects a const char pointer. You, however, are giving it the inputString[i]. The return value of std::string.operator[] is a reference (as here), hence the error. However, by the time you reach your else, you already have the desired character in your testB variable, so you can just change the line to
inputString.insert(0, &testB);
You also can't pass normal chars into strcmp. You can use operator==, or, in your case, operator!= though.

You are using the insert method incorrectly, check its reference here for possible arguments.
while (opComplete == false)
{
if (i == 0)
i++;
else if (i == inputString.size())
opComplete = true;
else if (i > 0) {
char testA = inputString[i-1];
char testB = inputString[i];
if(testA!=testB)
i++;
else {
inputString.insert(0,&testB); //Problem Corrected here.
inputString.erase(i,1);
inputString.erase(i-1,1);
opComplete = true;
}
}
}

Related

Simple Word Guessing Game

bool guess(char c)
{
if (guesses[c])
{
guesses[] = c;
return true;
}
else if (c > ='a' && c <= 'z')
{
guesses[] = c;
return false;
}
}
bool guesses[255] = {};
I need to use this to see if the person has enter a char between a - z and if they haven't I return true else I will return false. either way I will also update guesses with the char. Right now I don't understand how to add char to the array, so that next time I check the it will be false and tell them it was already guessed. I understand this is using the ASCII table but beyond that I am lost. Could anyone explain why this won't work.
I currently get the error
expected primary-expression before']'
but if I take bracket out I get
incompatible type char to bool
which make sense but then how do I make it so where char c is will be mark true in the Boolean array
You've left your brackets empty, so you currently aren't providing an index:
guesses[c] = c;
But you also don't want to assign the char to guesses, you'd want to assign a bool:
guesses[c] = true;
That will compile* and fix your problem.
* Note you also have a syntax error with > =, which I assume was just a copy+paste issue from the editor to the question, but you should fix that also to be >=. Your function guess can also potentially not return (if neither the if or else if are true), which is undefined behaviour. You should ensure all control paths return a value, and you should make sure you compile at the highest warning level so you are warned about these things.
But not your design.
Since you're only dealing with characters a-z, you don't need to allocate all 255 elements like you do. You could simply minus the character to obtain the correct index:
bool guesses[26];
if (c >='a' && c <= 'z')
guesses[c-'a'] = true;
Consider instead using a std::set, a container of unique elements, to track whether a character has been pressed:
#include <set>
std::set<char> guesses;
bool guess(char c)
{
// Have we already inserted this character?
if (guesses.find(c) != std::end(guesses))
{
// Character has already been guessed:
std::cout << "This character has already been guessed";
return true;
}
else if (c >= 'a' && c <= 'z')
{
// Valid guess:
guesses.insert(c);
return false;
}
}

non-standard syntax use '&' to create a pointer to member c++

I have created two vectors o3 ( a vector to hold the words from a string) and o4 ( a vector to hold those vector of words). In the if statement, once ";" has been found in the vectoro3[i], I want to stop putting words from thato3[i]` into o4, and go to the next line held in o3. I am getting the error "non-standard syntax use '&' to create a pointer to member c++" in the line commented as ERROR. Any help is highly appreciated. Thanks!
while (getline(myfile, line, (char)32)) // first read entire line into a
//string
// problem : this also reads empty lines
// and gives error
// while returning words
{
abc2.push_back(line); // inserting individual strings into a vector
//cout << abc[i] << "\n"; // use this to see
// them as a vector of lines
//i++;
}
for (int i = 0; i < abc.size(); i++)
{
single_line = abc[i];
if (((single_line[0] >= 'A') && (single_line[0] <= 'Z')) ||
((single_line[0] >= 'a') && (single_line[0] <= 'z')))
{
if (abc[i] != "")
{
o3 = output_words(abc[i], (char)32); // function to separate
//words in a line
int j1 = 0; int j2 = 0;
while (j2 < o3.size())
{
if (o3[j2] != "" && "\t") // *IMP* require this line to
// get words
// irrespective of spaces
{
if (o3[j2].find != ";") // ERROR
{
o4.resize(i + 1);// NO CLUE WHY IT WORKED WITH
// i+1 resize???!!!
o4[i].push_back(o3[j2]);
j2++;
}
else
{
j2++;
}
}
else
{
j2++;
}
}
}
}
else
{
o3 = { "" }; // o1 will be null vector (i.e will contain
// nothing inside)
o4.push_back(o3);
}
}
The result of expression o3[j2].find is a member of o3[j2] by the name find. That result is then compared with the string literal in the full expression o3[j2].find != ";".
The warning message seems to imply, that decltype(o3[j2])::find is a member function. In this context, the name of the member function decays to a member function pointer. The compiler warns you because such implicit conversion is ill-formed according to the standard, but supported as a language extension by the compiler. The standard way is to use the address-of operator & explicitly.
Comparing (a pointer to) a member function to a string literal makes little sense. You may have intended to call the member function instead. To call a function, you add the argument list surrounded by parenthesis: o3[j2].find(/* arguments */).
Assuming decltype(o3[j2]) is std::string (you forgot to declare o3), then the comparison with string literal also seems suspicious. std::string::find returns the index of the found substring or character. Comparing an integer to a string literal doesn't make any sense either. I recommend pondering what that line is supposed to do.

iterating vector of strings C++

The code is to read instructions from text file and print out graphic patterns. One is my function is not working properly. The function is to read the vectors of strings I've got from the file into structs.
Below is my output, and my second, third, and sixth graphs are wrong. It seems like the 2nd and 3rd vectors are not putting the correct row and column numbers; and the last one skipped "e" in the alphabetical order.
I tried to debug many times and still can't find the problem.
typedef struct Pattern{
int rowNum;
int colNum;
char token;
bool isTriangular;
bool isOuter;
}Pattern;
void CommandProcessing(vector<string>& , Pattern& );
int main()
{
for (int i = 0; i < command.size(); i++)
{
Pattern characters;
CommandProcessing(command[i], characters);
}
system("pause");
return 0;
}
void CommandProcessing(vector<string>& c1, Pattern& a1)
{
reverse(c1.begin(), c1.end());
string str=" ";
for (int j = 0; j < c1.size(); j++)
{
bool foundAlpha = find(c1.begin(), c1.end(), "alphabetical") != c1.end();
bool foundAll = find(c1.begin(), c1.end(), "all") != c1.end();
a1.isTriangular = find(c1.begin(), c1.end(), "triangular") != c1.end() ? true : false;
a1.isOuter = find(c1.begin(), c1.end(), "outer") != c1.end() ? true : false;
if (foundAlpha ==false && foundAll == false){
a1.token = '*';
}
//if (c1[0] == "go"){
else if (c1[j] == "rows"){
str = c1[++j];
a1.rowNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "columns"){
str = c1[++j];
a1.colNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "alphabetical")
a1.token = 0;
else if (c1[j] == "all"){
str = c1[--j];
a1.token = *str.c_str();
j++;
}
}
}
Before debugging (or posting) your code, you should try to make it cleaner. It contains many strange / unnecessary parts, making your code harder to understand (and resulting in the buggy behaviour you just described).
For example, you have an if in the beginning:
if (foundAlpha ==false && foundAll == false){
If there is no alpha and all command, this will be always true, for the entire length of your loop, and the other commands are all placed in else if statements. They won't be executed.
Because of this, in your second and third example, no commands will be read, except the isTriangular and isOuter flags.
Instead of a mixed structure like this, consider the following changes:
add a default constructor to your Pattern struct, initializing its members. For example if you initialize token to *, you can remove that if, and even the two bool variables required for it.
Do the parsing in one way, consistently - the easiest would be moving your triangular and outer bool to the same if structure as the others. (or if you really want to keep this find lookup, move them before the for loop - you only have to set them once!)
Do not modify your loop variable ever, it's an error magnet! Okay, there are some rare exceptions for this rule, but this is not one of them.
Instead of str = c1[++j];, and decrementing later, you could just write str = c1[j+1]
Also, are you sure you need that reverse? That makes your relative +/-1 indexing unclear. For example, the c1[j+1 is j-1 in the original command string.
About the last one: that's probably a bug in your outer printing code, which you didn't post.

Recursive C++ Function To Move Specific Characters To End Of String

I am attempting to write a recursive function that, given a string, recursively computes a new string where all the lowercase 'x' chars have been moved to the end of the string.
For example,
moveXs("xxre") --> "rexx"
moveXs("xxhixx") --> "hixxxx"
moveXs("xhixhix") --> "hihixxx"
I am relatively new to C++ and especially to recursion (unfortunately the function must employ this method to solve the problem), so I am having trouble with this problem. Below is the code I have written thus far, but it seems to be returning only empty strings and I can't for the life of me figure out why.
string moveXs(const string& str)
{
string strCopy = str;
if (strCopy.length() <= 1)
{
return str;
}
else if (strCopy[0] == 'x')
{
strCopy = strCopy.substr(1, strCopy.length() - 1) + str[0];
return moveXs(strCopy.substr(0, (strCopy.length() - 2)));
}
else
{
return strCopy.substr(0, 1) + moveXs(strCopy.substr(1, strCopy.length() - 1));
}
}
Any help or advice would be greatly appreciated!
Looks like you just had some indexing issues. I modified your code here, and note the new returns. Also I got rid of the extraneous second string.
string moveXs(const string& str)
{
if (str.length() <= 1)
{
return str;
}
else if (str[0] == 'x')
{
return moveXs(str.substr(1, (str.length() - 1))) + str[0];
}
else
{
return str[0] + moveXs(str.substr(1, str.length()));
}
}
You can see it in action here: http://ideone.com/aT75l5
One simple approach could be just traverse the string from beginning to end counting and removing 'x'. Then append 'x' count number of times in previous string.

write trie parsing recursive function with node step over

The purpose: This function parses through a string trie following the path that matches an input string of characters. When all the char in the string are parsed, true is returned. I want to step over a char and return if there is still a valid path.
The application: the strings are a location hierarchy for a highway project. So, project 5 has an alignment C, that has an offset of N and a workzone 3; 5CN3. But, sometimes I want to define a string for all child locations for a project task that covers all the locations. So, '0' is all locations; for a half day operation like grade dirt has no workzones - all the so to represent this task is all workzones in the north alignment C; 5CN0. same for if an operation covers the whole project; 5000.
Approaches: I could have used a wildcard '?' function but I want to keep this specific step over for the purpose of abstracting the locations. Maybe '?' is the right approach, but seems to loose some control. Also, this could be written without the for loop and use a position index parameter; maybe that is where this goes wrong - maybe on backtracking.
Code: nodeT is the trie nodes, word is the input string, this function is a bool and returns 1/0 if the string path exists.
bool Lexicon::containsWordHelper(nodeT *w, string word)) //check if prefix can be combined
{
if(word == "") { //base case: all char found
return true;
} else {
for(int i = 0; i < w->alpha.size(); i++) { //Loop through all of the children of the current node
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1));
else if (word[0] == '0') //if '0' then step over and continue searching for valid path
containsWordHelper(w->alpha[i].next, word.substr(1)); //removed return here to allow looping through all the possible paths
} //I think it is continuing through after the loop and triggering return false
}
return false; //if char is missing - meaning the exact code is not there
}
The problem is that this returns false when a '0' wildcard is used. What is going wrong here? My knowledge is limited.
I hacked on this problem for awhile and used the 'howboutthis howboutthat' approach, and found that placing the return at the end of the step over statement works.
bool Lexicon::containsWordHelper(nodeT *w, string word, int &time, int &wag, string compare) //check if prefix can be combined
{
if(word == "") { //base case: all letters found
if ((w->begin-wag) <= time && time <= (w->end+wag))
return w->isWord; // case 2: timecard check for high/low date range
else if (time == ConvertDateToEpoch(9999, 01, 01)) return w->isWord; //this is for single code lookup w/o date
} else {
for(int i = 0; i < w->alpha.size(); i++) { //Loop through all of the children of the current node
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1), time, wag, compare);
else if (word[0] == 'ž')
if (containsWordHelper(w->alpha[i].next, word.substr(1), time, wag, compare)) return true;
}
}
return false; //if char is missing - meaning the exact code is not there
}
It seems logical that if I only one the path that ends in true to return then I should place the return after the recursion is done and then conditionally pass back only if true. It works and seems logical in retrospect, but my confidence in this is sketchy at best.
I still have the same question. What is/was going wrong?
You could test the result of the latter containsWordHelper call and return true if the result is true, else continue iterating.
Solved: place a return after an if statement containing the recursive call
bool Lexicon::containsWordHelper(nodeT *w, string word)
{
if(word == "") return w->isWord;
else {
for(int i = 0; i < w->alpha.size(); i++) {
if (w->alpha[i].letter == word[0])
return containsWordHelper(w->alpha[i].next, word.substr(1));
else if (word[0] == 'ž')
if (containsWordHelper(w->alpha[i].next, word.substr(1))) return true;
}
}
return false;
}