isPalindromic Function [duplicate] - c++

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 5 years ago.
I wrote this function isPalindromic for my compsci class where the professor wants us to better understand how library functions work. So he asked us to write a function isPalindromic and mine isn't working as well. Because there are so many parts, I will paste the whole function, so bear with me. Sorry!
The function always returns false for some reason. The word passed is "HELLO ". My first loop checks for the size of the word without spaces or null characters so I can use it as a parameter in my second loop. This returns false, which is correct, but when I pass "HELLEH " or "HELLEH", they both return false. I've rewritten this at least 5 times, and I can't figure out why it's returning false.
char* isPalindromic(char inputCheck[]){
int actWord;
int sizeCheck = myStrLen(inputCheck);
char tempWord[actWord];
for(int check = 0; check < sizeCheck; check++){
if(inputCheck[check] = ' ' || inputCheck[check] == '\0')
actWord = check;
}
for(int replace = 0; replace < actWord; replace++){
tempWord[replace] = inputCheck[actWord - replace];
}
tempWord == inputCheck ? inputCheck = "True" : inputCheck = "False";
return inputCheck;
}

char tempWord[actWord];
actWord at this point is uninitialised. Your entire program therefore has undefined behaviour.
tempWord == inputCheck ? inputCheck = "True" : inputCheck = "False";
This is also a problem; you cannot compare two character arrays with == like this; you're just comparing their locations in memory. You'll have to use reimplement strcmp for that (although, actually, a much simpler version of your algorithm will not require such logic).
You don't need any of this extra buffer space. All you need to do is iterate from front and back simultaneously, comparing characters.
const char* isPalindromic(const char inputCheck[])
{
const int size = myStrLen(inputCheck);
for (size_t i1 = 0, i2 = size-1; i1 < i2; i1++, i2--)
if (inputCheck[i1] != inputCheck[i2])
return "False";
return "True";
}
(live demo)
Also I would strongly consider returning a bool, not "True" or "False".

Related

Exception thrown (Stackoverflow-vs error) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
Given a paragraph as a character array, write a c++ program to remove a sub string from
that paragraph. Your function should return the original array after removing the input
array.
Why my code gives "stack overflow" error at this line Para[j] = Para[j + lenInput]; when I tried to run against given test cases?
Source code
//suppose all libraries included .as we are dealing with google tests,no main function required
char* removeSentence(char* Para, char* input) {
int lenPara = strlen(Para);
int lenInput = strlen(input);
int i = 0;
while (i <= lenPara - lenInput) {
if (strncmp(&Para[i], input, lenInput) == 0 && (i == 0 || Para[i - 1] == ' ') && (Para[i + lenInput] == ' ' || Para[i + lenInput] == '.')) {
for (int j = i; j < lenPara - lenInput; j++) {
// int temp=j+lenInput;
Para[j] = Para[j + lenInput]; //This line gives error-exception overthrown
}
lenPara -= lenInput;
i -= lenInput;
}
i++;
}
return Para;
}
Google test
TEST(RemoveSentence, Test1)
{
char* Para = "Helpdesk: There is an icon on your computer labeled My Computer. Double click on it. User: What's your computer doing on mine?";
char* input = "Double click on it.";
char* output = "Helpdesk: There is an icon on your computer labeled My Computer. User: What's your computer doing on mine?";
ASSERT_EQ(0, strcmp(output, removeSentence(Para, input)));
}
TEST(RemoveSentence, Test2)
{
char* Para = "A son asked his father (a programmer) why the sun rises in the east, and sets in the west. His response? It works, don’t touch!";
char* input = "(a programmer)";
char* output = "A son asked his father why the sun rises in the east, and sets in the west. His response? It works, don’t touch!";
ASSERT_EQ(0, strcmp(output, removeSentence(Para, input)));
}
My logic:
The removeSentence function takes two arguments, Para and input, both of which are character arrays. It uses a while loop to iterate over each character of the Para array, comparing each substring of length lenInput with input using the strncmp function. If the substring matches input and the characters immediately before and after the substring are either spaces or periods, the function removes the substring from the Para array by shifting all subsequent characters back by lenInput.
Note that the function modifies the Para array in place and returns a pointer to it, rather than creating and returning a new array. Also note that the function assumes that the input string occurs at most once in the Para string. If it occurs multiple times, the function will only remove the first occurrence.
Test string literals should be marked const as it is not modifiable, so modifying in-place is likely to cause corruption.
I have modified the function to void removeSentence(char *para, char const* input), which omits the return, and passing test strings as
char *para1 = new char[]{"Helpdesk (...skipped...)?"};
etc., and found out removeSentence doesn't produce any error. I assume the error you mentioned must be triggered by the reason above.
Related to code:
i -= lenInput is needless as i is not modified, doing so only causing the program to strncmp the part done before.
i++ causes the subsequence input to be ignored if (i == 0 || ... == '.') check is omiited and i -= lenInput is removed; you may want to move this to else of strncmp.

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;
}
}

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.

