Convert char to string doesn't work fine C++ - c++

Well I have that code:
for (int x = 0; x<(worldWidth-1); x++) {
for (int y = 0; y<(worldHeight-1); y++) {
sf::Texture texture;
if (!texture.loadFromFile("images/blocks/" + ruta(mapa[y][x]) + ".png"))
return -1;
sf::RectangleShape rectCaja(sf::Vector2f(16, 16));
rectCaja.setPosition(sf::Vector2f(x*16, y*16));
rectCaja.setTexture(&texture);
window.draw(rectCaja);
}
}
That prints boxes (of 16*16 pixels), that are "blocks" in a game the problem is that it doesn't print any block, it crashes directly I don't know why :/
I know (by consoles tests) that array "mapa" isn't wrong... So the only explanation that I have is that ruta function doesn't work fine... (I have tested it with a std::string var = "dirt"; and it works fine)... :/
std::string ruta(char id) {
if (id=='0') return "air";
if (id=='1') return "stone";
if (id=='2') return "dirt";
if (id=='3') return "grass_side";
if (id=='4') return "coal_ore";
}
If somebody wants the hold code there is: http://pastebin.com/5jvbzwkR
Thanks! :P

Only a guess because there isn't enough information to be sure but this might be the answer
std::string ruta(int id) {
if (id==0) return "air";
if (id==1) return "stone";
if (id==2) return "dirt";
if (id==3) return "grass_side";
if (id==4) return "coal_ore";
}
In C++ you have to be careful about types, and understand the difference, for instance, between an int and a char. A char with value '3' is not the same an an int with value 3.

One issue I immediately see is that you're comparing an int to a char. Consider:
std::string ruta(int id)
{
switch( id )
{
case 0:
return "air";
case 1:
return "stone";
case 2:
return "dirt";
case 3:
return "grass_side";
case 4:
return "coal_ore";
}
}

