How to save the index of a string in a vector? - c++

Let's say I have a function
int pozvec(vector<string> vect)
which takes as parameter a pre-filled vector of strings.
I want to know at which position i there is the character "p", specifically "p". All of the strings are single-character, but the vector is declared as containing strings. I want to save the index at which "p" is found in a variable x;
for(int i=0; i<vect.size(); i++)
if(vect[i] == "p")
x=i;
does not seem to work. Nor does strcmp, at all.
The problem is more complex, but the part that doesn't work is this one.
Thank you in advance for your help!

I don't know what you really want to do, but this worked perfectly fine for me:
for (size_t i {}; i < vec.size(); ++i) {
if (vec.at(i) == "p") {
x = i;
break; // I don't know wether you want to break here or not
} else {
continue;
}
}
Or if you all strings include just one character this should also work:
for (size_t i {}; i < vec.size(); ++i) {
if (vec.at(i).at(0) == 'p') {
x = i;
break; // I don't know wether you want to break here or not
} else {
continue;
}
}

By that function, your storing the index of the last occurrence of the string your looking for. This is because your not exiting from the loop once the first occurrence was found.
To exit from a loop conditionally, use the break statement.
for(int i = 0; i< vect.size(); i++)
{
if(vect[i] == "p")
{
x=i;
break;
}
}
Now it will exit right after the first occurrence was found.
You also have another option in the form of std::find.
int index = std::find(vect.begin(), vect.end(), "P") - vect.begin()

Related

Adding a space before a character in a string C++ insert function

I am attempting to add space before a character in a string by using the insert function.
Can someone kindly explain why the following code does not work ?
for(int i = 0; i < line.length(); i++)
{
if(line[i+1] == '=')
{
line.insert(i, " ");
}
}
If you want to insert before = you can get the index of = directly and not the index of char followed by =. This could lead to out of bounds access.
Also, when you insert the space you extend your string by 1, that's ok but only if you also adjust the counter i, otherwise it will insert again and again and again before = resulting in infinite loop. Adjust your code in this manner:
for (int i = 0; i < line.length(); i++)
{
if (line[i] == '=')
{
line.insert(i++, " ");
}
}
The code seems fine except for one little detail:
Imagine you have a string with "test=something". When you iterate it, when i is 3 you will find the next character is an equals, so you put a space into it. Next iteration i will be 4, but you just added a space, so at i equals 5 there's the same equals sign. So you put another space and so on. TO fix this youy can try:
std::string line = "test=something";
for (int i = 0; i < line.length(); i++)
{
if (line[i + 1] == '=')
{
i++;
line.insert(i, " ");
}
}

String matching algorithm trying to correct it

I'm trying to do string matching algorithm a brute force method. but The algorithm is not working correctly, I get an out of bound index error.
here is my algorithm
int main() {
string s = "NOBODY_NOTICED_HIM";
string pattern="NOT";
int index = 0;
for (int i = 0; i < s.size();)
{
for (int j = 0; j < pattern.size();)
{
if(s[index] == pattern[j])
{
j++;
i++;
}
else
{
index = i;
j = 0;
}
}
}
cout<<index<<endl;
return 0;
}
FIXED VERSION
I fixed the out of bound exception. I don't know if the algorithm will work with different strings
int main() {
string s = "NOBODY_NOTICED_HIM";
string pattern="NOT";
int index = 0;
int i = 0;
while( i < s.size())
{
i++;
for (int j = 0; j < pattern.size();)
{
if(s[index] == pattern[j])
{
index++;
j++;
cout<<"i is " <<i << " j is "<<j <<endl;
}
else
{
index = i;
break;
}
}
}
cout<<i<<endl;
return 0;
}
Because the inner for loop has a condition to loop while j is less than pattern.size() but you are also incrementing i inside the body. When i goes out of bounds of s.size() then index also goes out of bounds and you'd get an OutOfBounds error.
The brute force method has to test the pattern with every possible subsequence. The main condition is the length, which has to be the same. All subsequence from s are:
['NOB', 'OBO', 'BOD', 'ODY', 'DY_', 'Y_N', 'NO', 'NOT', 'OTI', 'TIC',
'ICE', 'CED', 'ED', 'D_H', '_HI', 'HIM']
There are many ways to do it, you can do it char by char, or by using string operations like taking a substring. Both are nice excercises for learning.
Starting at zero in the s string you take the first three chars, compare to the pattern, and if equal you give the answer. Otherwise you move on to the char starting at one, etc.

Code not returning the right index