When is the condition of this for loop will becomes false?

I'm working on my C++ practice question to prepare for my upcoming test and I'm struggling with a for loop condition that I have never seen before.
for (int i = 0; s[i]; i++)
The string s that has been sent from the main is "Two roofs to fix"
The question is when is the for loop's condition will become false?
The loop condition becomes false, when the string's terminating zero '\0' is hit. (if (0) evaluates to false)
Please note: this form of test is a possible error waiting to happen if the string isn't null terminated.
Just to clarify #MitchWheat's answer, if an expression used as a condition specifies only a value, like if (x), then it's essentially equivalent to if (x != 0). If the value is a pointer type, then it's equivalent to if (x != NULL) instead (though that's not really an "instead", since NULL == 0).
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s = "Two roofs to fix";
int i;
for (i = 0; s[i]; i++);
cout<<"i = "<<i<<endl;
}
I test the problem with the above code. It returns an error "string subscript out of range". So if the length of string s is Len, s[Len] is illegal.
In your code, s is not a pointer char*, but a string. So it is unappropriate to code like this.

input string validation without external libraries for c++

I need to validate one input string from a user. Eventually it will need to break down into two coordinates. ie a4 c3. And once they are coordinates they need to be broken out into 4 separate ints. a=0 b=1, etc. They must also follow the following stipulations:
If an end-of-input signal is reached the program quits.
Otherwise, all non-alphanumeric characters are discarded from the input.
If what remains is the single letter 'Q'
Then the program quits.
If what remains consists of 4 characters, with one letter and one digit among the first two characters and one letter and one digit among the last two characters, and if each letter-digit pair is in the legal range for our grid
Then input is acceptable.
I have completely over-thought and ruined my function. Please let me know where I can make some corrections.
I am mainly having trouble going from one string, to four chars if and only if the data is valid. Everything else I can handle.
Here is what I have so far.
void Grid::playerMove()
{
string rawMove;
string pair1 = " ";
string pair2 = " ";
bool goodInput = false;
char maxChar = 'a';
char chary1, chary2;
int x11,x22,y11,y22;
for (int i =0; i<size; i++)
{
maxChar++;
}
while(!goodInput)
{
cout<<"What two dots would you like to connect? (Q to quit) ";
cin>>rawMove;
rawMove = reduceWords(rawMove);
if (rawMove == "Q")
{
cout<<"end game";
goodInput = false;
}
else if (rawMove.size() == 4)
{
for(int j=0;j<2;j++)
{
if (pair1[j] >='a' && pair1[j] <=maxChar)
{
chary1 = pair1[j];
}
else if(pair1[j] >=0 && pairl[j]<=size+1)
{
x1 = pair1[j];
}
}
for(int k=0;k<2;k++)
{
if (pair2[k] >='a' && pair2[k] <=maxChar)
{
chary2 = pair2[k];
}
else if(pair2[k] >=0 && pair2[k]<=size+1)
{
x2 = pair2[k];
}
}
}
if(char1 != NULL && char2 != NULL && x1 !=NULL && x2 != NULL)
{
for (int m = 0; m <= size m++)
{
if (char1 == m;)
{
x1 = m;
}
}
for (int n = 0; n <= size n++)
{
if (char2 == n)
{
x2 = n;
}
}
}
}
The end goal would be to have x1, x2, y1, and y2 with their respective values.
Keep in mind I am not allowed to have any external libraries.
It's not clear what exactly you want to achieve, but here are some pointers to get you started:
The while loop will never end because you're setting goodInput to false on quit which lets the loop continue.
The code probably does not even compile? You are missing a curly closing brace..
You are initializing pair1 and pair2 to empty strings but never change them again, so they will never contain any real information about your moves
maybe what you really want is to split up rawMove into the pair1 and pair2 substrings first?
Since this is a homework - and you're supposed to learn from those (right?) - I'm not going to give you the complete answer, but rather something like a recipe:
Use std::istream::getline(char*, std::streamsize s) to read a whole line from std::cin. Make sure you allocate a buffer large enough to hold the expected input (including the terminating null character) plus some more for invalid characters. After the call, check the failbit (input was too long) and the eofbit (hit the end-of-input) of the std::cin stream and handle those cases. Construct a std::string from the buffer if there was no error or EOF has not been reached.
Write a character-classification function (e.g. call it isAlNum(char c)) that returns true if the char argument is alpha-numeric, and false otherwise.
Combine std::string::erase(), std::remove_if(), std::not1(), std::ptr_fun() and your function isAlNum() to sanitise the input string.
Write a function that validates and parses the coordinates from the sanitised input string and call it with the sanitised input string.
Wrap the whole thing in an appropriate while() loop.
This should get you started in the right direction. Of course, if you're allowed to use C++11 features and you know how to write good regular expressions, by all means, use the <regex> header instead of doing the parsing manually.