Here is your scene declaration:
int scene[worldWidth][worldHeight];
Here is how you fill up your scene:
while (!finished) {
if (yPos >= topOfTheWorld) {
scene[xPos][yPos] = 1;
}
else if(yPos < topOfTheWorld) {
scene[xPos][yPos] = 0;
}
//etc...
}
Here is how you write into your mapa.txt:
std::ofstream output("mapa.txt");
for(int y=0;y<worldHeight;y++) {
for(int x=0;x<worldWidth;x++) {
output<<scene[x][y];
if(x<(worldWidth-1)){output<<",";}
}
if(y<(worldHeight-1)){output<<std::endl;}
}
Basically this all means that you are writing the numerical value 0 and 1 into your mapa.txt and not the character values '0' and '1'. Yet in your ruta function you compare with '0' and '1'. You should compare with 0 and 1 without the single quotes (').

Related

C++ std::set<string> Alphanumeric custom comparator

I'm solving a problem with a sorting non-redundant permutation of String Array.
For example, if input string is "8aC", then output should be order like {"Ca8","C8a", "aC8", "a8C", "8Ca", "9aC"}.I chose C++ data structure set because each time I insert the String into std:set, set is automatically sorted and eliminating redundancy. The output is fine.
But I WANT TO SORT SET IN DIFFERENT ALPHANUMERIC ORDER which is different from default alphanumeric sorting order. I want to customize the comparator of set the order priority like: upper case> lower case > digit.
I tried to customize comparator but it was quite frustrating. How can I customize the sorting order of the set? Here's my code.
set<string, StringCompare> setl;
for (i = 0; i < f; i++)
{
setl.insert(p[i]); //p is String Array. it has the information of permutation of String.
}
for (set<string>::iterator iter = setl.begin(); iter != setl.end(); ++iter)
cout << *iter << endl; //printing set items. it works fine.
struct StringCompare
{
bool operator () (const std::string s_left, const std::string s_right)
{
/*I want to use my character comparison function in here, but have no idea about that.
I'm not sure about that this is the right way to customize comparator either.*/
}
};
int compare_char(const char x, const char y)
{
if (char_type(x) == char_type(y))
{
return ( (int) x < (int) y) ? 1 : 0 ;
}
else return (char_type(x) > char_type(y)) ? 1 : 0;
}
int char_type(const char x)
{
int ascii = (int)x;
if (ascii >= 48 && ascii <= 57) // digit
{
return 1;
}
else if (ascii >= 97 && ascii <= 122) // lowercase
{
return 2;
}
else if (ascii >= 48 && ascii <= 57) // uppercase
{
return 3;
}
else
{
return 0;
}
}
You are almost there, but you should compare your string lexicographically.
I roughly added small changes to your code.
int char_type( const char x )
{
if ( isupper( x ) )
{
// upper case has the highest priority
return 0;
}
if ( islower( x ) )
{
return 1;
}
if ( isdigit( x ) )
{
// digit has the lowest priority
return 2;
}
// something else
return 3;
}
bool compare_char( const char x, const char y )
{
if ( char_type( x ) == char_type( y ) )
{
// same type so that we are going to compare characters
return ( x < y );
}
else
{
// different types
return char_type( x ) < char_type( y );
}
}
struct StringCompare
{
bool operator () ( const std::string& s_left, const std::string& s_right )
{
std::string::const_iterator iteLeft = s_left.begin();
std::string::const_iterator iteRight = s_right.begin();
// we are going to compare each character in strings
while ( iteLeft != s_left.end() && iteRight != s_right.end() )
{
if ( compare_char( *iteLeft, *iteRight ) )
{
return true;
}
if ( compare_char( *iteRight, *iteLeft ) )
{
return false;
}
++iteLeft;
++iteRight;
}
// either of strings reached the end.
if ( s_left.length() < s_right.length() )
{
return true;
}
// otherwise.
return false;
}
};
Your comparator is right. I would turn parameters to const ref like this
bool operator () (const std::string &s_left, const std::string &s_right)
and start by this simple implementation:
return s_left < s_right
This will give the default behaviour and give you confidence you are on the right track.
Then start comparing one char at the time with a for loop over the shorter between the length of the two strings. You can get chars out the string simply with the operator[] (e.g. s_left[i])
You're very nearly there with what you have.
In your comparison functor you are given two std::strings. What you need to do is to find the first position where the two strings differ. For that, you can use std::mismatch from the standard library. This returns a std::pair filled with iterators pointing to the first two elements that are different:
auto iterators = std::mismatch(std::begin(s_left), std::end(s_left),
std::begin(s_right), std::end(s_right));
Now, you can dereference the two iterators we've been given to get the characters:
char c_left = *iterators.first;
char c_right = *iterators.second;
You can pass those two characters to your compare_char function and it should all work :-)
Not absoloutely sure about this, but you may be able to use an enumerated class towards your advantage or an array and choose to read from certain indices in which ever order you like.
You can use one enumerated class to define the order you would like to output data in and another that contains the data to be outputed, then you can set a loop that keeps on looping to assign the value to the output in a permuted way!
namespace CustomeType
{
enum Outs { Ca8= 0,C8a, aC8, a8C, 8Ca, 9aC };
enum Order{1 = 0 , 2, 3 , 4 , 5};
void PlayCard(Outs input)
{
if (input == Ca8) // Enumerator is visible without qualification
{
string[] permuted;
permuted[0] = Outs[0];
permuted[1] = Outs[1];
permuted[2] = Outs[2];
permuted[3] = Outs[3];
permuted[4] = Outs[4];
}// else use a different order
else if (input == Ca8) // this might be much better
{
string[] permuted;
for(int i = 0; i<LessThanOutputLength; i++)
{
//use order 1 to assign values from Outs
}
}
}
}
This should work :
bool operator () (const std::string s_left, const std::string s_right)
{
for(int i = 0;i < s_left.size();i++){
if(isupper(s_left[i])){
if(isupper(s_right[i])) return s_left[i] < s_right[i];
else if(islower(s_right[i]) || isdigit(s_right[i]))return true;
}
else if(islower(s_left[i])){
if(islower(s_right[i])) return s_left[i] < s_right[i];
else if(isdigit(s_right[i])) return true;
else if(isupper(s_right[i])) return false;
}
else if(isdigit(s_left[i])){
if(isdigit(s_right[i])) return s_left[i] < s_right[i];
else if(islower(s_right[i]) || isupper(s_right[i])) return false;
}
}
}

