Replacing a word in a sentence with a another word - c++

i was working on this question but there is some weird error in it. The problem is in the "Replace" function. I have commented the problem in the code below.
I made three dynamic character arrays (sentence, word1, word2) and used cin.getline to input. What i want to do is that if :
sentence = "I like pizza",
word1 = "like", and
word2 = "hate"
then I want sentence = "I hate pizza".
Also this is my first time using stack overflow so if there is any problem with this thread please let me know. Your help will be greatly appreciated.
void Replace(char* s, char* w1, char* w2)
{
int lisw = 0; //lisw = letters in single word
bool found = false;
for (int i = 0; s[i] != '\0' || found == true; i++)
{
lisw = 0;
//Problem is down here. The loop doesn't terminate when encountering a
//space character. When i used static_cast code to check the ASCII
//values only junk values were output. If i just cout<<s; then there is
//no problem but doing it here causes some weird logical errors.
for (int j = i; s[j] != ' '; j++)
{
lisw++;
cout << static_cast<int>(s[j]);
}
found = true;
for (int j = i; j < lisw; j++)
{
if (s[j] != w1[j])
{
found = false;
}
}
if (found == true)
{
for (int j = i; j < lisw; j++)
{
s[j] = w2[j];
}
}
i = i + lisw;
}
}

Ok so i found a solution thanks to the comments. I'll copy the corrected code below. The corrections can be seen in the comments.
void Replace(char* s,char* w1, char* w2)
{
int lisw = 0; //lisw = letters in single word
bool found =false;
for (int i=0;s[i]!='\0' && found!=true;i++) //Replaced || with &&.
{
lisw=0;
for (int j=i;s[j]!=' '&& s[j]!='\0';j++)//added: && s[j]!='\0' so the loop terminates because otherwise it kept finding "spaces" since the character array was of a larger size to accommodate any sentence.
{
lisw++;
}
found=true;
int k=0;
for (int j=i;j<lisw+i;j++) //loop goes until lisw+i instead of lisw
{
if (s[j]!=w1[k])
{
found=false;
}
k++;
}
k=0;
if (found==true)
{
for (int j=i;j<lisw+i;j++)//same as above.
{
s[j]=w2[k];
k++;
}
}
i=i+lisw;
}
}

Related

C++, Find out if a string contains a substring?

I don't know how to use the find() function to check if a string contains a substring, then the program should print out all Words, and "Contains" if Sentence contains at least one of them. Can anyone help me out? My usage of find() sets A always to true. Thanks for help
#include <iostream>
#include <string>
using namespace std;
string Words, Sentence, buf;
int i, n, j = 0;
string arr[20];
bool A;
int main() {
cout << "Words separated by slashes";
cin >> Words;
cout << "Sentence";
cin >> Sentence;
for (i = 0; i <= Words.length(); i++)
{
if (Words[i] != '/')
{
buf = buf + Words[i];
}
else
{
arr[n] = buf;
n = n + 1;
buf = "";
}
}
for (j = 0; j <= n; j++)
{
cout << arr[j] << "\n";
if (Sentence.find(arr[j]) != string::npos)
{
A = true;
}
}
if (A == true)
{
cout << "Contains.";
}
else
{
enter code herecout << "Does not contain.";
}
}
There are a few bugs and issues in this code I think, but the biggest is the for loops all go too far by one.
for (i = 0; i <= Words.length(); i++)
and
for (j = 0; j <= n; j++)
should be
for (i = 0; i < Words.length(); i++)
and
for (j = 0; j < n; j++)
The valid indexes for a string, vector or array are zero upto but not including the size of the string, vector or array.
This mistake causes the bug that you see. Suppose you have two words in arr, e.g. arr = { "stack", "overflow", "", "", ... } . Because you go around the for loop one too many times you end up searching for arr[2] which equals "". This search always succeeds because every string contains the empty string. And so you always set A to true.

How to compare a certain character with another character of a string

