How to properly compare strings in c++? - c++

Good night to everyone!
I am trying to compare 2 strings in c++, using the .compare() function. However, the result i see is not what is expected from this function. Take a look please.
#include <iostream>
#include <string>
using namespace std;
class game
{
private:
char mtx [2][2];
int i = 0, j = 0, a = 0;
std::string matrix1;
std::string xis = "xx";
public:
game();
char winner();
};
game::game()
{
for(i = 0; i<2; i++)
{
for (j = 0; j<2; j++)
{
mtx [i][j] = 'x';
}
}
char game::winner()
{
i = j = 0;
for (j=0; j<2; j++)
{
matrix1 = mtx [0][j]; //string recieve the first line of the matrix.
}
a = xis.compare(matrix1);
cout << a<<endl;
}
int main(void) {
velha game;
velha.winner;
}
When I compile the program the a value printed is neither a '0' nor any other integers. It prints #85.
Notes: I've also tried to use <string.h> and strncmp() using a char array instead of std:: string but with no success.
I was trying to create a game class and I did not put here the other methods because they are not relevant). (also, I use Linux Mint to code)
Can anyone help me please in this context?

#include <iostream>
#include <string>
int main(void) {
std::string first, second;
std::cout << "First String: ";
getline(std::cin, first);
std::cout << "Second Line: ";
getline(std::cin, second);
if (first == second)
std::cout << "Same strings.";
else
std::cout << "Different strings.";
return 0;
}
Explanation: Just taken two strings from the user and matches straightforward without using any much complexity, just used a conditional operation.

For string compare and even strcmp the value returned will be the lexicographical comparison of the two strings. The following are the values you should see:
negative if *this appears before the character sequence specified by the argument in lexicographical order
0 if *this and the character sequence specified are equivalent
positive if *this appears after the character sequence specified by the argument in lexicographical order
If you are looking to get the first column of your matrix, do a string comparison on, you would want to do something like:
for(int col = 0; col < 2; col++) {
matrix1.push_back(mtx[0][col]); // This appends that character to the end of your string
}
If you are looking to get the rows you can just do the following:
matrix1 = mtx[0];
// To ensure you have a null terminated string
// Otherwise you will have garbage.
matrix1.replace(matrix1.begin() + 2, matrix1.end(), 1, "\0");
I have ran through the test with comparing that the matrix contains "xx" and ended up receiving 0. However a much easier comparison is to us operator == to simply return a true or false value.

Related

How do you insert characters into middle of string? C++

The purpose of this code is to insert an x in between repeating letters. For example, if I were to input "CoolBoolFallmoose", the output would be "CoxolBoxolFalxlmoxose".
The code is also supposed to make an even number of pairs of letters, so if there is an odd amount of characters, an x is added to the end of the string. An example for this would be if we had "ball", it would become "balxlx" to make even pairs: "ba" "lx" "lx".
This is the code I have so far:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main(){
string cipher, plain, paired = "";
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
for (int i=0;i<plain.length();i++){
if (plain[i]==plain[i+1]){
plain.insert(i,'x');
}
paired[i]=paired[i];
cout<<paired[i];
}
if (paired.length() % 2!= 0){
paired=+'x';
}
cout<<paired<<endl;
return 0;
}
The output I get is just the same as my input, no "x" added in any place.
The issue I am having is, every time I try to use the append() or insert() function for strings, I get an error from my compiler, which is xCode. Is there another way to solve this code?
EDIT: The error says:
No matching member function to call for insert
It also comes up for append().
I don't really know what you wanted to do with this part:
paired[i]=paired[i];
cout<<paired[i];
but otherwise the logic is good. Here is my take on it, x is a counter:
#include <iostream>
#include <string>
using namespace std;
int main(){
string m,n;
int x = 0;
cout << "Input: " << endl;
getline(cin, m);
for(int i = 0;i < m.length();i++){
x++;
n = n + m[i];
if(m[i] == m[i+1]){
n = n + 'x';
x++;
}
}
if((x % 2) != 0){
n = n + 'x';
}
cout << n;
return 0;
}
If you look at the available overloads of std::string::insert(), you will see that your statement plain.insert(i,'x'); does not match any of them, hence the compiler error. The overloads that takes a single char require either:
an index and a count (you are omitting the count)
an iterator and an optional count
There is, however, a couple of overloads that take just an index and a value, but they require a const char* or a std::string, not a single char.
Also, paired[i]=paired[i]; is a no-op. Except in your case, since paired has a size() of 0 since you never append anything to paired, so actually any access to paired[...] is undefined behavior.
Try this instead:
#include <iostream>
#include <string>
using namespace std;
int main(){
string plain, paired;
cout << "input plaintext(no spaces, lowercase):\n";
cin >> plain;
paired = plain;
for (string::size_type i = 1; i < paired.size(); ++i){
if (paired[i] == paired[i-1]){
paired.insert(i, 1, 'x');
// or: paired.insert(paired.begin()+i, 'x');
// or: paired.insert(i, "x");
// or: paired.insert(i, string{'x'});
// or: paired.insert(paired.begin()+i, {'x'});
++i; // skip the x just inserted
}
}
if (paired.size() % 2 != 0){
paired += 'x';
}
cout << paired << endl;
return 0;
}
Demo
A couple of points
First, Although the string.insert function says it takes an int as its first argument it really wants an iterator in this case.
Second, you are inserting elements into your "plain" string which increases its length and you have plain.length within your loop so you create an infinite loop.
Third, insert inserts BEFORE the index so you need to add 1 to I.
The code below will work for your loop:
Int len = plain.length();
Int count = 0;
for (int i = 0; i < len + count; i++)
{
If (plain[i] == plain[i + 1])
{
plain.insert(plain.begin() + (i +1), 'X');
++count;
}
}
cout << plain;
And as, mentioned below, if you want to handle spaces you can use getline(cin, plain) instead of cin.