Is there any functional difference between the following 2 code snippets?

Is there any functional difference between the following 2 code snippets?
bool ColorClass::setTo(int inRed, int inGreen, int inBlue)
{
amountRed = inRed;
amountGreen = inGreen;
amountBlue = inBlue;
return clipColor(amountRed, amountGreen, amountBlue);
}
bool ColorClass::setTo(int inRed, int inGreen, int inBlue)
{
amountRed = inRed;
amountGreen = inGreen;
amountBlue = inBlue;
if (clipColor(amountRed, amountGreen, amountBlue))
{
return true;
}
else
{
return false;
}
}
The functions the above code calls are defined below:
bool ColorClass::clipColor(int &checkRed, int &checkGreen, int &checkBlue)
{
int numClips = 0; //numClips is used to counter number of clips made
checkColorBounds(checkRed, numClips);
checkColorBounds(checkGreen, numClips );
checkColorBounds(checkBlue, numClips);
return (numClips != 0);
}
void ColorClass::checkColorBounds(int &color, int &clipCounter)
{
if(color > MAXCOLOR)
{
color = MAXCOLOR;
clipCounter++;
}
else if (color < MINCOLOR)
{
color = MINCOLOR;
clipCounter ++;
}
}
I tested both and gone through both, and I can't seem to notice anything functionally different.
I like the first one better, because it is much more succint and more efficient (avoids the if-else)
There're no any functional differences at all. Then use the 1st one.
KISS

Error: not all control paths return a value

I am writing two functions in a program to check if a string has an assigned numeric code to its structure array or if the given numeric code has an assigned string in the same structure array. Basically, if I only know one of the two, I can get the other. I wrote the following:
int PrimaryIndex::check_title_pos(std::string title) {
bool findPos = true;
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
} else {
return -1;
}
}
std::string PrimaryIndex::check_title_at_pos(int pos) {
bool findTitle = true;
if (findTitle) {
for (int p = 1; p <= 25; p++) {
if (my_list[p].tag == pos) {
return my_list[p].title;
}
}
} else {
return "No title retrievable from " + pos;
}
}
However, it says not all control paths have a return value. I thought the else {} statement would handle that but it's not. Likewise, I added default "return -1;" and "return "";" to the appropriate functions handling int and string, respectively. That just caused it to error out.
Any idea on how I can keep this code, as I'd like to think it works but cant test it, while giving my compiler happiness? I realize through other searches that it sees conditions that could otherwise end in no returning values but theoretically, if I am right, it should work fine. :|
Thanks
In the below snippet, if s iterates to 26 without the inner if ever evaluating to true then a return statement is never reached.
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
}

Searching first specified element in array