In the following code, I am having trouble comparing specific letters two given strings.
#include <bits/stdc++.h>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
cin.ignore();
string phrases[m];
string records[n];
for (int i = 0; i < m; i++) {
getline(cin, phrases[i]);
}
for (int i = 0; i < n; i++) {
getline(cin, records[i]);
}
int lowBound;
sort(phrases, phrases + m);
int ans = 0;
bool stillIs;
for (int i = 0; i < n; i++) {
lowBound = lower_bound(phrases, phrases + m, records[i]) - phrases;
if (lowBound == m) {
continue;
}
stillIs = true;
for (int j = 0; j < records[i].length(); i++) {
if (records[i][j] == phrases[lowBound][j]) {
stillIs = false;
}
}
if (stillIs) {
ans++;
}
}
cout << ans;
return 0;
}
On line 33, if (records[i][j] == phrases[lowBound][j]), it is not giving me an error, but if I run it with this line, nothing happens, but when I comment the if statement out, it works properly, but obviously not giving me the correct answer. Is there any way I can compare these two strings (the second one is larger in size than the first one) to find whether the first one is the start of the second one?
Thanks!
You are incrementing i instead of j in the loop at line 32
You have your test backwards in line 33 - you want to set stillIs = false if the characters don't match, (i.e., !=)
I haven't fully read your code, but those two problems jumped out at me, so see if that sorts it out

for loop skips one round on reading values to char array in c++

So I got this weird thing that's happening to me.
I have a 2 dimensional char array, I'm suppose to put values in the array with the following conditions:
Each word (string) should be in a different array (different
line)
"." is an indicator that it is the end of the input.
This is my code:
const int MAX_STRS = 10, MAX_STR_LEN = 8;
int main()
{
char dict[MAX_STRS][MAX_STR_LEN] = { 0 };
getArray(dict);
return EXIT_SUCCESS;
}
void getArray(char array[][MAX_STR_LEN])
{
bool dot = false;
int i, j;
for ( i = 0; i < MAX_STRS && !dot; i++)
for ( j = 0; j < MAX_STR_LEN && !isspace(array[i][j - 1]); j++)
{
array[i][j] = cin.get();
if (array[i][j] == '.')
{
dot = true;
break;
}
}
}
The line I'm trying to read is:
blabla picked nice PeTer a hahaha of pickled Piper .
for some reason every time i=8, j automatically has the same value (j=8) and it skips this round of the loop.
Help would be much appreciated!
The problem was that when j=0, I asked him to check if array[-1] has whitespace.
Anyway here is the fixed code:
void getArray(char array[][MAX_STR_LEN])
{
bool dot = false;
int i, j;
for ( i = 0; i < MAX_STRS && !dot; i++)
for ( j = 0; j < MAX_STR_LEN ; j++)
{
array[i][j] = cin.get();
if (array[i][j] == '.')
{
dot = true;
break;
}
if( isspace(array[i][j]))
break;
}
}
Thank you Alan Stokes for bringing that to my attention!
I believe that your problem is with this:
for ( j = 0; j < MAX_STR_LEN && !isspace(array[i][j - 1]); j++)
Ask yourself what are you reading from when j is 0? That code tries to read from array[i][-1]. What is that? It could be anything!
If your loop is exiting early then that isspace check is probably returning true.
Sometimes to debug these things you need to discard all of your assumptions and check each thing individually using a debugger or print statements.
For example you could have put this line before your for loop:
cout << isspace(array[i][-1]);

Trouble with finding a c-string substring in C++

