Occasional unhandled exception with atoi(string.c_str()) Updated - c++

UPDATE
I thought stoi(string) solved it, but it only worked for a little while.
I have added the code for splitString and decrypt below.
I occasionally get unhandled exceptions with atoi() using the supposable same value.
My code looks like this:
ifstream myfile ("Save.sav");
string line = "";
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
}
myfile.close();
line = StaticFunctions::decrypt(line);
}
vector<string> splitString = StaticFunctions::splitString(line, 's');
return atoi(splitString[0].c_str());
So what it does is reading a savefile, then it decrypts it and then it splits the string by every 's'. When I'm debugging, the savefile is always the same and the first value is 3.
This work sometimes, maybe every 10 attempt. So every 9 out of 10 attempts I get unhandled exception at ... at memory location.
Monitoring the converted value shows it always returns 3 and then the application doesn't crash until I start the game which is a bit further in the code.
If I remove the atoi and just return 3 the application works fine.
I've tried strtod but it didn't help.
Thanks,
Markus
SplitString code:
vector<string> StaticFunctions::splitString(string str, char splitByThis)
{
vector<string> tempVector;
unsigned int pos = str.find(splitByThis);
unsigned int initialPos = 0;
// Decompose statement
while( pos != std::string::npos ) {
tempVector.push_back(str.substr( initialPos, pos - initialPos + 1 ) );
initialPos = pos + 1;
pos = str.find(splitByThis, initialPos );
}
// Add the last one
tempVector.push_back(str.substr(initialPos, std::min(pos, str.size()) - initialPos + 1));
return tempVector;
}
Decrypt code (very simple):
string StaticFunctions::decrypt(string decryptThis)
{
for(int x = 0; x < decryptThis.length(); x++)
{
switch(decryptThis[x])
{
case '*':
{
decryptThis[x] = '0';
break;
}
case '?':
{
decryptThis[x] = '1';
break;
}
case '!':
{
decryptThis[x] = '2';
break;
}
case '=':
{
decryptThis[x] = '3';
break;
}
case '#':
{
decryptThis[x] = '4';
break;
}
case '^':
{
decryptThis[x] = '5';
break;
}
case '%':
{
decryptThis[x] = '6';
break;
}
case '+':
{
decryptThis[x] = '7';
break;
}
case '-':
{
decryptThis[x] = '8';
break;
}
case '"':
{
decryptThis[x] = '9';
break;
}
}
}
return decryptThis;
}

Try use strtol instead
strtol (splitString[0].c_str(),NULL,10);

stoi(string) instead of atoi(string.c_str()) solved it.
UPDATE:
It did not solve it.

Related

Brainfuck interpreter strange output

I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.
In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).
char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;
MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.
while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '\0') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}
When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: ┼ (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.
There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells[] array.
There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.
Try something more like this instead:
static const int maxCells = 65536;
class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};
__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}
char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}
void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();
memset(cells, 0, maxCells);
cellp = 0;
const char* start = commands.c_str();
const char* p = start;
while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;
case '<':
--cellp;
break;
case '+':
cellData()++;
break;
case '-':
cellData()--;
break;
case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}
case ',':
{
char ch;
if (input.Length() == 0) {
ch = '\0';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}
case '[':
{
if (cellData() == '\0')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
case ']':
{
if (cellData() != '\0')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}
++p;
}
ShowMessage(cellp);
}
void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}

c++ The evaluation of expression. How to exit the while loop?

