I have an array that gets populated by either a "." or a "#", and I need a way of checking whether array[y+1][x] is equal to #, do something if it is and stop the loop, otherwise increment y. First I wrote it without the & before lavirint and it gave me an error that it can't compare a pointer and an int, which got me confused cause "#" shouldn't be an int?
The problem is the first condition in the loop never happens although it should, and the loop stops when
y==n
Maybe I'm just stupid and overlooked something but I would really appreciate a solution to this.
char lavirint[500][500];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%c", &lavirint[i][j]);
}
}
bool n_povecava = true;
...
while(n_povecava)
{
if(&lavirint[y+1][x] == "#" || y==n)
{
k--;
m_povecava = true;
n_povecava = false;
}
else
y++;
}
"#" is a string literal of type const char[2] and decays to const char*.
You need '#' which is a character:
if (lavirint[y+1][x] == '#' || ... )
Related
https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/
In this Leetcode question, I tried to do it without using the concept of a stack. But according to the answer, I get the loop is not getting completed, why is that the case here?
class Solution {
public:
string removeDuplicates(string s) {
for (int i = 0; i<s.length(); i++) {
if(s[i] == s[i+1]){
s.erase(i,2);
i=0;
}
}
return s;
}
};
This is the error I am getting:
Your loop boundary, i < s.length(), is wrong since it'll let s[i + 1] access the string out of bounds*.
You need to reset i when a match is found, which you do, but it's followed by i++ directly, so it will never find a match at s[0] == s[1] again.
Fixed:
string removeDuplicates(string s) {
for (unsigned i = 0; i + 1 < s.length();) { // corrected loop bounds
if (s[i] == s[i + 1]) {
s.erase(i, 2);
i = 0;
} else ++i; // only add 1 if no match is found
}
return s;
}
* The out of bounds access will really access the terminating \0 (since C++11, undefined behavior before that), but it's unnecessary since you can't erase it anyway.
A somewhat quicker version would be to not reset i to 0, but to continue searching at the current position. You may also use std::adjacent_find to simplify the algorithm:
string removeDuplicates(string s) {
for(auto it = s.begin(); (it = std::adjacent_find(it, s.end())) != s.end();) {
it = s.erase(it, it + 2);
if(it != s.begin()) --it;
}
return s;
}
The main problem of this for loop
for (int i = 0; i<s.length(); i++) {
if(s[i] == s[i+1]){
s.erase(i,2);
i=0;
}
}
is that after erasing two adjacent elements the variable i is set to 0 within the if statement and then at once is incremented in the for statement. So in the next iteration of the loop the variable i is equal to 1.
Consider the following string
"abba'
after erasing "bb" the string becomes equal to "aa" but after that the variable i is equal to 1 and in the next iteration of the loop you are comparing s[1] and s[2] that are 'a' and '\0'.
Rewrite the loop at least the following way
for ( std::string::size_type i = 0; i < s.length(); )
{
if ( s[i] == s[i+1] )
{
s.erase(i,2);
i=0;
}
else
{
++i;
}
}
Pay attention to that according to the C++ Standard s[s.length()] is equal to '\0'. So you may use the comparison s[i] == s[i+1]. According to the assignment in the provided link the string contains only low case letters.
I'm trying to make a program which modifies words in a specific manner:
It should first check the ending of the words and then proceed to modify them. I won't explain it in detail, because it doesn't make much sense in English.
I've written the following:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Por favor, introduzca los gentilicios separados por la tecla enter, para finalizar, escriba OK" << '\n';
string name[10];
string place[10];
for (int i(0); (i < 10); i++)
{
getline(cin, name[i]);
if (name[i] == "OK") //Error here
break;
}
for (int i(0); (i < 10); i++)
{
place[i] = name[i];
if (name[i][name[i].length() - 1] == 'c')
{
if (name[i][name[i].length()] == 'a' || (name[i][name[i].length()] == 'o') || (name[i][name[i].length()] == 'u'))
place[i][place[i].length() - 1] = 'q';
place[i][place[i].length()] = 'u';
place[i] = place[i] + "istan";
}
else if (name[i][name[i].length()] == 'a' || name[i][name[i].length()] == 'e' || name[i][name[i].length()] == 'i' || name[i][name[i].length()] == 'o' || name[i][name[i].length()] == 'u')
{
place[i][place[i].length()] = 'i';
place[i] = place[i] + "stan";
}
if (name[i][name[i].length()] == 's')
place[i] = place[i] + "tan";
else {
place[i] = place[i] + "istan";
}
place[i][0] = toupper(place[i][0]);
}
for (int i(0); (i < 10); i++)
{
cout << place[i] << '\n';
}
return 0;
}
Now I'm getting the error "String subscript out of range" . I would like to know where is the error exactly. I know it prompts when I write "OK", at line "18".
The condition i <= sizeof(name). sizeof(name) returns the size of the array in bytes, not the number of elements in it. Even if it returned the number of elements, <= is wrong and would cause an out-of-bounds access (should be <).
To loop through all elements in an array, you can use the range-based for-loop:
for(auto& n : name)
{
getline(cin, n);
if (n == "OK")
break;
}
Or to do it the right way with the C-style for-loop:
for (int i(0); i < sizeof(name)/sizeof(name[0]; i++)
{
…
}
Here:
for (int i(0); (i <= sizeof(name)); i++)
sizeof(name) is the size in bytes of the array, which as it is an array of std::string is effectively meaningless. If you want to iterate over 10 items, simply say so (note also that less-than-or-equals is also wrong here):
for (int i = 0; i < 10; i++)
And here:
getline(cin, name[i]);
whenever you perform input you must check the return value of the input function and handle any errors:
if( ! getline(cin, name[i]) ) {
// handle error somehow
}
And here:
string * p;
you do not want to be dealing with pointers to strings. If you want to access the contents of a string, you use operator[] or other string member functions on the string.
std::strings are not like cstrings. You can just grab a part of them using a std::string*. When you do
*(p+ (name[i].length()-2))
You actually say advance the address stored in p by name[i].length()-2 amount and access that string. If you go past the end of the name array then that is undefined behavior. If not you still haver a std::string which cannot be compared with a char. If you want to check if the string ends with "ca" then you can just use
if (name[i].substr(name[i].size() - 2) == "ca")
You're last loop is doing something quite funky. There's no need to go that far. You can just do something like:
if (name[i][name[i].length - 2] == 'c')
To compare the next to last character with c. And a very similar test to compare the last one with a.
To clarify why what you're doing is not OK, you first get p as a pointer to a string to the current element. Then you do some pointer arithmetic p + (name[i].length - 2), which still results in a pointer to a string. Finally, you dereference this, resulting in a string. Which you can't compare to a char. Moreover, the pointer was to some arbitrary address in memory, so the dereference would produce a string with very bad data in it. Quite arbitrary, one might say. If you tried to work with it you'd break your program
You seem to be working with the string as one would with a C-like string, a char*. The two are not the same, even though they represent the same concepts. A C++ string, usually, has a size field, and a char* pointer inside it, as well as a bunch of other logic to make working with it a char-m.
Because you aren't comparing against a specific char in the string, you're comparing against a string.
Considering the following bit of code:
*(p + (name[i].length() - 2))
This evaluates to a string because you are taking p (a string*) and concatenating a char to it. This means it's still a string (even though it's a one-character string), thus the other side of the equation won't be comparable to it.
What you need here instead is this:
if (name[i][name[i].length() - 2] == 'c')
Since name[i] is already a string, we can just get the char from it using the code above. This does return char, so it's comparable. This also allows you to get rid of the whole string* bit as it is not needed.
First, (i <= sizeof(name)) is wrong, it should be i < sizeof(name) / sizeof(*name). sizeof(array) return the size of array in bytes, you need to divide the size of an array's element to actually get the maximum element count of an array. If you find that complicated then use std::vector:
vector<string> name(10); //a vector of size 10
for (size_t i = 0; i < name.size(); i++) //name.size(), simple
Secondly, you need to keep track of how many strings in your name array. Or you need to check if name[i] == "OK" then break the second loop (similar to the first loop). name[i] after "OK" are invalid.
Thirdly, don't use *(p+ (name[i].length()-2)). If you want the second last character of name[i], you can write it as name[i][name[i].size()-2] or name[i].end()[-2] or end(name[i])[-2]
If you want to check if the word ends in "ca", then you can use substr:
if (name[i].substr(name[i].size() - 2) == "ca")
{
//...
}
I have a program where I want to update a variable from a string. The function will read in a string, find if it is addition, subtraction, etc. and then add it to the variable. The function is this:
using namespace std;
struct variable{
string name;
int value;
};
void update_varabile(string line, vector<variable> & v)
{
char c = line[0]; //variable to be updated
string b;
char d[0];
int flag = 0; //counter
int a = 0;
int temp_value = 0;
int perm_value = 0;
for (int i = 0; i < v.size(); i++) {
if (c == v[i].name[0]) {
flag = 1;
temp_value = v[i].value;
break;
}
}
if (flag == 1) { //variable is present
for (int i = 0; i< line.size(); i++) {
if (line[i] == '+'|| line[i] =='-'|| line[i] == '*'|| line[i] =='/') {
b[0] = line[i+1]; //assuming the integer is between 0 and 9
d[0] = b[0];
a = atoi (d);
if (line [i] == '+') {
perm_value = temp_value + a;
} else if (line [i] == '-') {
perm_value = temp_value - a;
} else if (line [i] == '*') {
perm_value = temp_value * a;
} else if (line [i] == '/') {
perm_value = temp_value / a;
}
}
}
for (int i = 0; i < v.size(); i++) {
if (v[i].name[0] == 'c') {
v[i].value = perm_value;
break;
}
}
}
}
The call in main looks like this:
int main()
{
variable a;
int val = 0;
string up = "c=c+2";
string f = "c";
vector<variable> q;
a.name = f;
a.value = val;
q.push_back(a);
update_varabile(up, q);
return 0;
}
However, when I run the code, I get this error message:
Assertion failed: ((m_->valid == LIFE_MUTEX) && (m_->busy > 0)), file C:/crossdev/src/winpthreads-git20141130/src/mutex.c, line 57
Process returned 1 (0x1) execution time : 0.014 s
Press any key to continue.
I have run the debugger line by line and it shows that the function properly executes. I have also tried to look for that C:/ file on my computer and it doesn't exist. Not sure why this isn't working.
First thing first, get rid of all the breaks. Only place breaks should be used in C++ is at the end of each case statement. Makes near impossible to read code with a bunch of breaks, because I have to go down and figure out what each break is there and why. If you need to get out of a for loop early, then use a while loop. you don't need breaks at the end of if and else statements because they cause the program to leave a function early, your if and else statements will naturally skip over if you are using if, else if, and else condition formatting.
Now having said that, you need to break down better what you are trying to do.
example you get a string value like this.
2+3+4-5+6
Your program is going to read from left to right. I am assuming you want it to take the first value which is two and then add three to it then four and so on and so fourth.
The way to do this is first parse the string for int values and then parse the addition and subtraction values. In other words read the int values out of the string untill you hit a value that is not between 0 and 9. Then see if that non-numerical value is an operator you are looking for. This way your program wont trip up on a value like 2555 and 2.
IE
//intValueHolder is a string.
while(i < line.size() && line[i] >= '0' && line[i] <= '9' ) {
intValueHolder.push_back(string[i]);
}
Then when you hit a '+' or something like that put the char value through a case statements. and don't forget to add a default value at the end to account for garbage input like 'a'. You may want to hold the value just incase you need to get your left side value first before you can get your right side value. But it sounded like you start out with a left side value so you really only need to find right and which operator it needs. I'm not going to rewrite your program because this looks like an assignment for school. But I will point you in the right direction. Let me know, if I was off on understanding your question.
You may also want to look into using queues for this, if you are not being restricted to just strings and vectors.
Consider the following for loop.
char temp[100];
char *str = "abab";
int i, j;
for (i = 0, j = 0; temp[i] = str[j];j++)
{
if (str[j] == temp[i])
i++;
else
i--;
}
It does not have terminating condition but still it manages to terminates after traversing "str".
Please explain.
The assignment expression temp[i] = str[j] has a value, which is the value that was assigned.
Since str is \0 terminated (character value 0), when the loop reaches it and assigns it to temp, the expression evaluates to 0. And the loop condition becomes false.
The loop does have a terminating condition, namely
temp[i] = str[j]
As the value of that is str[j], the loop condition boils down to
for (j = 0; str[j]; j++)
This certainly traverses str exactly once since str[j] evaluates to false in this context if and only if str[j] == '\0'. '\0' is a special character that terminates all string literals and is used to terminate C style strings.
In the "real world", i.e. outside of toy programs, you should avoid "clever" code like this, even if it works.
Also note that the conversion from string literals to char* is deprecated and that every attempt to modify a string literal invokes undefined behavior. Use
const char *str = "abab";
instead.
The condition is temp[i] = str[j]. That assigns and returns the assigned value. Therefore it will be evaluated to true for everything different to \0 and false, when the terminating \0 has been reached.
#include <iostream>
using namespace std;
int main()
{
char temp[100];
const char *str = "abab";
int i, j;
for (i = 0, j = 0; temp[i] = str[j]; j++)
{
if (str[j] == temp[i])
i++;
else
i--;
}
cout << (temp[4] ? "true" : "false") << endl;
}
Printing shows that the condition of the last iteration evaluates to false because it's zero ('\0' as end of string).
from the looks of it, the loop run it course as its scan the whole word "abab" and the condition for the loop to end is str = temp, the final output of those variables are 4 = 4
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()