Simple Word Guessing Game - c++

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

Related

check if one string is interleaved by two other strings

I am debugging the following problem. Post detailed problem statement and the coding. My question is whether the last else if (else if (A[i-1]==C[i+j-1] && B[j-1]==C[i+j-1])) is necessary? I think it is not necessary since it is always covered either by else if(A[i-1]==C[i+j-1] && B[j-1]!=C[i+j-1]), or covered by else if (A[i-1]!=C[i+j-1] && B[j-1]==C[i+j-1]), i.e. previous two if-else check conditions. Thanks.
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
// The main function that returns true if C is
// an interleaving of A and B, otherwise false.
bool isInterleaved(char* A, char* B, char* C)
{
// Find lengths of the two strings
int M = strlen(A), N = strlen(B);
// Let us create a 2D table to store solutions of
// subproblems. C[i][j] will be true if C[0..i+j-1]
// is an interleaving of A[0..i-1] and B[0..j-1].
bool IL[M+1][N+1];
memset(IL, 0, sizeof(IL)); // Initialize all values as false.
// C can be an interleaving of A and B only of sum
// of lengths of A & B is equal to length of C.
if ((M+N) != strlen(C))
return false;
// Process all characters of A and B
for (int i=0; i<=M; ++i)
{
for (int j=0; j<=N; ++j)
{
// two empty strings have an empty string
// as interleaving
if (i==0 && j==0)
IL[i][j] = true;
// A is empty
else if (i==0 && B[j-1]==C[j-1])
IL[i][j] = IL[i][j-1];
// B is empty
else if (j==0 && A[i-1]==C[i-1])
IL[i][j] = IL[i-1][j];
// Current character of C matches with current character of A,
// but doesn't match with current character of B
else if(A[i-1]==C[i+j-1] && B[j-1]!=C[i+j-1])
IL[i][j] = IL[i-1][j];
// Current character of C matches with current character of B,
// but doesn't match with current character of A
else if (A[i-1]!=C[i+j-1] && B[j-1]==C[i+j-1])
IL[i][j] = IL[i][j-1];
// Current character of C matches with that of both A and B
else if (A[i-1]==C[i+j-1] && B[j-1]==C[i+j-1])
IL[i][j]=(IL[i-1][j] || IL[i][j-1]) ;
}
}
return IL[M][N];
}
thanks in advance,
Lin
You do need the final else if to catch the cases when the next character in C matches the next character in both A and B. For example, run your program with A="aaaa", B="aaaa", and C="aaaaaaaa" and see if you enter that last else if block.
Additionally, you also need a final else block to handle cases when none of the previous conditions match. In this case, you need to set IL[i][j] to false. Otherwise, the function will incorrectly return true.
Edit: Even though the code uses memset to initialize all elements of IL to 0, it may not work because ISO C++ does not support variable length arrays (VLAs). In fact, this is what happened when I tried the code at cpp.sh. It uses g++-4.9.2 with flags that causes it to report sizeof(IL) to be 1 even though g++ is supposed to support VLAs. Maybe this is a compiler bug or maybe it does not support multidimensional VLAs. In any case, it might be safer to not use them at all.

Efficiency & Readabilty of a C++ For Loop that Compares two C-style Strings