I'm trying to make function that has a loop that checks every member of an array made from boolean variables and exits when it finds the first "true" value.
That's what I have now:
bool solids[50];
int a,i;
//"equality" is a function that checks the equality between "a" and a defined value
solids[0] = equality(a,&value_1);
solids[1] = equality(a,&value_1);
solids[2] = equality(a,&value_1);
solids[3] = equality(a,&value_1);
for (i = 0; solids[i] != true; i++)
{
[...]
}
But I have no idea, what should I put into the loop?
My attempt was
for (i = 0; i <= 50; i++)
{
if (solids[i] == true)
{
return true;
break;
} else {
return false;
}
}
,that should return true after the first found true and return false if the array has no member with true value, but it doesn't seem to work in the code.
Is it wrong? If yes, what is the problem?
PS.: I may count the number of trues with a counter but that's not an optimal solve to the problem, since I just look for the FIRST true value and consequently, the program doesn't have to check all the 50 members. Needley to count, how many unnecesary steps should this solve would mean.
here's a short example usage of std::find() as advised by #chris:
bool find_element_in_array() {
bool solids[50];
int length;
/* ... do many operations, and keep length as the size of values inserted in solids */
bool* location = std::find(solids, length, true);
// if element is found return true
if (location != solids + length)
return true;
// else return false
return false;
}
Once you have solids correctly set (it looks like you're currently setting every value to the same thing), you can make a loop that exits on the first true like this:
for (i = 0; i < 50; i++)
{
if (solids[i] == true)
{
return true;
}
}
return false;
I'd also just move the declaration of i into the for loop body, since it's not used outside, but the above answers your question.
return immediately exits the function, so there is no need to break the loop after.
If it's sufficient to exit the function right after the search, you should write something like:
for (int i = 0; i < 50; i++) {
if (solids[i]) return true;
}
return false;
If you need to use the result of the search in the same function, use additional variable:
bool found = false;
for (int = 0; i < 50; i++) {
if (solids[i]) {
bool = true;
break;
}
}
if (found) { ...

arrays and functions

my assignment requires me to write a function that reads in a title and return the corresponding fee to the calling function. if the title is not in the list, return -1.0.
this is what i have got at the moment:
struct eventType
{
string title;
double fees;
};
eventType eventTable[10];
int findFees (string newTitle, string newFees)
{
int Index = 0;
int flag;
while (Index < 9) && (eventTable[Index].title != newTitle))
Index = Index + 1;
if (eventTable[Index].title == newTitle)
{
eventTable[Index].fees = newFees;
flag = 0;
}
else
flag = -1;
return flag;
}
is anything missing?
update
after looking at the advice u guys have given, i have adopted and changed the codes to:
double findFees (string title)
{
for (int Index = 0 ; Index < 10 ; Index++)
{
if (eventTable[Index].title == title)
{
return eventTable[Index].fees;
}
}
return -1.0;
}
I'm not sure if this is correct either but I do not need a new title or new fees since these values are to be found within eventTable, and return it.
corrections?
I don't want to give away the answer for you, but here are two things you should keep in mind:
When you have a conditional or a loop, you need to surround statements in { and } so that the compiler knows which statements go inside the loop.
Second, C++ is a type-safe language, meaning that if you are assigning variables to a value of a different type, your program won't compile, look through your code and see if you can find anything wrong on that front
It should be:
while (Index < 10)
And you said it should return the fee, but it returns 0 when found. (This is ok, since you are passing in the fee, why return it too?)
I would also change the signature of the function to be:
int findFees (const string &newTitle, const string &newFees)
and while you are at it, have it return a "bool" instead of a flag to denote success since:
if(findFees(blahTitle, blahFees))
sounds a lot better than:
if(findFees(blahTitle, blahFees) == 0)
when checking for whether the title is found.
It seems to me your function does not return the fees, as you described.
It looks like it updates the eventTable, changing the fee stored there, and returns a flag if the update was done successfully.
Please clarify. Do you want to find the fee stored in the eventTable and return it? Or do you want to update the eventTable with new data? Or a hybrid of both.
Still, for a noob, your code is well structured and reasonably well written.
You could simplfy it as so.
int flag = -1;
int Index = 0;
while(Index <= 9)
{
if(eventTable[Index].title == newTitle)
{
eventTable[Index].fees = newFees;
flag = 0
break;
}
}
return flag;
eventTable[Index].fees = newFees;
This won't work because fees is a double and newFees is a string. Also you didn't say anything about changing the fees, so I'm confused by that line.
If you want to return the fees of the item you found, you should just put return eventTable[Index].fees; at that point and change the return value of the function to float.
Your description (return the fee, or -1.0 if not found) does not match your code:
struct eventType
{
string title;
double fees;
};
eventType eventTable[10];
double findFees (string newTitle)
{
for (int Index = 0 ; Index < 10 ; Index++)
{
if (eventTable[Index].title == newTitle)
{
return eventTable[Index].fees;
}
}
return -1.0;
}
The only error I see is
while (Index < 9) && (eventTable[Index].title != newTitle))
should probably be:
while ((Index < 10) && (eventTable[Index].title != newTitle))
Note the missing '('. Otherwise you miss matching the last entry in the array.
I would probably write the function something like:
double findFees (const string& title, double newFee)
{
for (int i = 0; i < 10; i++)
{
if (eventTable[i].title == title)
{
eventTable[i].fees = newFee;
return newFee;
}
}
return -1.0;
}
This way you will not iterate through the entire array if you already found the item you where searching for.