Creating strings by splitting a char array

As part of my homework assignment, I have to split a char[] by its indices. So for example, the main function looks like:
int main()
{
char str[] = "A string to be split into given number of parts";
int split_size;
cout << "Enter the size of the part: ";
cin >> split_size;
int size = sizeof(str) / sizeof(str[0]);
SplitString(str, split_size, size);
int wait;
cin >> wait;
return 0;
}
Then using the function SplitString, the first x elements are printed, new line, then the next.
My first idea, was to use two for loops. One loops through the splits (i.e. if there are 4 splits, the range on this loop is 0 to 3), then the second loops through the split itself, iterating over the array elements.
My SplitString() function looks like this:
void SplitString(char str[], int split_size, int size) {
int parts = size / split_size;
for (int i = 0; i < parts; i++) {
for (int j = 0; j < split_size; j++) {
j = split_size * i;
cout << str[j];
}
cout << endl;
}
}
Is there an easier way to do this? I know in Python, you can use the arr[1:] to grab a range of elements from the array. Is there anything similar in C++? Is there some flaw in my logic? Is there something wrong with my code?
cout comes with a write function that takes a pointer and a size argument.
for (int i = 0; i < parts; i++) {
cout.write (str+i*split_size, split_size)
cout << endl;
}
Note that the code above does not check if the string is actually long enough. If the total size is not equal the split_size times a whole number, you will have to add an additional check.
Also, note that this:
int size = sizeof(str) / sizeof(str[0]);
can be written as:
int size = sizeof(str);
instead because the size of a char is always 1.
You can use std::string for this. Alternatively, if your compiler supports C++17, you can use std::string_view as the first argument of SplitString to avoid unnecessary copying.
#include <algorithm>
#include <iostream>
#include <string>
void SplitString(std::string s, std::size_t split_size)
{
while(!s.empty())
{
auto size = std::min(split_size, s.size());
std::cout << s.substr(0, size) << '\n';
s = s.substr(size, std::string::npos);
}
}
int main()
{
char str[] = "A string to be split into given number of parts";
int split_size = 5;
SplitString(str, split_size);
return 0;
}
Live example.

I'm having trouble with my conversion program

