I have code that is supposed to separate a string into 3 length sections:
ABCDEFG should be ABC DEF G
However, I have an extremely long string and I keep getting the
terminate called without an active exception
When I cut the length of the string down, it seems to work. Do I need more space? I thought when using a string I didn't have to worry about space.
int main ()
{
string code, default_Code, start_C;
default_Code = "TCAATGTAACGCGCTACCCGGAGCTCTGGGCCCAAATTTCATCCACT";
start_C = "AUG";
code = default_Code;
for (double j = 0; j < code.length(); j++) { //insert spacing here
code.insert(j += 3, 1, ' ');
}
cout << code;
return 0;
}
Think about the case when code.length() == 2. You're inserting a space somewhere over the string. I'm not sure but it would be okay if for(int j=0; j+3 < code.length(); j++).
This is some fairly confusing code. You are looping through a string and looping until you reach the end of the string. However, inside the loop you are not only modifying the string you are looping through, but you also change the loop variable when you say j += 3.
It happens to work for any string with a multiple of 3 letters, but you are not correctly handling other cases.
Here is a working example of the for loop that is a bit more clear it what it's doing:
// We skip 4 each time because we added a space.
for (int j = 3; j < code.length(); j += 4)
{
code.insert(j, 1, ' ');
}
You are using an extremely inefficient method to do such an operation. Every time you insert a space you are moving all the remaining part of the string forward and this means that the total number of operations you will need is in the order of o(n**2).
You can instead do this transormation with a single o(n) pass by using a read-write approach:
// input string is assumed to be non-empty
std::string new_string((old_string.size()*4-1)/3);
int writeptr = 0, count = 0;
for (int readptr=0,n=old_string.size(); readptr<n; readptr++) {
new_string[writeptr++] = old_string[readptr];
if (++count == 3) {
count = 0;
new_string[writeptr++] = ' ';
}
}
A similar algorithm can be written also to work "inplace" instead of creating a new string, simply you have to first enlarge the string and then work backward.
Note also that while it's true that for a string you don't need to care about allocation and deallocation still there are limits about the size of a string object (even if probably you are not hitting them... your version is so slow that it would take forever to get to that point on a modern computer).
Related
So I started learning C++ two weeks ago and I want to build a program that checks if a string is a palindrome or not.
I tried different ways including the str1==str2 method in the following way:
#include<iostream>
#include<string>
using namespace std;
string empty;
string word;
bool inverse(string word)
{
for (int i=0;i<=word.length();i++)
{
empty+=word[word.length()-i];
}
return empty==word;
}
int main()
{
cout<<inverse("civic");
}
The output is always 0
Second way: the str1.compare(str2) method
#include<iostream>
#include<string>
using namespace std;
string empty;
string word;
bool inverse(string word)
{
for (int i=0;i<=word.length();i++)
{empty+=word[word.length()-i];}
if (word.compare(empty))
return true;
else
return false;
}
int main()
{
if (inverse(word)==true)
cout<<"is a palindrome";
else
cout<<"is not a palindrome";
cout<<inverse("ano");
cout<<inverse("madam");
}
the output is always: is palindrome1 (with 1 or two ones at the end of "palindrome")
even if the string is not a palindrome.
please explain to me what mistakes I made and how I can correct them.
Also If I want to make my program handle a string that has white space in it, how can I do it?
There are a couple of problems
Your code is looping too many times. For example a word of three letters should loop three times, but your code loops for 4 (i=0, i=1, i=2, and i=3). To fix this you need to change the final condition to use < instead of <=.
You are computing the symmetrical index with the wrong formula. If for example you have a word of length three the letters be word[0], word[1] and word[2]. However your code uses length - i and for i=0 this will use word[3] that is outside the allowed limits for the word. You need to do the indexing using as formula length - 1 - i instead of length - i.
Both of these errors are quite common in programming and they're called "off-by-one" errors. Remember to always double-check the boundary conditions when you write code so that you can keep this kind of error away from your programs.
For first one you need to change
for (int i=0;i<=word.length();i++)
{empty+=word[word.length()-i];}
to this
for (int i=0;i<word.length();i++)
{empty+=word[word.length()-(i+1)];}
Your program's behavior will become undefined after this line:
for (int i = 0;i <= word.length(); i++)
empty += word[word.length() - i];
Since length is always one plus the last element (Since the first index is zero), when i is 0, then: word[word.length()] will give you the element after the last element, which is not possible and thus your program will invoke undefined behavior since C/C++... word[word.length()] is also possible when i itself becomes word.length(), so change <= (less than or equal to) to < (less than)
So, it should be:
for (int i = 0;i < word.length(); i++)
empty += word[word.length() - 1 - i];
I am trying to make an own simple string implementation in C++. My implementation is not \0 delimited, but uses the first element in my character array (the data structure I have chosen to implement the string) as the length of the string.
In essence, I have this as my data structure: typedef char * arrayString; and I have got the following as the implementation of some primal string manipulating routines:
#include "stdafx.h"
#include <iostream>
#include "new_string.h"
// Our string implementation will store the
// length of the string in the first byte of
// the string.
int getLength(const arrayString &s1) {
return s1[0] - '0';
}
void append_str(arrayString &s, char c) {
int length = getLength(s); // get the length of our current string
length++; // account for the new character
arrayString newString = new char[length]; // create a new heap allocated string
newString[0] = length;
// fill the string with the old contents
for (int counter = 1; counter < length; counter++) {
newString[counter] = s[counter];
}
// append the new character
newString[length - 1] = c;
delete[] s; // prevent a memory leak
s = newString;
}
void display(const arrayString &s1) {
int max = getLength(s1);
for (int counter = 1; counter <= max; counter++) {
std::cout << s1[counter];
}
}
void appendTest() {
arrayString a = new char[5];
a[0] = '5'; a[1] = 'f'; a[2] = 'o'; a[3] = 't'; a[4] = 'i';
append_str(a, 's');
display(a);
}
My issue is with the implementation of my function getLength(). I have tried to debug my program inside Visual Studio, and all seems nice and well in the beginning.
The first time getLength() is called, inside the append_str() function, it returns the correct value for the string length (5). When it get's called inside the display(), my own custom string displaying function (to prevent a bug with std::cout), it reads the value (6) correctly, but returns -42? What's going on?
NOTES
Ignore my comments in the code. It's purely educational and it's just me trying to see what level of commenting improves the code and what level reduces its quality.
In get_length(), I had to do first_element - '0' because otherwise, the function would return the ascii value of the arithmetic value inside. For instance, for decimal 6, it returned 54.
This is an educational endeavour, so if you see anything else worth commenting on, or fixing, by all means, let me know.
Since you are getting the length as return s1[0] - '0'; in getLength() you should set then length as newString[0] = length + '0'; instead of newString[0] = length;
As a side why are you storing the size of the string in the array? why not have some sort of integer member that you store the size in. A couple of bytes really isn't going to hurt and now you have a string that can be more than 256 characters long.
You are accessing your array out of bounds at couple of places.
In append_str
for (int counter = 1; counter < length; counter++) {
newString[counter] = s[counter];
}
In the example you presented, the starting string is "5foti" -- without the terminating null character. The maximum valid index is 4. In the above function, length has already been set to 6 and you are accessing s[5].
This can be fixed by changing the conditional in the for statement to counter < length-1;
And in display.
int max = getLength(s1);
for (int counter = 1; counter <= max; counter++) {
std::cout << s1[counter];
}
Here again, you are accessing the array out of bounds by using counter <= max in the loop.
This can be fixed by changing the conditional in the for statement to counter < max;
Here are some improvements, that should also cover your question:
Instead of a typedef, define a class for your string. The class should have an int for the length and a char* for the string data itself.
Use operator overloads in your class "string" so you can append them with + etc.
The - '0' gives me pain. You subtract the ASCII value of 42 from the length, but you do not add it as a character. Also, the length can be 127 at maximum, because char goes from -128 to +127. See point #1.
append_str changes the pointer of your object. That's very bad practice!
Ok, thank you everyone for helping me out.
The problem appeared to be inside the appendTest() function, where I was storing in the first element of the array the character code for the value I wanted to have as a size (i.e storing '5' instead of just 5). It seems that I didn't edit previous code that I had correctly, and that's what caused me the issues.
As an aside to what many of you are asking, why am I not using classes or better design, it's because I want to implement a basic string structure having many constraints, such as no classes, etc. I basically want to use only arrays, and the most I am affording myself is to make them dynamically allocated, i.e resizable.
I'm coding a game that utilizes a 'grid', which I have created using a 2 dimensional array of structs, which contain a char value and a boolean value. In my program's .h file, I declare the struct and create the grid.
struct Tile
{
char letter;
bool active;
};
Tile grid [6][5];
In my .cpp file, I initialize the grid so that all values are blank.
for (int i = 0; i < 7; ++i)
{
for (int j = 0; j < 6; ++j)
{
grid[i][j].active == false;
//grid[i][j].letter = '.';
//it always crashes when i try doing the above line
}
}
The function that prints the grid, printGrid, is below
for (int i = 0; i < 7; ++i)
{
for (int j = 0; j < 6; ++j)
{
cout << i;
//the above statement is for debugging purposes so that I can see
//which column easier
std::cout << grid[i][j].letter;
}
std::cout << std::endl;
}
cout << "1 2 3 4 5 6" << endl;
Now, the original goal was to have the default .letter value be '.'. But for some reason, when I tried to do this, there are disastrous results; the screen fills up with characters moving so fast I can't entirely see what they are (I recall some hearts and smiley faces), along with an obnoxious, rapid beeping. So I decided to leave that commented line out.
When I run the program without that line, for some reason, the "grid" always displays characters in certain spots, without any input from the user, or without me having expressly declared any values to that spot. For instance, the spot of the 1st column from the left and the bottom row, always has a character in it (grid[6][5].letter). It changes every time I run the program, and I've seen it range from a heart, to the letter A, to the spanish 'n' (the one with a ~ over it).
I thought to myself, "Hey, since grid[6][5] is the spots that are always buggy, I'll just declare those individual spot's .letter values to be blank (' ')!". That didn't work.
I've got no idea why this one spot is giving me trouble. There were other areas that would have an abnormal character, but I was able to neutralize them by setting their .letter values to blank. If anyone has any idea on how to fix this, pleas
EDIT: The other abnormal characters, which appear at grid[6][0], grid[6][1], grid[6][5], and grid[6][4], all make my program crash at later stages if I set them to blank (' '); however, blanking grid[6][5] is the one that makes it crash at the get go. I tried using a debugger, but it wasn't able to tell me anything helpful.
you're running over the end of your arrays
Tile grid [6][5]; needs to be Tile grid [7][6];
or you need to loop only to i < 6 and j < 5.
I am using C++ and SDL to make a game for fun.
I show the kill count on the screen by turning it into a surface using TTF_RenderText, which needs a const char*. There are gaps in between where I want the individual digits to be shown so I split up the string into individual chars.
This is the code I wrote to split up the string and render it on the screen:
SpareStream.str("");
SpareStream << Kills;
std::string KillsString = SpareStream.str();
for (int i = 0; i <= 4; i++)
{
if(i < KillsString.size())
{
std::string Cheat = KillsString.substr(i,i+1);
const char *KillsChar = Cheat.c_str();
Message = TTF_RenderText_Solid(EightBitLimit,KillsChar,White);
}
else Message = TTF_RenderText_Solid(EightBitLimit,"0",White);
ApplySurface(540 + (45 * i),(500 - HUD->h) + 24,Message,Screen);
}
However, when the kill count exceeds more than 100, this happens:
the tens and ones are shown where only the tens should be.
Why is this happening?
from my reference, std::string::substr is:
string substr (size_t pos = 0, size_t len = npos) const;
Thats a start/length pair, not start/end, so you need:
std::string Cheat = KillsString.substr(i,1);
btw, while start/length pairs are rarely use for containers in teh standard library, they were so universal for char* management in C that it does frequently turn up in the string classes.
The following function will generate a string with '\x' in between,
string GetHexEncode(string hexstring){
string swap = "\\x";
string h = "\\x";
int si = hexstring.length();
for (int i=0; i<hexstring.length(); i++)
{
if (i%2==0){
swap+=hexstring.at(i);
}
else
{
swap+=hexstring.at(i)+h;
}
}
return swap;
}
On occasion, the program outputs the following:
\x45\x39\xD3\x5B\x4F\xEA\x6F\x3C\xBC\x1B\xA0\xF4\xE7\x41\xE5\x8
\x45\x39\xD3\x5B\x4F\xEA\x6F\x3C\xBC\x1B\xA0\xF4\xE7\x41\xE5\x
If this happens, is there any way that I can change the last part into this:
\x45\x39\xD3\x5B\x4F\xEA\x6F\x3C\xBC\x1B\xA0\xF4\xE7\x41\xE5
Start out with an empty swap and append h + digits instead of appending an \x at the end.
additionally you should pre-allocate enough space in swap before starting your result as you know the final length of your result before. This would save reallocations of the string.