find substring in a string with loops in c++ - c++

The code will get two string from user and checks the string , includes substring as the second input or not.
string st1;
string subst1;
string message = " ";
cout << "Enter string and subst:";
cin >> st1;
cin >> subst1;
for (int a=0; a < st1.length(); a++) {
if (st1[a] == subst1[0]) {
for (int k = 0; k < subst1.length(); k++) {
if (st1[a + k] == subst1[k])
message = "True";
else
message = "False";
}
}
}
cout << message;
This code does not work inputs like "alice" and "ba". The output should be false but when I execute the code program directly ended

Because in some cases a + k exceeds the length of the string st1:
if (st1[a + k] == subst1[k]) {
message = "True";
}
before executing this statement, verify if a + k < st1.length()
but another remark:
when message becomes False you must stop comparison else the variable message might be again True.

Why not use find():
string st1, subst1, message=" ";
cout<<"Enter string and subst:";
cin>>st1>>subst1;
if (st1.find(subst)==string::npos)
message="Not found";
else message ="Found";
If you're not allowed to use this approach, then I propose you the following:
string st1, subst1, message=" ";
bool found=false;
cout<<"Enter string and subst:";
cin>>st1 >>subst1;
for (int a=0; !found && a<st1.length();a++) {
if (st1[a]==subst1[0]) {
found = true; // there's some hope
for (int k=0; found && k<subst1.length(); k++) {
if (a+k>=st1.length() || st1[a+k]!=subst1[k]) // oops! might overflow or fail
found = false; // this will also end the inner loop
}
}
}
message = found ? "True":"False";
cout<< message<<endl;
The principle is that for a compare to be successfull, all chars must be equal. But if a single char fails, you shall stop the failed comparison.
Here a live demo

Related

What is wrong with my program to find the longest word in a sentence?

#include <iostream>
using namespace std;
int main() {
char a[101]{0};
cin>>a;
cin.getline(a,101);
cin.ignore();
int currLen{0};
int maxLen{0};
int startInd{-1};
int endInd{-1};
for(int i=0; i<101; i++) {
if(a[i]!=' ' ) {
++currLen;
} else if(a[i]==' '||a[i]=='\0') {
if(currLen>maxLen) {
maxLen=currLen;
startInd=i-currLen;
endInd=i-1;
}
if(a[i]=='\0')
break;
currLen=0;
}
}
cout<<maxLen<<endl;
if(startInd==-1)
cout<<-1;
else
for(int i=startInd; i<=endInd; i++)
cout<<a[i];
return 0;
}
If I take an input here, for example, "My name is Manav Kampani"
It will output 5
Manav instead of 7
Kampani
But if I write "My name is Manav Kampani ", with space after the last word
than it is considering Kampani too printing Kampani.
Also when I input "Kampani Manav is my name" then too it's displaying the wrong output. That means it is not considering the first word of the sentence.
if(a[i]!=' ' )
{
++currLen;
}
else if(a[i]==' '||a[i]=='\0')
{
....
}
Consider the case of a[i] == 0. Which of these if-statements will apply.
Answer: the first one. Which means you'll never look at the final word in the string. You also don't exit at the end of the string, but instead loop through whatever is in your string all the way out to character 101.
As a general structure, be very, very careful with this:
if (condition)
else if (condition)
// without a final else section
If you do that, you need to think about what you're doing. In this particular case, you can have:
if (a[i] != 0 && a[i] != ' ')
else
It may not solve all your issues, but it should solve some.
A nice sliding window pattern implementation.
You have 3 problems in your code
You must not write cin >> a;
You must not write cin.ignore();
You need to modify your if statement like so: if (a[i] != ' ' && a[i] != '\0') Otherwise you will not detect the last word.
Your complete working code with that minor fixes will lokk like that.
int main()
{
char a[101]{ 0 };
//cin >> a;
cin.getline(a, 101);
//cin.ignore();
int currLen{ 0 };
int maxLen{ 0 };
int startInd{ -1 };
int endInd{ -1 };
for (int i = 0; i < 101; i++)
{
if (a[i] != ' ' && a[i] != '\0')// Add comparison
{
++currLen;
}
else if (a[i] == ' ' || a[i] == '\0')
{
if (currLen > maxLen)
{
maxLen = currLen;
startInd = i - currLen;
endInd = i - 1;
}
if (a[i] == '\0')
break;
currLen = 0;
}
}
cout << maxLen << endl;
if (startInd == -1)
cout << -1;
else
for (int i = startInd; i <= endInd; i++)
cout << a[i];
return 0;
}
Additionally. You should not use C-Style arrays in C++. And please use std::string
There is a couple of things here:
1- You don't need to do a cin>>a this is actually consuming the first word, and afterwards the content is overrided by cin.getline(). So removing the firsst cin>>ayou'll be fine.
2- The last word is not read because there isn't any if condition that matches the condition aka.
if(a[i]!=' ' ) case of not a space
//not end of word
else if(a[i]==' '||a[i]=='\0') case of space or null
//end of word
So your last character is not a space nor null, that means you don't detect the last word.

