I'm working on a mini-compiler and I reached the code generation level.
I want to store a string dynamically to the heap segment, so I wrote this C++ code (cg is the file I'm generating assembly code to) :
int length = strlen("abc");
cg << "\tori\t$a0,$0," << (length + 3) * 4 << endl; // reserve space for type + length + null + size
cg << "\tori\t$v0,$0,9" << endl;
cg << "\tsyscall" << endl;
increamentSP();
cg << "\tsw\t$v0,0($sp)" << endl;
cg << "\tori\t$t1,$0,1" << endl; // store the type
cg << "\tsw\t$t1,0($v0)" << endl;
cg << "\tori\t$t1,$0," << length << endl; // store the length
cg << "\tsw\t$t1," << 4 << "($v0)" << endl;
for (int i = 0; i < length; i++)
{
cg << "\tori\t$t1,$0," << (int)p->val[i] << endl; // store the char
cg << "\tsw\t$t1," << (2 + i) * 4 << "($v0)" << endl;
}
cg << "\tsw\t$0," << (2 + length) * 4 << "($v0)" << endl;
Basically, what I'm trying to do is :
First, I want to store a flag (1) referring that this type is a string to the first location.
Then, I want to store the size of my string to the second location.
After that, I want to store my strings chars to the next locations.
Finally, I want to store a null-terminating char to the last location.
My problem is that when I try to print my string using a code like this :
la $a0,8($t0)
ori $v0,$0,4
syscall
The result is that mips prints only the letter 'a', how can I print a string stored like this? or is there any better way to store my string?
p.s. I know I can use .asciiz in the .data segment, but the problem is that in my code I might edit the string, so I don't exactly know what my string would become.
Can any one help me with that?
Related
The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo
In this Book object I created a system to keep track of the time a book has been checked out... there is a tm* called dateCheckedOut to store the date that the book is checked out.
int Book::getHeldTime()
{
time_t now ;
time(&now);
tm* t = localtime(&now);
double difference = difftime(now, mktime(dateCheckedOut))/(60 * 60 * 24);
cout << dateCheckedOut->tm_mon << dateCheckedOut->tm_mday << dateCheckedOut->tm_year << endl; //prints out 231117, which is correct.
cout << t->tm_mon << t->tm_mday << t->tm_year << endl; //prints out 34117, which is also correct
cout << difftime(now, mktime(dateCheckedOut)) << endl; //prints out 0
cout << difference << endl; //prints out 0;
return (int)(difference); //returns 0
}
I am quite confused because I checked the date when its checked out and the date when it is loaded, both are correct, but the difftime function just returns 0. Is there anything that might cause this code to not work? Thank in advance!
P.S. dateCheckedOut only has tm_mday, tm_mon, and tm_year set to the correct value, the rest are all not set. Is that a problem?
so to give this context
I'm making a script generating the config files for some games I'm running.
I'm at this point just trying to get the script to generate the file and put it in the directory of said game. (this is still work in progress. and I don't have any way of getting user input. but first I need it to put it in the proper directory.)
in this example its minecraft.
but I can't find any posts on any forum or here on stackoverflow that works.
it might be because im missing the rest of the code as most people just give 3 lines of code.
point is I'm not experienced whit c++ as I have never used it.
so I'm hoping some one can help me fix it.
yes I added the full code I got so far as it probably is filled whit "shit" and a loot longer than what it needs to be so any help would be nice.
final note*
I'm using MS visual studio express 2013
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// comment
/*
multi
line
comment
*/
//locked
// server ip : string
string ip = "127.0.0.1";
//server port : integer 1-65534
string port = "25565";
//world name : string
string world = "world";
//amount of allowed players : integer 0-2147483647
string mxpla = "20";
//view distance : integer 3-15
string viedis = "10";
//trexture pack :string
string texpack = "";
//user defined
// world gen setting : string (only used whit CUSTOMIZED leveltype)
string genset = "";
// allow flight : boolean true or false
string alfly = "true";
// level type : string DEFAULT, FLAT, LARGEBIOMES, AMPLIFIED, CUSTOMIZED --> same as DEFAULT unless generator settings is filled out
string levtype = "DEFAULT";
// level seed : string
string levseed = "";
// max build hight : integrer 0-256
string mxbh = "256";
//spawn npc : boolean true or false
string snpc = "true";
// whitelist : boolean true or false
string wlist = "false";
//spawn animals : boolean true or false
string sanimal = "true";
// hardcore mode : boolean true or false
string hc = "false";
//online mode : boolean true or false
string onmo = "true";
// pvp mode : boolean true or false
string pvp = "false";
//server difficulity : integer 0-3 0 peaceful - 3 hard
string diff = "1";
// game mode : integer 0-3 0 survival, 1 creative, 2 adventure and 3 spectator (dont use 3 on the server side)
string gamemo = "0";
// spawn mobs : boolean true or false
string smob = "true";
//generate structures : boolean ture or false
string genstru = "true";
// mesage of the day : string
string motd = "test";
int main() {
ofstream outFile;
// output file
outFile.open("test.properties");
// file generator
outFile << "generator-settings=" << genset << endl
<< "level-name=" << world << endl
<< "allow-flight=" << alfly << endl
<< "server-port=" << port << endl
<< "level-type=" << levtype << endl
<< "level-seed=" << levseed << endl
<< "server-ip=" << ip << endl
<< "max-build-height=" << mxbh << endl
<< "spawn-npcs=" << snpc << endl
<< "white-list=" << wlist << endl
<< "spawn-animals=" << sanimal << endl
<< "hardcore=" << hc << endl
<< "texture-pack=" << texpack << endl
<< "online-mode=" << onmo << endl
<< "pvp=" << pvp << endl
<< "difficulty=" << diff << endl
<< "gamemode=" << gamemo << endl
<< "max-players=" << mxpla << endl
<< "spawn-monsters=" << smob << endl
<< "generate-structures=" << genstru << endl
<< "view-distance=" << viedis << endl
<< "motd=" << motd << endl;
outFile.close();
return 0;
}
The ofstream's open() method takes a full path, so you can specify it like that:
outFile.open("c:\\games\\minecraft\\test.properties");
If you want to create output file at any folder than in VS you should change working directory. Go in Solution properties -> Configuration properties -> Debugging -> Working directory and change the value there to your preferred path. For example write there C:\Games\minecraft
I was trying to make use of the new Shape Transformers and Interfaces of OpenCV3.0. Unfortunately it doesn't work as expected. To ensure not making any fancy warps and getting strange results cause of that reason I initialized a transformation where nothing at all should happen. But output of the transformation for a testpoint is always [0,0] and the warped image is always completley gray. Any suggestions what could be wrong are welcome.
int main(void){
Mat img1 = imread("C:\\opencv\\sources\\samples\\data\\graf1.png", IMREAD_GRAYSCALE);
std::vector<cv::Point2f> points1, testpoints;
vector<DMatch> good_matches;
Mat respic, resmat;
points1.push_back(Point(0, 0)); //Corners 800x600 pic
points1.push_back(Point(799, 0));
points1.push_back(Point(799, 599));
points1.push_back(Point(0, 599));
Mat pointmatrix1(points1);
good_matches.push_back(DMatch(0, 0, 0));
good_matches.push_back(DMatch(1, 1, 0));
good_matches.push_back(DMatch(2, 2, 0));
good_matches.push_back(DMatch(3, 3, 0));
testpoints.push_back(Point(250, 250));
Mat testpointsmat(testpoints);
// Apply TPS
Ptr<ThinPlateSplineShapeTransformer> mytps = createThinPlateSplineShapeTransformer(0);
mytps->estimateTransformation(pointmatrix1, pointmatrix1, good_matches); // Using same pointmatrix nothing should change in res
mytps->applyTransformation(testpointsmat, resmat);
cout << "pointmatrix1 = " << endl << " " << pointmatrix1 << endl << endl;
cout << "testpointsmat = " << endl << " " << testpointsmat << endl << endl;
cout << "resmat = " << endl << " " << resmat << endl << endl; //Always [0,0] ?
imshow("img1", img1); // Just to see if I have a good picture
mytps->warpImage(img1, respic);
imwrite("Tranformed.png", respic);
imshow("Tranformed", respic); //Always completley grey ?
waitKey(0);
return 0;
}
Don't ask me why but if I add this two lines it works.
// Apply TPS
transpose(pointmatrix1, pointmatrix1); // ADD
transpose(testpoints, testpoints); // ADD
Ptr<ThinPlateSplineShapeTransformer> mytps = createThinPlateSplineShapeTransformer(0);
Now There is something strange in source code here why cols and not rows.
by LBerger
i am making a project in clr windows form using c++ and im having problem in retrieving the data from the file in a template(vector) when the form is loaded. my form has the button to save the code which calls the save method in the class coded as below. pls suggest what should be the code to retrieve the file, thank you.here record isthe name of the vector.
int men_database::save(int count)
{ ofstream out;
out.open("MALE.txt",ios::out|ios::binary);
if(!out)
return -1;
else
{for(int i=0;i<count;i++)
{out<<'\n'<<record[i].getid();
out<<'\n'<<record[i].getname();
out<<'\n'<<record[i].getsize();
out<<'\n'<<record[i].getcolor();
out<<'\n'<<record[i].getprice();
out<<'\n'<<record[i].getpic();
out<<'\n'<<record[i].getwatch();
}
out.close();
}//else ends
return 1;}
Here is some basic code for reading/writing. Though you might find something better elsewhere. \n is used as delimiter. Each record should have 2 fields (in yours it is 7 fields). Each field must be single-line string. Ps, you get more attention with c++ tag on your question.
int main()
{
{
ofstream f("data.txt");
f << "id1" << endl;
f << "name1" << endl;
f << endl;
f << "id2" << endl;
f << "name2" << endl;
f << endl;
}
{
ifstream f("data.txt");
string id;
string name;
while (f)
{
f >> id;
f >> name;
if (!f) break;
cout << "id: " << id << endl;
cout << "name: " << name << endl;
cout << endl;
}
}
return 0;
}