long time lurker, first time poster. I have been working on this problem for the last six hours hours.
Problem:
Implement the following functions. Each function deals with null terminated C-Style strings. You can assume that any char array passed into the functions will contain null terminated data. Place all of the functions in a single file and then create a main() function that tests the functions thoroughly.
Note: You may not use any c-string functions other than strlen().
I am having trouble with the fourth function.
The desired behavior is: This function returns the index in string s where the substring can first be found. For example if s is "Skyscraper" and substring is "ysc" the function would return 2. It should return -1 if the substring does not appear in the string.
prototype:
int findSubstring(char *str, char substring[])
Here's my two starts for function definitions, I'm not really sure if either is going in the right direction, I'm having a lot of trouble keeping the loop iterations in my head, any help would be TREMENDOUSLY appreciated.
int findSubstring(char *str, char substring[]){
int subS = -1, index1 = 0, index2 = 0;
int length1 = (strlen(str) - 1);
int length2 = (strlen(substring) - 1);
if(length1 > length2){
for(int i = 0; i <= length2; i++){
for(int j = 0; j <= length1; j++){
if(*(substring + i) == *(str + j) && *(substring +i) != '\0' ){
i++;
if(index1 == 0){
index1 = i;
}
}
if( *(substring + i) == '\0'){
subS = i + 2;
}
}
}
}
if (length1 < length2){
cout << "Invalid, substring exceeds size of string!" << endl;
}
return subS;
}
int findSubstring(char *str, char substring[]){
int index = -1;
int lengthStr = (strlen(str) - 1);
int lengthSub = (strlen(substring) - 1);
if (lengthStr < lengthSub){
cout << "Invalid input, substring exceeds size of string!" << endl;
}
if( lengthSub == 0){
cout << "";
}
if (lengthStr > lengthSub){
for(int i = 0; i <= lengthSub; i++){
for(int j = 0; j <= lengthStr; j++){
}
return index;
}
//You can replace my str.size() and subString.size() by the size of each c-string.
int stringPointerOperation( string str, string subString )
{
int pos=0;
bool notFound;
for(int i = 0; i < str.size() ; i++)
{
notFound= false;
if(str[i] == subString[0])
{
pos=i;
for(int k = 0 ; k < subString.size() && k < str.size() ; k++,i++)
{
if(subString[k] != str[i] )
{
notFound=true;
break;
}
}
}
}
if(notFound)
return -1;
else
return pos;
}
You are using the wrong strategy for finding a sub-string in a string. The outer for loop needs to iterate over the main string and the inner for loop needs to iterate over the sub-string.
Say you are looking for "de" in "abcdef". The strategy that I find easier to understand and implement is:
Can I find "de" starting from 0 of "abcdef". No, I can't.
Can I find "de" starting from 1 of "abcdef". No, I can't.
Can I find "de" starting from 2 of "abcdef". No, I can't.
Can I find "de" starting from 3 of "abcdef". Yes, I can. Return 3.
Here's a version that works for me.
int findSubstring(char *str, char substring[]){
int i;
int j;
int length1 = strlen(str);
int length2 = strlen(substring);
if(length1 < length2){
std::cout << "Invalid, substring exceeds size of string!" << std::endl;
return -1;
}
for(i = 0; i < length1; i++){
for(j = 0; j < length2; j++){
// The index to use access the element of str
// needs to be offset by i.
if( str[i+j] != substring[j] )
{
break;
}
}
if ( j == length2 )
{
return i;
}
}
return -1;
}

Finding the largest palindrome in string implementation

I'm trying to solve a problem that asks to find the largest palindrome in a string up to 20,000 characters. I've tried to check every sub string whether it's a palindrome, that worked, but obviously was too slow. After a little googling I found this nice algorithm
http://stevekrenzel.com/articles/longest-palnidrome. I've tried to implement it, however I can't get it to work. Also the given string contains illegal characters, so I have to convert it to only legal characters and output the longest palindrome with all characters.
Here's my attempt:
int len = original.length();
int longest = 0;
string answer;
for (int i = 0; i < len-1; i++){
int lower(0), upper(0);
if (len % 2 == 0){
lower = i;
upper = i+1;
} else {
lower = i;
upper = i;
}
while (lower >= 0 && upper <= len){
string s2 = original.substr(lower,upper-lower+1);
string s = convert(s2);
if (s[0] == s[s.length()-1]){
lower -= 1;
upper += 1;
} else {
if (s.length() > longest){
longest = s.length();
answer = s2;
}
break;
}
}
}
I can't get it to work, I've tried using this exact algorithm on paper and it worked, please help. Here's full code if you need it : http://pastebin.com/sSskr3GY
EDIT:
int longest = 0;
string answer;
string converted = convert(original);
int len = converted.length();
if (len % 2 == 0){
for (int i = 0; i < len - 1; i++){
int lower(i),upper(i+1);
while (lower >= 0 && upper <= len && converted[lower] == converted[upper]){
lower -= 1;
upper += 1;
}
string s = converted.substr(lower+1,upper-lower-1);
if (s.length() > longest){
longest = s.length();
answer = s;
}
}
} else {
for (int i = 0; i < len; i++){
int lower(i), upper(i);
while (lower >= 0 && upper <= len && converted[lower] == converted[upper]){
lower -= 1;
upper += 1;
}
string s = converted.substr(lower+1,upper-lower-1);
if (s.length() > longest){
longest = s.length();
answer = s;
}
}
}
Okay so I fixed the problems, it works perfectly fine but only if the length of converted string is odd. Please help.
I can see two major errors:
Whether you initialise your upper/lower pointers to i,i or i,i+1 depends on the parity of the palindrome's length you want to find, not the original string. So (without any further optimisations) you'll need two separate loops with i going from 0 to len (len-1), one for odd palindrome lengths and another one for even.
The algorithms should be executed on the converted string only. You have to convert the original string first for it to work.
Consider this string: abc^ba (where ^ is an illegal character), the longest palindrome excluding illegal characters is clearly abcba, but when you get to i==2, and move your lower/upper bounds out by one, they will define the bc^ substring, after conversion it becomes bc, and b != c so you concede this palindrome can't be extended.
#include <iostream>
using namespace std;
int main()
{
string s;
cin >> s;
signed int i=1;
signed int k=0;
int ml=0;
int mi=0;
bool f=0;
while(i<s.length())
{
if(s[i]!=s[i+1])
{
for(k=1;;k++)
{
if(!(s[i-k]==s[i+k] && (i-k)>=0 && (i+k)<s.length()))
{
break;
}
else if(ml < k)
{
ml=k;
mi=i;
f=1;
}
}
}
i++;
}
i=0;
while(i<s.length())
{
if(s[i]==s[i+1])
{
for(k=1;;k++)
{
if(!(s[i-k]==s[k+1+i] && (i-k)>=0 && (k+i)<s.length()))
{
break;
}
else if(ml < k)
{
ml=k;
mi=i;
}
}
}
i++;
}
if(ml < 1)
{
cout << "No Planidrom found";
return 0;
}
if(f==0)
{
cout << s.substr(mi-ml,2*ml+2);
}
else
{
cout << s.substr(mi-ml,2*ml+1);
}
return 0;
}
#biziclop : As you said.. i used 2 while loops. one for even and one for old palindrom string. finally i was able to fix it. thanks for your suggestion.
public void LongestPalindrome()
{
string str = "abbagdghhkjkjbbbbabaabbbbbba";
StringBuilder str1=new StringBuilder();
StringBuilder str2= new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
str1.Append((str[i]));
for (int j = i + 1; j < str.Length; j++)
{
str1.Append((str[j]));
if (Checkpalindrome(str1))
{
str2.Append(str1);
str2.Append(" ");
}
}
str1.Clear();
}
var Palstr = str2.ToString().Split(' ');
var Longestpal = Palstr.Where(a => a.Length >= (Palstr.Max(y => y.Length)));
foreach (var s in Longestpal)
{
Console.WriteLine(s);
}
}
public bool Checkpalindrome(StringBuilder str)
{
string str1 = str.ToString();
StringBuilder str2=new StringBuilder();
var revstr = str1.Reverse();
foreach (var c in revstr )
{
str2.Append(c);
}
if (str1.Equals(str2.ToString()))
{
return true;
}
return false;
}