A loop never starts

I'm writing a simple function that is supposed to read an input from a user as a string. Check if the strings solely consist of digits then converts it to and int and returns it. The problem is the loop never used regardless of the input. I'm struggling to find the root of the problem.
int correctInt()
{
string temp;
int input;
bool m;
do
{
m = false;
getline(cin, temp);
int length=temp.length();
for (int a = 0; a < length; a++)
{
if (temp[a] < '0' && temp[a]>'9')
{
cout << "ID should consist of numbers. Try again: ";
m = true;
break;
}
}
if (!m)
{
return input = atoi(temp.c_str());
}
} while (1);
}
Thank you in advance
You should use OR instead of AND:
temp[a] < '0' || temp[a]>'9'
Try to change && (and) condition to || (or) condition
if (temp[a] < '0' || temp[a]>'9')

How to know if a number is a palindrome without using maths?

So I'm thinking if I could use strings to check if a number is a palindrome, but I don't really know how strings, arrays and that stuff works and I'm not arriving at anything.
I've done this using math, but I wonder if it would be easier to use arrays or strings.
n = num;
while (num > 0)
{
dig = num % 10;
rev = rev * 10 + dig;
num = num / 10;
}
// If (n == rev) the number is a palindrome
this is the code made with math
So it works yeah, but I'm curious
It is much easier if you use correctly the index of the array in the loop:
// Num is the number to check
// Supposing we are using namespace std
string numString = to_string(num);
bool palindrome = true;
int index = 0;
while(index < numString.size() && palindrome){
palindrome = numString[index] == numString[numString.size() - index - 1];
index++;
}
if(palindrome)
cout << num << " is a palindrome \n"; // line break included
else
cout << num << " is not a palindrome \n"; // line break included
Use this code:-
//num is the Number to check
//Converting int to String
ostringstream ss;
ss<<num;
string snum = ss.str();
string fromfront="", fromback="";
fromfront = snum;
string character;
for(int i=snum.length();i>0;i--)
{
if(i>0)
character = snum.substr(i-1, 1);
fromback+=character;
}
if(fromfront==fromback)
cout<<endl<<"It is a palindrome.";
else
cout<<endl<<"It is not a palindrome.";

c++ binary to decimal converter input to only accept 1 or 0