So I've created my own function to compare two C Strings:
bool list::compareString(const char array1[], const char array2[])
{
unsigned char count;
for (count = 0; array1[count] != '\0' && array2[count] != '\0' && (array1[count] == array2[count] || array1[count + 32] == array2[count] || array1[count] == array2[count+32]); count++);
if (array1[count] == '\0' && array2[count] == '\0')
return true;
else
return false;
}
The parameter of my for loop is very long because it brings count to the end of at least one of the strings, and compares each char in each array in such a way that it their case won't matter (adding 32 to an uppercase char turns that char into its lowercase counterpart).
Now, I'm guessing that this is the most efficient way to go about comparing two C Strings, but that for loop is hard to read because of its length. What I've been told is to use a for loop instead of a while loop whenever possible because a for loop has the starting, ending, and incrementing conditions in its starting parameter, but for this, that seems like it may not apply.
What I'm asking is, how should I format this loop, and is there a more efficient way to do it?
Instead of indexing into the arrays with count, which you don't know the size of, you can instead operate directly on the pointers:
bool list::compareString(const char* array1, const char* array2)
{
while (*array1 != '\0' || *array2 != '\0')
if (*array1++ != *array2++) return false; // not the same character
return true;
}
For case insensitive comparison, replace the if condition with:
if (tolower(*array1++) != tolower(*array2++)) return false;
This does a safe character conversion to lower case.
The while loop checks if the strings are terminated. It continues while one of the strings is not yet terminated. If only 1 string has terminated, the next line - the if statement, will realize that the characters don't match (since only 1 character is '\0', and returns false.
If the strings differ at any point, the if statement returns false.
The if statement also post-increments the pointers so that it tests the next character in the next iteration of the while loop.
If both strings are equal, and terminate at the same time, at some point, the while condition will become false. In this case, the return true statement will execute.
If you want to write the tolower function yourself, you need to check that the character is a capital letter, and not a different type of character (eg. a number of symbol).
This would be:
inline char tolower(char ch)
{
return (ch >= 'A' && ch <= 'Z' ? (ch + 'a' - 'A') : ch);
}
I guess you are trying to do a case-insensitive comparison here. If you just need the fastest version, use a library function: strcasecmp or stricmp or strcmpi (name depends on your platform).
If you need to understand how to do it (I mean, is your question for learning purpose?), start with a readable version, something like this:
for (index = 0; ; ++index)
{
if (array1[index] == '\0' && array2[index] == '\0')
return true; // end of string reached
if (tolower(array1[index]) != tolower(array2[index]))
return false; // different characters discovered
}
Then measure its performance. If it's good enough, done. If not, investigate why (by looking at the machine code generated by the compiler). The first step in optimization might be replacing the tolower library function by a hand-crafted piece of code (which disregards non-English characters - is it what you want to do?):
int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
}
Note that I am still keeping the code readable. Readable code can be fast, because the compiler is going to optimize it.
array1[count + 32] == array2[count]
can lead to an OutOfRangeException, if the length of the array is smaller than 32.
You can use strcmp for comparing two strings
You have a few problems with your code.
What I'd do here is move some of your logic into the body of the for loop. Cramming everything into the for loop expression massively reduces readability without giving you any performance boosts that I can think of. The code just ends up being messy. Keep the conditions of the loop to testing incrementation and put the actual task in the body.
I'd also point out that you're not adding 32 to the character at all. You're adding it to the index of the array putting you at risk of running out of bounds. You need to test the value at the index, not the index itself.
Using an unsigned char to index an array gives you no benefits and only serves to reduce the maximum length of the strings that you can compare. Use an int.
You could restructure the code so that it looks like this:
bool list::compareString(const char array1[], const char array2[])
{
// Iterate over the strings until we find the string termination character
for (int count = 0; array1[count] != '\0' && array2[count] != '\0'; count++) {
// Note 0x20 is hexadecimal 32. We're comparing two letters for
// equality in a case insensitive way.
if ( (array1[count] | 0x20) != (array2[count] | 0x20) ) {
// Return false if the letters aren't equal
return false;
}
}
// We made it to the end of the loop. Strings are equal.
return true;
}
As for efficiency, it looks to me like you were trying to reduce:
The size of the variables that you're using to store data in
memory
The number of individual lines of code in your solution
Neither of these are worth your time. Efficiency is about how many steps (not lines of code, mind you) it will take to perform a task and how those steps scale as the inputs get bigger. For instance, how much slower would it be to compare the content of two novels for equality than two single word strings?
I hope that helps :)