I'm tring to solve a small problem. I have two strings. s1 and s2. I want my function to return the first index of s1 that has a character not present in the string s2. This is my code.
int cad_nenhum_dos (char s1[], char s2[]){
int i,j;
for (i=0;s1[i]!='\0';i++)
{
for (j=0;s2[j]!='\0';j++)
if (s1[i]!=s2[j]) return i;
}
return -1;
}
If I run s1="hello" s2="hellm", the result should be index 4, because s1[4]='o' and "o" is not present in s2... But I allways get 0 when I run this. The -1 works fine if the strings are the same.
What am I doing wrong?
Regards
In your inner loop you need to break out when you find a character the same -- as it stands you're returning when there are any different characters in the second string, even if an earlier one was the same. You want something like
for (j=0;s2[j]!='\0';j++)
if (s1[i]==s2[j]) break;
if (s2[j]==0)
return i;
I.e. you want to return the ith character of the first string when you've made you way through the whole of the second string without having found that character.
For programming exercises at the introductory level it's a good idea to carefully execute the code manually (step through yourself and see what's happening).
As TooTone suggested, you need to break out of the loop when you find a match:
for (int i = 0; s1[i] != '\0'; i++)
{
bool charFound = false;
for (int j = 0; s2[j] != '\0'; j++)
{
if (s1[i] == s2[j])
{
charFound = true;
break;
}
}
if ( ! charFound)
return i;
}
Because the inner for-loop is comparing first letter of the first string against all the letters in the second string.
int cad_nenhum_dos (char s1[], char s2[])
{
int i,j;
for(i=0; s1[i]; i++)
{
if(s1[i] != s2[j])
return(i);
}
return(-1);
}

Getting run time error working with vectors