For my class, I am to write a program in C++ that converts each character in a sentence to the opposite case (upper to lower, lower to upper). We are supposed to use arrays and a user-defined method, and this is what I came up with:
#include <iostream>
using namespace std;
// declare variables
int count = 0; // array counter
int i = 0; // loop control
char ch[100]; // each character entered will be stored in this array
char newCh[100]; // this will hold each character after its case has been changed
main()
{
cout << "Enter a sentence." << endl; // prompts user
while ( ch[count] != '\n' ) // loop continues until "enter" is pressed
{
cin >> ch[count]; // store each character in an array
count += 1; // increment counter
}
int convert(); // call user-defined function
}
// even though it isn't necessary, we are using a user-defined function to perform the conversion
int convert()
{
for ( i = 0; i >= 0; i++ )
{
if ( (ch[i] > 64) and (ch[i] < 91)
)
{
newCh[i] = tolower(ch[i]);
}
else
{
newCh[i] = toupper(ch[i]);
}
cout << newCh[i];
}
}
I'm not sure why, but it doesn't work. I don't believe that my while loop is terminating and executing the rest of the program. Any advice would be greatly appreciated.
The loop condition in while ( ch[count] != '\n' ) is wrong, as all entries in ch will be initialized to zero by the compiler, and as you increase count inside the loop the condition will never be false and you have an infinite loop, causing you to write beyond the limits of the array.
And writing beyond the limits of an array leads to undefined behavior, and will cause your whole program to be illegal.
I suggest you learn about std::string and std::getline.
There's a problem with your for loop - you want for ( i = 0; i < count; i++ ). Also your function can be void and you need to pass the count value into it (and you just need to invoke it with convert() without int or void in front.
I have rewrite your code with some modification. The following code works perfectly in my machine -
#include <iostream>
#include<cstdio>
#include<string>
using namespace std;
void convert(char *, int);
string line;
char input[1024];
char output[1024];
main()
{
cout << "Enter a sentence." << endl;
while (getline(cin, line)) { // POINT 1
cout<< line<<endl;
//converting to char array since you need char array
//POINT 2
for(int i=0; i< line.length(); i++){
input[i]=line[i];
}
convert(input, line.length());
cout<<output<<endl;
input[1024] = {0}; //POINT 3
output[1024] = {0};
}
}
//Custom Convert Method
void convert(char input[], int size){
for(int i = 0; i < size; i++){
if(input[i] >= 'a' && input[i] <= 'z'){
output[i] = toupper(input[i]);
} else {
output[i] = tolower(input[i]);
}
}
}
Note some points (in my comment) here -
POINT 1: reading a n entire line using getline() method. Here line is a string
POINT 2: since you need char array here I am converting the string line to char array input[1024]
POINT 3: input and output array are being reset to work with the next value;
Output of the code:
"Ctrl+C" will terminate the program
Hope it will help you.
Thanks a lot.

How to parse a user's input and store each individual character as a string

Okay so I'm working a calculator program that takes in a user input(ex. "(3+(4+12))"), and I need to parse the user's input and store it in an array of strings but I am having trouble doing so. My code currently is this
void parseInput(string input) {
vector <string> input_vector;
for(int i = 0; i < input.size(); ++i) {
if(isdigit(input.at(i)) == 0 && isdigit(input.at(i + 1)) == 0) {
++i;
input_vector.push_back((input.at(i) + input.at(i+1)));
}
else {
input_vector.push_back(input.at(i));
}
}
for(int i = 0; i < input_vector.size(); ++i) {
cout << endl << input_vector[i];
}
}
I know my problem is coming from trying to add a char to an vector of strings, but how would I get each char in the string and keep it as a string to store into my vector. Or is there a better way to parse this out??
edit
Okay so what I am having the most trouble with is the problems that come from the 12 splitting up into two separate chars "1 * 2" How would I go about so that it represents 12 and doesn't split it up???
Here is a solution (using c++11):
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
int main() {
std::string const input = "(3+(4+12))";
std::vector<std::string> chars(input.length());
// Maps each character of `input` to `std::string`
// with that character and saves the results in
// corresponding position in `chars` vector:
std::transform(input.cbegin(), input.cend(), chars.begin(),
[](char c) {
// One of the ways to cast `char` to `std::string`:
return std::string(1, c);
});
// To be sure it works properly, it prints
// generated strings:
for (size_t i = 0; i < chars.size(); ++i) {
std::cout << chars[i];
}
std::cout << std::endl;
}
The answer is u need to split the string into tokens, i have given an example which will add 4 to 12, to make it 16, but think that the string does'nt have any brackets, suppose if the user entered 4+12 and u need to add it you can do the following:
char string[10], nstr[10];
int p=0, a=0, b=0, op=0;
cin>>string; // input string
While (string[i]!='+' || string[i]!='-')
{
nstr[p]=string[i]; // copy the contents of string to nstr.
p++;
i++;
}// loop exits if the string[i] reaches to the operator (+/-*).
nstr[p]='\0';
a=atoi(nstr);// convert the string to integer.
op=i;// this will hold the position of array of the operator in the string.
i++;
p=0;
while (string[i]!='\0')
{
nstr[p]=string[i];// this will copy the contents of the string after the operator.
i++;
p++;
}
nstr[p]='\0';
b=atoi(nstr);
if (string[op]=='+')// check what the user want to do. Add/subtract/divide etc.
c=a+b;
else if (string[op]=='-')
c=a-b;
This program is not tested but will work, if not then use the logic in your program, like i did in my program, this will not take 1 and 2 sepratly, instead it will take 4 and 12, you can type more charaters but is limited to long, i used int here to get the return value of atoi(), hope this helps u...