I use stack to evaluate an expression.
The most important function is below:
double Expression_Eval()
{
SeqStack<char,100> OPTR;
SeqStack<double,100> OPND;
OPTR.Push('#');
char ch;
ch=getchar();
while (ch!='#' || OPTR.GetTop()!='#')
{
if (!InOPTR(ch))
{
int n=ch-'0';
double num=(double)n;
OPND.Push(num);
ch=getchar();
}
else
{
char pre_op=OPTR.GetTop();
switch (Precede(pre_op, ch))
{
case '<': OPTR.Push(ch);
ch=getchar();
break;
case '=': OPTR.Pop();
ch=getchar();
break;
case '>': double b=OPND.Pop();
double a=OPND.Pop();
pre_op=OPTR.Pop();
OPND.Push(Operate(a, pre_op, b));
ch=getchar();
break;
}
}
}
return OPND.GetTop();
}
Then, when I input 8/(5-3)#, it will not print the result.
I think the loop termination condition ch!='#' || OPTR.GetTop()!='#' is wrong.
When I press Enter, getchar() get the last char is CR but not #.
But, I don't know how to revise it to make my program work.
The other part of my program is below:
#include<iostream>
using namespace std;
template<typename DataType,int StackSize>
class SeqStack
{
private:
DataType data[StackSize];
int top;
public:
SeqStack()
{ top=-1; }
~SeqStack() {}
void Push(DataType x)
{
if(top == StackSize-1)
throw "error";
data[++top]=x;
}
DataType Pop()
{
if(top == -1)
throw "error";
DataType x=data[top--];
return x;
}
DataType GetTop()
{
if(top != -1)
return data[top];
else
cout<<"error";
}
};
bool InOPTR(char ch)
{
if( (ch>='(' && ch<='+') || ch=='-' || ch=='/' )
{
return true;
}else{
return false;
}
}
char Precede(char op1, char op2)
{
char pri[7][7]={ {'>','>','<','<','<','>','>'}
, {'>','>','<','<','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'<','<','<','<','<','=','#'}
, {'>','>','>','>','#','>','>'}
, {'<','<','<','<','<','#','='} };
int m,n;
switch(op1)
{
case '+': m=0;break;
case '-': m=1;break;
case '*': m=2;break;
case '/': m=3;break;
case '(': m=4;break;
case ')': m=5;break;
case '#': m=6;break;
}
switch(op2)
{
case '+': n=0;break;
case '-': n=1;break;
case '*': n=2;break;
case '/': n=3;break;
case '(': n=4;break;
case ')': n=5;break;
case '#': n=6;break;
}
return pri[m][n];
}
double Operate(double a, char op, double b)
{
double result;
switch(op)
{
case '+': result=a+b; break;
case '-': result=a-b; break;
case '*': result=a*b; break;
case '/': result=a/b; break;
}
return result;
}
int main()
{
double r=Expression_Eval();
cout<<r<<endl;
return 0;
}
Problem seem to be that '#' is considered a number, but it should be considered an operation:
Use:
bool InOPTR(char ch) {
if ((ch >= '(' && ch <= '+') || ch == '-' || ch == '/' || ch=='#'){
return true;
}
else {
return false;
}
}
Note that '#' is ASCII 64 which is not covered in the ranage '(' to '+' [40-43]
Hope this helps.
You need to consume carriage return or newline character after getchar(); which comes into play when you press enter button.
One trick is as below.
ch=getchar();
getchar(); //this getchar to consume CR.
since you have used ch = getchar() many times you have to use above solution at many places.
Better solution to this problem will be to enter string instead of entering single character using getchar()...
Hope you got what I am trying to say...

Go word-by-word through a text file and replace certain words

My intended program is simple: Take each word of a text file and replace it with asterisks if it's a swear word. For instance, if the text file was "Hello world, bitch" then it would be modified to "Hello world, *****".
I have the tool for taking a word as a string and replacing it with asterisks if needed. I need help setting up the main part of my program because I get confused with all the fstream stuff. Should I instead make a new file with the replaced words and then overwrite the previous file?
#include <iostream>
#include <string>
#include <fstream>
const char* BANNED_WORDS[] = {"fuck", "shit", "bitch", "ass", "damn"};
void filter_word(std::string&);
void to_lower_case(std::string&);
int main (int argc, char* const argv[]) {
return 0;
}
void filter_word(std::string& word) {
std::string wordCopy = word;
to_lower_case(wordCopy);
for (int k = 0; k < sizeof(BANNED_WORDS)/sizeof(const char*); ++k)
if (wordCopy == BANNED_WORDS[k])
word.replace(word.begin(), word.end(), word.size(), '*');
}
void to_lower_case(std::string& word) {
for (std::string::iterator it = word.begin(); it != word.end(); ++it) {
switch (*it) {
case 'A': *it = 'a';
case 'B': *it = 'b';
case 'C': *it = 'c';
case 'D': *it = 'd';
case 'E': *it = 'e';
case 'F': *it = 'f';
case 'G': *it = 'g';
case 'H': *it = 'h';
case 'I': *it = 'i';
case 'J': *it = 'j';
case 'K': *it = 'k';
case 'L': *it = 'l';
case 'M': *it = 'm';
case 'N': *it = 'n';
case 'O': *it = 'o';
case 'P': *it = 'p';
case 'Q': *it = 'q';
case 'R': *it = 'r';
case 'S': *it = 's';
case 'T': *it = 't';
case 'U': *it = 'u';
case 'V': *it = 'v';
case 'W': *it = 'w';
case 'X': *it = 'x';
case 'Y': *it = 'y';
case 'Z': *it = 'z';
}
}
}
The usual solution to modifying a file is to generate a new
file, then delete the old and rename the new. In your case,
because your replacement text has exactly the same length as
your new text, you can do it in place, with something like:
std::fstream file( fileName, ios_base::in | ios_base::out );
if ( !file.is_open() ) {
// put error handling here...
std::string word;
std::fstream::pos_type startOfWord;
while ( file.peek() != std::fstream::traits::eof() ) {
if ( ::isalpha( file.peek() ) ) {
if ( word.empty() ) {
startOfWord = file.tellg();
}
word += file.get();
} else {
if ( !word.empty() ) {
if ( std::find_if( banned.begin(), banned.end(), CaseInsensitiveCompare() ) ) {
file.seekp( startOfWord );
file.write( std::string( word.size(), '*').c_str(), word.size() );
}
word.clear();
}
file.get();
}
}
with:
struct CaseInsensitiveCompare
{
bool operator()( unsigned char lhs, unsigned char rhs ) const
{
return ::tolower( lhs ) == ::tolower( rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return lhs.size() == rhs.size()
&& std::equal( lhs.begin(), lhs.end(), rhs.begin(), *this )
}
};
The tellg and seekp probably aren't the most efficient
operations around, but if the file is large, and you don't have
to seek too often, it may still be more efficient than writing
a completely new file. Of course, if efficiency is an issue,
you might want to consider mmap, and doing the job directly in
memory. That would certainly be the most efficient, and
probably the easiest to code as well. But it would be platform
dependent, and would require extra effort to handle files larger
than your available address space.
Also, for the future (since there is a standard tolower that
you can use), when doing code translation (which is really what
to_lower_case does), use a table. It's much simpler and
faster:
char
to_lower_case( char ch )
{
char translationTable[] =
{
// ...
};
return translationTable[static_cast<unsigned char>( ch )];
}
If you don't want your code to be dependent on the encoding, you
can use dynamic initialization:
if ( !initialized ) {
for ( int i = 0; i <= UCHAR_MAX; ++ i ) {
translationTable[i] = i;
}
static char const from[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static char const to[] = "abcdefghijklmnopqrstuvwxyz";
for ( int i = 0; i != sizeof(from); ++ i ) {
translationTable[from[i]] = to[i];
}
}
This is not a good idea for things like tolower, however;
you would have to know all of the possible upper case
characters, which in turn depends on the encoding. (The
functions in <ctype.h> do do something like this. And
redefine the translation table each time you change locale.) It
can be useful for other types of mappings.
I think you need a code to read file word by word and replace if the word is one of BANNED_WORDS
So here is a solution for main():
int main()
{
std::vector <std::string> words; // Vector to hold our words we read in.
std::string str; // Temp string to
std::cout << "Read from a file!" << std::endl;
std::ifstream fin("thisfile.txt"); // Open it up!
while (fin >> str) // Will read up to eof() and stop at every
{ // whitespace it hits. (like spaces!)
words.push_back(str);
}
fin.close(); // Close that file!
std::ofstream fout("temp.txt"); // open temp file
for (int i = 0; i < words.size(); ++i)
{ // replace all words and add it to temp file
filter_word(words.at(i));
fout<<words.at(i) << endl;
}
// Add code for replace the file
return 0;
}
And for to_lower_case() you can use
#include <ctype.h>
// ...
*it = tolower(*it);
As suggested by Paul Evans
Hope this will help you

"Illegal case" when using special symbols in case in c++

I have some problem, when I use special char case in c++. I try use '{' but it's over with error to.
Visual Studio 2010.
Here is my code.
for (int i = 0; i < inputString.length(); i++)
{
switch(inputString[i])
case '{':
nowChar = inputString[i];
nowCaret = i;
break;
case '[':
nowChar = inputString[i];
nowCaret = i;
break;
case '(':
nowChar = inputString[i];
nowCaret = i;
break;
}
How I can remove these errors? I really don't have any idea about it.
You need to open and end your switch with braces.
switch() {
// ...
}
You might have just forgot the brace for the switch statement. Btw, it will be better to have default in a switch statement.
for (int i = 0; i < inputString.length(); i++)
{
switch(inputString[i]) {
case '{':
nowChar = inputString[i];
nowCaret = i;
break;
case '[':
nowChar = inputString[i];
nowCaret = i;
break;
case '(':
nowChar = inputString[i];
nowCaret = i;
break;
default:
break;
}
}
You forgot to use { and } around the cases:
switch(inputString[i])
{ //<------------------------------ this
case '{':
nowChar = inputString[i];
nowCaret = i;
break;
case '[':
nowChar = inputString[i];
nowCaret = i;
break;
case '(':
nowChar = inputString[i];
nowCaret = i;
break;
} //<------------------------------- and this
A switch block starts with { when it has multiple cases. If it has just one case, then { and } are not mandatory.
switch(i)
case 0 :
// code
break;
Here { and } are not mandatory.

Returning a formatted string from a time structure

I wrote a little structure for getting certain time information. This structure is a helper,
for my logging class im planning to write. Here is the code:
struct UTime
{
char Month [4];
char DayOfMonth [3];
char DayOfWeek [4];
char Year [5];
char Time [9];
char Full [25];
UTime()
{
this->refresh();
}
void refresh()
{
char TimeBuffer[26] = {};
time_t RawTime = 0;
time(&RawTime);
ctime_s(TimeBuffer, 26*sizeof(char), &RawTime);
this->DayOfWeek[0] = TimeBuffer[0];
this->DayOfWeek[1] = TimeBuffer[1];
this->DayOfWeek[2] = TimeBuffer[2];
this->DayOfWeek[3] = 0;
this->Month[0] = TimeBuffer[4];
this->Month[1] = TimeBuffer[5];
this->Month[2] = TimeBuffer[6];
this->Month[3] = 0;
this->DayOfMonth[0] = TimeBuffer[8];
this->DayOfMonth[1] = TimeBuffer[9];
this->DayOfMonth[2] = 0;
this->Time[0] = TimeBuffer[11];
this->Time[1] = TimeBuffer[12];
this->Time[2] = TimeBuffer[13];
this->Time[3] = TimeBuffer[14];
this->Time[4] = TimeBuffer[15];
this->Time[5] = TimeBuffer[16];
this->Time[6] = TimeBuffer[17];
this->Time[7] = TimeBuffer[18];
this->Time[8] = 0;
this->Year[0] = TimeBuffer[20];
this->Year[1] = TimeBuffer[21];
this->Year[2] = TimeBuffer[22];
this->Year[3] = TimeBuffer[23];
this->Year[4] = 0;
memcpy(this->Full, TimeBuffer, 25);
this->Full[24] = 0;
}
}; // struct UTime;
Now Id like to add a function wich returns a formatted version of the time information.
For example:
std::string formatted = utime.get(Year, Month)
This function should return something like: "2011 Nov", or another example:
std::string formated = utime.get(DayOfWeek, Time);
This function should return something like: "Mon 20:43:24". Can anyone please point me in the most effecient way to do this? Im just not sure about effeciency because in a logger this function might get called alot. Thank you very much.
You can use strftime. It supports lots of format
std::string utime::get(char* format) {
std::string formatted;
formatted.reserve(30);
for( ; *format!='\0'; ++format) {
if (*format != '%')
formatted.append(*format);
else {
++format;
switch (*format) {
case 'a': formatted.append(DayOfWeek); break;
case 'b': formatted.append(Month); break;
case 'd': formatted.append(DayOfMonth); break;
case 'H': formatted.append(Time, 2); break;
case 'M': formatted.append(Time+3, 2); break;
case 'S': formatted.append(Time+6, 2); break;
case 'x': formatted.append(Month);
formatted.append(' ');
formatted.append(DayOfMonth);
formatted.append(' ');
formatted.append(Year);
break;
case 'X': formatted.append(Time); break;
case 'y': formatted.append(Year+2); break;
case 'Y': formatted.append(Year); break;
case '%': formatted.append('%'); break;
default: throw std::logic_error("Unsupported string format");
};
}
}
return formatted;
}
This should be fairly fast since it reserves a fair amount of space, and simply appends chacters to the end of the already allocated buffer most of the time. I highly recommend matching a standard formatting scheme like strftime as parapura rajkumar suggested.