So, I read the problem 4.5 from Accelerated C++, and interpreted it rather wrong. I wrote a program which is supposed to display counts of a word in string. However, I have probably done something very stupid, and very wrong. I can't figure it out.
Here's the code: http://ideone.com/87zA7E.
Stackoverflow says links to ideone.com must be accompanied by code. Instead of pasting the all of it, I will just paste the function which I think is most likely at fault:
vector<str_info> words(const vector<string>& s) {
vector<str_info> rex;
str_info record;
typedef vector<string>::size_type str_sz;
str_sz i = 0;
while (i != s.size()) {
record.str = s[i];
record.count = 0;
++i; //edit
for (str_sz j = 0; j != s.size(); ++j) {
if (compare(record, s[j]))
++record.count;
}
for (vector<str_info>::size_type k = 0; k != s.size(); ++k) {
if (!compare(record, rex[k].str))
rex.push_back(record);
}
}
return rex;
}
One problem is that you have this:
str_sz i = 0;
while (i != s.size()) {
but you never increment i, leading to an endless loop. Inside of that loop, you're pushing elements into vector rex. A vector cannot contain an infinite number of elements.
Also, you are trying to access:
rex[k].str
in
for (vector<str_info>::size_type k = 0; k != s.size(); ++k) {
if (!compare(record, rex[k].str)) // rex is empty in the beginning!!
rex.push_back(record);
}
But you do not know whether rex has k+1 elements in it.
EDIT: Change your code to:
while (i != s.size()) {
// read new string into a record (initial count should be one).
str_info record;
record.str = s[i];
record.count = 1;
// check if this string already exists in rex
bool found = false;
for (vector<str_info>::size_type k = 0; k < rex.size(); ++k) {
if ( record.str == rex[k].str ) {
rex[k].count++;
found = true;
break;
}
}
i++;
if ( found )
continue;
// if it is not found then push_back to rex
rex.push_back( record );
}

Can I use break to exit multiple nested 'for' loops?

Is it possible to use the break function to exit several nested for loops?
If so, how would you go about doing this? Can you also control how many loops the break exits?
No, don't spoil it with a break. This is the last remaining stronghold for the use of goto.
AFAIK, C++ doesn't support naming loops, like Java and other languages do. You can use a goto, or create a flag value that you use. At the end of each loop check the flag value. If it is set to true, then you can break out of that iteration.
Just to add an explicit answer using lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Of course this pattern has a certain limitations and obviously C++11 only but I think it's quite useful.
Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.
Of course, this brings up the other argument of whether you should ever explicitly return from a function anywhere other than at the end.
break will exit only the innermost loop containing it.
You can use goto to break out of any number of loops.
Of course goto is often Considered Harmful.
is it proper to use the break function[...]?
Using break and goto can make it more difficult to reason about the correctness of a program. See here for a discussion on this: Dijkstra was not insane.
How about this?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Although this answear was already presented, i think a good approach is to do the following:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
A code example using goto and a label to break out of a nested loop:
for (;;)
for (;;)
goto theEnd;
theEnd:
One nice way to break out of several nested loops is to refactor your code into a function:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
I know this is an old thread but I feel this really needs saying and don't have anywhere else to say it. For everybody here, use goto. I just used it.
Like almost everything, goto is not 100% either/xor "bad" or "good". There are at least two uses where I'd say that if you use a goto for them - and don't use it for anything else - you should not only be 100% okay, but your program will be even more readable than without it, as it makes your intention that much clearer (there are ways to avoid it, but I've found all of them to be much clunkier):
Breaking out of nested loops, and
Error handling (i.e. to jump to a cleanup routine at the end of a function in order to return a failure code and deallocate memory.).
Instead of just dogmatically accepting rules like "so-so is 'evil'", understand why that sentiment is claimed, and follow the "why", not the letter of the sentiment. Not knowing this got me in a lot of trouble, too, to the point I'd say calling things dogmatically "evil" can be more harmful than the thing itself. At worst, you just get bad code - and then you know you weren't using it right so long as you heard to be wary, but if you are wracking yourself trying to satisfy the dogmatism, I'd say that's worse.
Why "goto" is called "evil" is because you should never use it to replace ordinary ifs, fors, and whiles. And why that? Try it, try using "goto" instead of ordinary control logic statements, all the time, then try writing the same code again with the control logic, and tell me which one looks nicer and more understandable, and which one looks more like a mess. There you go. (Bonus: try and add a new feature now to the goto-only code.) That's why it's "evil", with suitable scope qualification around the "evil". Using it to short-circuit the shortcomings of C's "break" command is not a problematic usage, so long as you make it clear from the code what your goto is supposed to accomplish (e.g. using a label like "nestedBreak" or something). Breaking out of a nested loop is very natural.
(Or to put it more simply: Use goto to break out of the loop. I'd say that's even preferable. Don't use goto to create the loop. That's "evil".)
And how do you know if you're being dogmatic? If following an "xyz is evil" rule leads your code to be less understandable because you're contorting yourself trying to get around it (such as by adding extra conditionals on each loop, or some flag variable, or some other trick like that), then you're quite likely being dogmatic.
There's no substitute for learning good thinking habits, moreso than good coding habits. The former are prior to the latter and the latter will often follow once the former are adopted. The problem is, however, that far too often I find, the latter are not explicated enough. Too many simply say "this is bad" and "this needs more thought" without saying what to think, what to think about, and why. And that's a big shame.
(FWIW, in C++, the need to break out of nested loops still exists, but the need for error codes does not: in that case, always use exceptions to handle error codes, never return them unless it's going to be so frequent that the exception throw and catch will be causing a performance problem, e.g. in a tight loop in a high demand server code, perhaps [some may say that 'exceptions' should be 'used rarely' but that's another part of ill-thought-out dogmatism: no, at least in my experience after bucking that dogma I find they make things much clearer - just don't abuse them to do something other than error handling, like using them as control flow; effectively the same as with "goto". If you use them all and only for error handling, that's what they're there for.].)
goto can be very helpful for breaking nested loops
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
I'm not sure if it's worth it, but you can emulate Java's named loops with a few simple macros:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Example usage:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Another example:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.
from msdn.
I do think a goto is valid in this circumstance:
To simulate a break/continue, you'd want:
Break
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
Continue
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
Break any number of loops by just one bool variable see below :
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
In this code we break; all the loops.
Other languages such as PHP accept a parameter for break (i.e. break 2;) to specify the amount of nested loop levels you want to break out of, C++ however doesn't. You will have to work it out by using a boolean that you set to false prior to the loop, set to true in the loop if you want to break, plus a conditional break after the nested loop, checking if the boolean was set to true and break if yes.
I know this is old post . But I would suggest a bit logical and simpler answer.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
bool found = false;
for(int i=0; i < m; ++i){
for(int j=0; j < n; ++j)
if(grid[i][j] == '*'){
q.push(make_pair(i,j));
found = true;
break;
}
if(found)
break;
}
My suggestion is use a check variable to break a desired loop. The result code may not be so pleasant.
You can use preprocessors in order to make desired breaking under the hood. This approach can hides ugly codes and extra complexity.
For example, I created my custom break mechanism as follow:
Wanted code:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
breakToLevel = 0;
}
if (breakToLevel < 3) {
break;
}
}
if (breakToLevel < 2) {
break;
}
}
if (breakToLevel < 1) {
break;
}
}
Defined macros:
#define BREAK_TO(L) breakToLevel = (L);
#define CHECK_BREAK(L) if (breakToLevel < (L)) break;
and result:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
BREAK_TO(0)
}
CHECK_BREAK(3)
}
CHECK_BREAK(2)
}
CHECK_BREAK(1)
}
while (i<n) {
bool shouldBreakOuter = false;
for (int j=i + 1; j<n; ++j) {
if (someCondition) {
shouldBreakOuter = true;
}
}
if (shouldBreakOuter == true)
break;
}
you can use "goto" to leave nested loops
below is my original code including "goto"
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
goto fail;
}
}
cout << sum << endl;
fail:
}
return 0;
}
however, I could avoid "goto" by adding a function "calculate"
void calculate(const string &str)
{
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
return;
}
}
cout << sum << endl;
}
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
calculate(str);
}
return 0;
}
You can use try...catch.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
If you have to break out of several loops at once, it is often an exception anyways.
Breaking out of a for-loop is a little strange to me, since the semantics of a for-loop typically indicate that it will execute a specified number of times. However, it's not bad in all cases; if you're searching for something in a collection and want to break after you find it, it's useful. Breaking out of nested loops, however, isn't possible in C++; it is in other languages through the use of a labeled break. You can use a label and a goto, but that might give you heartburn at night..? Seems like the best option though.