I am scratching my head... why is the return statement inside strcmp_iter never being called?
When I run this function, the output is simply to count from 0 to 6 and then terminate... no return statement. Very frustrating. Interestingly, if I change myString2 to "abcdefG" then everything works fine... very odd.
int strcmp_iter(string s1, string s2) {
int i = 0;
for (; ((s1.at(i) == s2.at(i)) && (i <= s1.length())); i++) {
cout << i << endl;
}
return s1.at(i) - s2.at(i);
}
int main() {
string myString1 = "abcdefg";
string myString2 = "abcdefg";
int count_iter = strcmp_iter(myString1, myString2);
cout << "Iter: " << count_iter << endl;
return 0;
}
You are looping beyond the bounds of the string and probably throwing an std::out_of_range exception. Change your condition to
i < s1.length()
and make that check before any calls to std::string::at(size_type pos)
Also, beware your function can only work if s2 is at least as long as s1. You should probably be looping up to one less than std::min(s1.length(), s2.length()).
Whenever I see this construction, it makes me cringe:
for (; ((s1.at(i) == s2.at(i)) && (i <= s1.length())); i++)
C-like languages always do short circuit evaluation and from left to right. So the condition for termination—and validating that the comparison makes sense to do—should precede the comparison:
int n = s1.length();
if (s2.length() < n)
n = s2.length(); // choose smaller length
for (; i < n && s1.at(i) == s2.at(i); i++)
(I have also removed unnecessary parentheses, limited the search length to the short string, and changed <= to < because of how array subscripts work.)
for (; ((s1.at(i) == s2.at(i)) && (i <= s1.length())); i++) {
use i < s1.length()
Related
i already studied c++ in school and during the last days i have been doing the beginner c++ course of codecademy. On codecademy there is an exercise in which i have to identify palindrome words and return true or false. I haven't been able to resolve it so i saw the solution and it was:
#include <iostream>
// Define is_palindrome() here:
bool is_palindrome(std::string text) {
std::string reversed_text = "";
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
}
if (reversed_text == text) {
return true;
}
return false;
}
int main() {
std::cout << is_palindrome("madam") << "\n";
std::cout << is_palindrome("ada") << "\n";
std::cout << is_palindrome("lovelace") << "\n";
}
My only doubt is with this line:
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
i know it has to do with index values but i can't understand why it has a -1.
Could somebody explain this to me?
i thanks in advance whoever read this post. i'm sorry for my english or my poor using of stacksoverflow, i'm italian and that's my first time using this site.
for (int i = text.size() - 1; i >= 0; i--) {
reversed_text += text[i];
text is basically the string that you receive as input via function. size() is function that returns the size of the string i.e text.size() so in our test cases it will return
5 for madam
3 for ada
8 for lovelace
If you think about the strings as an array with exact above size then the index range will become
0-4 for madam
0-2 for ada
0-7 for lovelace
So that's why the text.size()-1 is using as the starting index of loop. text.size() will return the actual size of string and then minus 1 to get the index of last character in string.
so behind the scene, your loop iteration will look something like below
for (int i = 4; i >= 0; i--) { //for madam
}
//aca
for (int i = 2; i >= 0; i--) {
}
//lovelace
for (int i = 7; i >= 0; i--) {
}
I hope it clear out your confusion.
Thanks,
i know it has to do with index values but i can't understand why it has a -1.
If a string is n characters long, the characters in it are indexed from 0 to n−1.
Since the loop works with characters from the end of the string to the beginning, it starts with index text.size() - 1.
However, the solution you have shown is nominally inefficient. There is no reason to make a reversed copy of the string. It suffices merely to test whether each character in the first half of the string equals the character in the reflected position:
bool is_palindrome(std::string text)
{
size_t e = text.size();
for (int i = 0; i < e/2; ++i)
if (text[i] != text[e-1-i])
return false;
return true;
}
If using a for loop to reverse the string is confusing, you could also use the reverse function
std::string reversed_text = text;
reverse(reversed_text.begin(),reversed_text.end());
which just helps flip the entire string reversed_text and can achieve the same result in a simpler way.
string extract(string scrambeledword){
unsigned int index;
string output;
string input= " ";
for (index=0; index <= scrambeledword.length() ; index++);
{
if (index%2==0)
{
output+=input ;
cout << output;
}
}
return output;}
I want to extract the even numbered indexed letters from the 40 letter long word inputted by users. does this make sense? i have not taken arrays yet and do not want to include them.
Problems:
1. You have a ; after your for loop, the loop body is never run.
2. <= is wrong here since scrambeledword.length() is out of range. Use != or < instead.
3. You need to either assign something to input before adding it to output or get rid of it altogether.
4. As #Aconcagua pointed out, it is worth noting that I removed your declaration of index from the function scope and added it only to the for loop scope. If you also considered doing so, compiler would throw an error (since it'd be undeclared outside of the scope of for) and you'd be noted about the ; problem.
Fixed version:
string extract(const string &scrambeledword){ // copying strings is expensive
// unsigned int index; // obsolete
string output;
// string input= " "; // obsolete
for (size_t index = 0; index != scrambeledword.length(); ++index) // `<=` would be wrong since scrambeledword.length() is out of range
{
if (index % 2 == 0)
{
output += scrambeledword[index];
// cout << output; // obsolete. If you just want the characters, print scrambeledword[index]
cout << scrambeledword[index];
}
}
cout << endl; // break the line for better readability
return output;
}
Your code won't run the block under the for because there is a ; at the end of the line. That means the for runs without block. Basically it will count to the length of the given word.
In the for index <= scrambeledword.length() can cause an out of bound exception because you can index out of the string-array. Use index < scrambeledword.length() instead.
This can be a good solution for the problem:
string extract(const string& scrambeledword)
{
string output;
for (unsigned int index = 0; index < scrambeledword.length(); index++)
{
if (index % 2 == 0)
{
output += scrambeledword[index];
}
}
return output;
}
auto str = "HelloWorld"s;
int i = 0;
for_each(str.cbegin(), str.cend(), [&i](char const & c) { if (i++ % 2 == 0) cout << c; });
output: Hlool
You could go with something like this:
for(int i = 0; i < scrambleword.length(); i+=2){
output += scrambleword.at(i);
}
First of all, sorry for the mis-worded title. I couldn't imagine a better way to put it.
The problem I'm facing is as follows: In a part of my program, the program counts occurences of different a-zA-Z letters and then tells how many of each letters can be found in an array. The problem, however, is this:
If I have an array that consists of A;A;F;A;D or anything similar, the output will be this:
A - 3
A - 3
F - 1
A - 3
D - 1
But I am required to make it like this:
A - 3
F - 1
D - 1
I could solve the problem easily, however I can't use an additional array to check what values have been already echoed. I know why it happens, but I don't know a way to solve it without using an additional array.
This is the code snippet (the array simply consists of characters, not worthy of adding it to the snippet):
n is the size of array the user is asked to choose at the start of the program (not included in the snippet).
initburts is the current array member ID that is being compared against all other values.
burts is the counter that is being reset after the loop is done checking a letter and moves onto the next one.
do {
for (i = 0; i < n; i++) {
if (array[initburts] == array[i]) {
burts++;
}
}
cout << "\n\n" << array[initburts] << " - " << burts;
initburts++;
burts = 0;
if (initburts == n) {
isDone = true;
}
}
while (isDone == false);
Do your counting first, then loop over your counts printing the results.
std::map<decltype(array[0]), std::size_t> counts;
std::for_each(std::begin(array), std::end(array), [&counts](auto& item){ ++counts[item]; });
std::for_each(std::begin(counts), std::end(counts), [](auto& pair) { std::cout << "\n\n" << pair.first << " - " pair.second; });
for (i = 0; i < n; i++)
{
// first check if we printed this character already;
// this is the case if the same character occurred
// before the current one:
bool isNew = true;
for (j = 0; j < i; j++)
{
// you find out yourself, do you?
// do not forget to break the loop
// in case of having detected an equal value!
}
if(isNew)
{
// well, now we can count...
unsigned int count = 1;
for(int j = i + 1; j < n; ++j)
count += array[j] == array[i];
// appropriate output...
}
}
That would do the trick and retains the array as is, however is an O(n²) algorithm. More efficient (O(n*log(n))) is sorting the array in advance, then you can just iterate over the array once. Of course, original array sequence gets lost then:
std::sort(array, array + arrayLength);
auto start = array;
for(auto current = array + 1; current != array + arrayLength; ++current)
{
if(*current != *start)
{
auto char = *start;
auto count = current - start;
// output char and count appropriately
}
}
// now we yet lack the final character:
auto char = *start;
auto count = array + arrayLength - start;
// output char and count appropriately
Pointer arithmetic... Quite likely that your teacher gets suspicious if you just copy this code, but it should give you the necessary hints to make up your own variant (use indices instead of pointers...).
I would do it this way.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
vector<int> capCount(26, 0), smallCount(26, 0);
cout << "Enter the string\n";
cin >> s;
for(int i = 0; i < s.length(); ++i)
{
char c = s.at(i);
if(c >= 'A' && c <= 'Z')
++capCount[(int)c - 65];
if(c >= 'a' && c <= 'z')
++smallCount[(int)c - 97];
}
for(int i = 0; i < 26; ++i)
{
if(capCount[i] > 0)
cout << (char) (i + 65) << ": " << capCount[i] << endl;
if(smallCount[i] > 0)
cout << (char) (i + 97) << ": " << smallCount[i] << endl;
}
}
Note: I have differentiated lower and upper case characters.
Here's is the sample output:
output
I am trying to create a program that will take in an expression (example: "10*2+1") and solve it. My code is:
#include <iostream>
#include <string>
#include <vector>
void calculateString(std::string str);
int main() {
calculateString("10*2+2");
system("pause");
}
void calculateString(std::string str) {
int total = 0;
std::string temp1 = "";
std::string temp2 = "";
std::string add = "";
std::string *ray = new std::string[str.length()];
std::vector<int> newRay;
for (int i = 0; i < str.length(); i++) {
if (str.at(i) != '*' && str.at(i) != '/' && str.at(i) != '+' && str.at(i) != '-') {
add += str.at(i);
}
else {
ray[i] = add;
std::cout << ray[i] << "\n";
add = "";
}
}
for (int i = 0; i < str.length(); i++) {
if (ray[i].compare("*")) {
total = atoi(ray[i - 1].c_str()) * atoi(ray[i + 1].c_str());
newRay.push_back(total);
}
}
for (int i = 0; i < str.length(); i++) {
if (ray[i] == "+") {
newRay.push_back(atoi(ray[i - 1].c_str()) + atoi(ray[i + 1].c_str()));
}
}
for (int i = 0; i < newRay.size(); i++) {
std::cout << newRay[i] << "\n";
total += newRay[i];
}
std::cout << str << "=" << total << "\n";
}
However, whenever I run this I keep running into an access violation error that reads:
Exception thrown at 0x0F1CD4A0 (ucrtbased.dll) in CalcString.exe:
0xC0000005: Access violation reading location 0x01BE0FEE.
And it points to line 34 which is this:
total = atoi(ray[i - 1].c_str()) * atoi(ray[i + 1].c_str());
which is basically calculating the multiplication part of the expression then storing the asnwer in one variable. I have tried everything from changing my array to a vector to trying to rewrite all the methods and nothing seems to work. Please help
In
if (ray[i].compare("*"))
compare is misused. According to cppreference compare returns < 0 for smaller than, 0 for equal or > 0 for larger. As an if condition, 0 is false and everything else is true, so this resolves to
if (ray[i] != "*")
Probably the opposite of what is desired.
This allows entry into the if's body when ray[0] is "10" and i is 0, resulting in
total = atoi(ray[0 - 1].c_str()) * atoi(ray[0 + 1].c_str());
or
total = atoi(ray[-1].c_str()) * atoi(ray[1].c_str());
and accessing negative array indexes is undefined behaviour. Looks like it manifested as a crash in this case.
Solution:
All we care about is equality in this case so we can get away with
if (ray[i] == "*")
just as was done for
if (ray[i] == "+")
I also recommend a check to ensure an operator is never the first element of ray.
I recently did this question
Specification:
Input Format The first line contains the number of test cases, T. Next,
T lines follow each containing a long string S.
Output Format For each long string S, display the number of times SUVO
and SUVOJIT appears in it.
I wrote the following code for this :
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int suvo = 0;
int suvojit = 0;
string s;
cin >> s;
for (int i = 0; i <= s.size() - 7; i++) {
if (s.substr(i, 7) == "SUVOJIT")
suvojit++;
}
for (int i = 0; i <= s.size() - 4; i++) {
if (s.substr(i, 4) == "SUVO")
suvo++;
}
cout << "SUVO = " << suvo - suvojit << ", SUVOJIT = " << suvojit << "\n";
}
return 0;
}
The code about gave out of bounds exception for substr() function for this test case:
15
RSUVOYDSUVOJITNSUVOUSUVOJITESUVOSUVOSGSUVOKSUVOJIT
SUVOJITWSUVOSUVOJITTSUVOCKSUVOJITNSUVOSUVOJITSUVOJITSUVOSUVOSUVOJITTSUVOJ
SUVOSUVOSUVOJITASUVOJITGCEBISUVOJITKJSUVORSUVOQCGVHRQLFSUVOOHPFNJTNSUVOJITKSSUVO
SUVOJITSUVOJITJGKSUVOJITISUVOJITKJLUSUVOJITUBSUVOX
MMHBSUVOFSUVOFMSUVOJITUMSUVOJITPSVYBYPMCSUVOJIT
OASUVOSUVOJITSUVOSTDYYJSUVOJITSUVOJITSUVO
RLSUVOCPSUVOJITYSUVOSUVOOGSUVOOESUVOJITMSUVO
WVLFFSUVOJITSUVOVSUVORLESUVOJITPSUVOJITSUVO
RSUVOSUVOJITQWSUVOUMASUVOSUVOJITXNNRRUNUSUVOJIT
HYLSSUVOSUVOSUVOJITPOSUVOJIT
DGMUCSSSUVOJITMJSUVOHSUVOCWTGSUVOJIT
OBNSSUVOYSUVOSUVOJITSUVOJITRHFDSUVODSUVOJITEGSUVOSUVOSUVOJITSUVOSUVOJITSSUVOSUVOSUVOSSUVOJIT
AG
NSUVOJITSUVOSUVOJIT
CGJGDSUVOEASUVOJITSGSUVO
However, when instead of using the s.size() function, I converted the string into a char constant and took the length of it using strlen, then the code caused no error and everything went smoothly.
So, my question is... Why did this happen?
This is my working code with the change:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int suvo = 0;
int suvojit = 0;
string s;
cin >> s;
int le = strlen(&s[0]);
for (int i = 0; i <= le - 7; i++) {
if (s.substr(i, 7) == "SUVOJIT")
suvojit++;
}
for (int i = 0; i <= le - 4; i++) {
if (s.substr(i, 4) == "SUVO")
suvo++;
}
cout << "SUVO = " << suvo - suvojit << ", SUVOJIT = " << suvojit << "\n";
}
return 0;
}
In one case, you use size_t, in the other case you use int.
If the length is for example 6 characters, then s.size () - 7 is not -1, but one huge number and everything goes wrong. But if you write int len = strlen (...), then len - 7 is indeed -1 and everything is fine.
When I see a number subtracted from size_t, that's an immediate red flag. Write "i + 7 ≤ s.size()", not "i ≤ s.size() - 7".
First of all, in my testing your second leads to a problem as well:
Second, especially with older compilers (well, libraries, really) this can be horrendously inefficient, creating a huge number of temporary strings that you only use to compare with another string1.
So, let's consider how the job should be done instead. std::string has a member named find for situations like this. It returns the position of one string inside another, or std::string::npos if there is none. It allows you to specify a starting position at which to begin searching, when you don't want to start from the beginning.
We also, of course, have two instances of essentially identical code, once to search for SUVO, the other to search for SUVOJIT. The code would be much better off with the search code moved into a function, so we only have the search code in one place.
int count_pos(std::string const &haystack, std::string const &needle) {
size_t pos = 0;
int ret = 0;
while ((pos = haystack.find(needle, pos)) != std::string::npos) {
++ret;
++pos;
}
return ret;
}
Note that this also eliminates quite a bit more messy "stuff" like having to compute the maximum possible position at which at match could take place.
1. Why does compiler/library age matter? Older libraries often used a COW string that dynamically allocated storage for every string. More recent ones typically include what's called a "short string optimization", where storage for a short string is allocated inside the string object itself, avoiding the dynamic allocation.