Hello I am trying to do a programming assignment that converts a binary number to a decimal. The problem states that I have to get the users input as a sting and if there is anything other than a 1 or a 0 in the users input it should give an error message then prompt them to give a new input. I have been trying for a while now and I cant seem to get it right can anyone help me?
so far this is my best attempt it will run every input of the string into a if statement but it only seems to care about the last digit i cant think of a way to make it so if there is a single error it will keep while loop statement as true to keep going.
#include <iostream>
#include <string>
using namespace std;
string a;
int input();
int main()
{
input();
int stop;
cin >> stop;
return 0;
}
int input()
{
int x, count, repeat = 0;
while (repeat == 0)
{
cout << "Enter a string representing a binary number => ";
cin >> a;
count = a.length();
for (x = 0; x < count; x++)
{
if (a[x] >= '0' &&a[x] <= '1')
{
repeat = 1;
}
else
repeat = 0;
}
}
return 0;
}
return 0;
}
Change your for loop as this:
count = a.length();
repeat = 1;
for (x = 0; x < count; x++)
{
if (a[x] != '0' && a[x] != '1')
{
repeat = 0;
break;
}
}
The idea is that repeat is assumed to be 1 at first (so you assume that your input is valid). Later on, if any of your input characters is not a 0 or 1, then you set repeat to 0 and exit the loop (there's no need to keep looking for another character)

Typo searching for at least 1 character

The original prompt was:
Write a program that keeps track of a speakers bureau. The program should use a
structure to store the following data about a speaker:
Name
Telephone Number
Speaking Topic
Fee Required
The program should use an array of at least 10 structures. It should let the user enter
data into the array, change the contents of any element, and display all the data stored
in the array. The program should have a menu-driven user interface.
Input Validation: When the data for a new speaker is entered, be sure the user enters
data for all the fields. No negative amounts should be entered for a speaker s fee.
The added prompt was:
I need this to expand the search pattern with the potential one character of letter or digit typos. Only one character maybe a typo, in any position Try these test patterns should get the following results:
0-9 is 0x30-0x39
a-z is 0x41-0x5A
A-Z is 0x61-0x7A (or lower case it)
And I can't get the added prompt to work with my current program.
No other characters in the search pattern may be changed.
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
bool print_one_typo(string input, string people[11], bool is_found[11])
{
bool found = false;
if (input[0] == '?')
{
char *strPtr = NULL;
for (int i = 0; i < 11; i++)
{
strPtr = strstr(people[i].c_str(), input.substr(1).c_str());
if (strPtr != NULL)
{
cout << "\t" << people[i] << endl;
found = true;
is_found[i] = true;
}
}
}
else
{
for (int i = 0; i < 11; i++)
{
bool match = true;
string str = people[i];
int value = str.find(input[0]);
for (int k = 0; k < input.length(); k++)
{
if (input[k] != '?' && input[k] != str[value++])
{
match = false;
break;
}
}
if (match && !is_found[i])
{
found = true;
cout << "\t" << people[i] << endl;
}
}
}
return found;
}
int main()
{
string people[11] = { "Becky Warren, 555-1223",
"Joe Looney, 555-0097",
"Geri Palmer, 555-8787",
"Lynn Presnell, 555-1225",
"Holly Gaddis, 555-8878",
"Sam Wiggins, 555-0998",
"Bob Kain, 555-8712",
"Tim Haynes, 555-7676",
"Warren Gaddis, 555-9037",
"Jean James, 555-9223",
"Ron Palmer, 555-7227" };
bool is_found[11] = { false };
string lookUp;
int i;
cout << "\t People and Phone numbers" << endl;
cout << "Enter name or phone number: ";
cin >> lookUp;
cout << "result: " << endl;
bool found = false;
bool output = false;
for (int i = 0; i < lookUp.length(); i++)
{
string local = lookUp;
found = print_one_typo(local.replace(i, 1, 1, '?'), people, is_found);
if (found) output = true;
}
if (!output)
cout << "No matching product was found" << endl;
return 0;
}
I think your code overthinks the problem. Also, you didn't specify if "typo" just means "wrong character", or a fuller range that includes dropped characters or inserted characters.
If you are only looking for matches with zero or one incorrect characters, but otherwise the same length, I think this code should do:
bool print_one_typo(string input, string people[11], bool is_found[11])
{
for (int i = 0; i < 11; i++)
{
if ( is_found[i] ) // Skip if it had already been found?
continue;
if ( input.length() != people[i].length() ) // Are they same length?
continue; // No: Skip it.
int typos = 0;
size_t len = input.length();
for (size_t j = 0; j != len && typos < 2; j++)
if ( input[j] != people[i][j] )
typos++;
if (typos < 2) // Fewer than 2 typos: We have a winner! Return it.
{
is_found[i] = true;
return true;
}
}
return false;
}
This code skips strings that differ in length, or which you're filtering out via the is_found[] array. Not sure why you're doing that, but I preserved that bit of your original code.
If it finds two strings that are the same length, it just compares them character by character, counting up typos. If it sees 2 or more typos, it skips to the next one. Otherwise, it takes the first string that's the same length but fewer than 2 typos.