Boolean function does not work properly

I have trouble to come up with a Boolean function as expected by the assignment. I just need some explanations as I want to write my own code. I am supposed to write a MIPS code that actually counts the number of Uppercase, Lowercase, Vowels, Consonants and Digits in a string. I am writing the code in C++, then I will translate into MIPS assembly. I pasted the requirement below followed by the way the function bool consonant(char c) should look like (idea given by my professor). The problem is that it seems I am missing some information to make that function work. Can anyone provide me more information regarding that function? I don't need a code, just the missing details. Your help will be very appreciated.
//requirement of assignment bellow
To determine if an ASCII character c is a vowel or a consonant, write two functions bool vowel(char c) and
bool consonant(char c). Use the stack to pass the character argument to these functions. Avoid long conditional
expressions when testing a character for being a vowel and a consonant. Instead, use two global arrays
(tables) containing Boolean flags to implement vowel() and consonant(). For example, an array named
is_vowel would have true for characters ’a’ and ’A’ but false for ’b’ and ’B’.
// function that returns 0 if c is a consonant, or 1 if c is not a consonant
bool consonant(char c)
{
const bool is_conson[30]={0,0,...1,1,1,0,0...};
return is_conson[c];
}
//Here is The Code (C++) that I wrote for testing purpose only using Dev-C++
#include <iostream>
#include <math.h>
#include <cstdlib>
using namespace std;
bool consonant(char c)
{
const bool is_conso[30]= {1,1,1,1,0,0,0,0,0,1,0,1,1,0,0,0,1,0,1,0,1,1,1,1,0,1,0,1,0,1};
return is_conso[c];
}
int main()
{
int i;
bool result;
char c;
char sentence[]="aaaabbbbb";
cout<<"the array: ";
cout<<sentence<<endl;
for (i=0; i<9; i++)
{
c=sentence[i];
result=consonant(c);
if (result==0)
cout<<c<<" is a Consonant"<<endl;
}
return 0;
}
If you want to call bool consonant(char c) like consonant('a'), then you need to translate c into an index first (because 'a' != 0) or use another approach.
In portable C++, you could do it with a big switch:
switch(c) {
case 'b': case'B': case 'c': case 'C': .... return true;
default: return false;
}
In non-portable C++, you could offset c:
c = lower_case(c); // <-- left as exercise
const auto array_size = std::end(is_conson) - std::begin(is_conson);
if (c>=0 && c<array_size)
return is_conson[c - 'a']
throw std::logic_error(...);
This is non-portable because the C++ standard does not require the characters [a..z] to be contiguous. I don't know if your compiler at hands does support this.
A third, non-portable variant requires separate some special initialization, but allows direct indexing:
std::array<bool,std::numeric_limits<char>::max()> meh() {
std::array<bool,std::numeric_limits<char>::max()> ret;
ret['a'] = true;
ret['A'] = true;
...
return ret;
}
....
static const auto is_conson = meh();
if (c >= begin(is_conson) && c<= end(is_conson))
return is_conson[c];
throw std::logic_error(....);
Non-portable, because it assumes that all consonants are positive. It is, however, more portable than the previous variant. You could make it portable by also introducing std::numeric_limits<char>::min().
As it stands your function won't work because ASCII A is 65, you'll need to increase your array to cover all ASCII characters or subtract 'A' (which gives the ASCII value of A) to scale the number to your array. ASCII a is 97, so lowercase letters would have to be scaled by subtracting 'a'
Letters are represented by values 65 through 90 (uppercase) and 97 through 122 (lowercase) in ASCII. You're using the array as if they were starting at index 0. Do something like this:
if (c >= 'A' && c <= 'Z')
return is_conson[c-'A'];
if (c >= 'a' && c <= 'z')
return is_conson[c-'a'];
return false;
Also, you should declare the is_conson array as static, so that it's only constructed once and not each time the function is called.

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

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

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.