finding if one string ("AB") is subset of another ("ABCD")?

i had my midterm today. this was the first question. i could not solve this.
the exact requirement is as follows :
we have to determine if a string , lets say , "DA" is subset of another, "ABCD". the number of letters is crucial, for exmaple "DAD" is not a subset of "ABCD". because "D" is repeated twice whereas in the parent string "D" occurs once. also it can be assumed that that no. of letters of parent string is always equal to or greater than the other.
i thought a lot about this. my approach towards this was that i will compare the characters of the to-be-found substring with the parent string. if a match is found i will store its index in a third array. so in the end i will have the arrays of characters of the parent array which matched characters from the other array.this is how far i have been able to get.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char array[] = "ABCD";
char array1[] = "AB";
int size = strlen(array);
int size1 = strlen(array1);
int temp[size];
int no = 0;
for (int i = 0; i< size1; i++)
{
for (int j = 0; j< size; j++)
{
if (array1[i]==array[j])
{
for(int k = 0; k<size ; k++)
{
if (temp[k] != j)
{
temp[no] = j;
no++;
}
}
}
}
}
for (int i = 0; i<size; i++)
cout<<endl<<temp[i]<<" ";
return 0;
}
kindly help in solving this and do tel me if you have another approach to this.
also, are arrays or a string a better approach to this problem.
i am writing in c++
thanks in advance
(I recently used this as a quiz for my students but we're using Groovy and Java.)
A simple aproach: create a copy of the string ("ABCD") and strike matched letters so that they won't match again, for example after matching a "D" and "A", the copy would be "_BC_" and it would not match another "D".
You can also count the number of occurrences of each letter in each string and make sure the count of each letter in the second string is less than or equal to the count of each letter in the first string. This might be better in the case where you want to compare multiple potential substrings to a single collection of letters (e.g. comparing all the words in the dictionary to the current letters in Boggle).
This code will do that. It has the primary limitation that it only works with strings containing the 26 capital letters in the English alphabet. But it gets the idea across.
#include <iostream>
#include <cstring>
using namespace std;
void stringToArray(char *theString, int *countArray) {
int stringLength = strlen(theString);
for (int i=0; i<26; i++) {
countArray[i] = 0;
}
for (int i=0; i<stringLength; i++) {
countArray[theString[i] - 'A']++;
}
}
bool arrayIsSubset(int *superCount, int *subCount) {
//returns true if subCount is a subset of superCount
bool isSubset = true;
for (int i=0; i<26 && isSubset; i++) {
isSubset = subCount[i] <= superCount[i];
}
return isSubset;
}
int main()
{
char array[] = "ABCD";
char array1[] = "AB";
char array2[] = "ABB";
int letterCount[26], letterCount1[26], letterCount2[26];
stringToArray(array, letterCount);
stringToArray(array1, letterCount1);
stringToArray(array2, letterCount2);
cout << "array1 is " << (arrayIsSubset(letterCount, letterCount1) ? "" : "not ") << "a subset" << endl;
cout << "array2 is " << (arrayIsSubset(letterCount, letterCount2) ? "" : "not ") << "a subset" << endl;
}
produces:
array1 is a subset
array2 is not a subset