C++, Trouble with string and int conversion - c++

I know how to convert the string when it's just made up of integers, or it begins with ints. I am trying to convert to an integer when the string starts with a char in the beginning, or middle. I've tried running through a for loop, checking if (isdigit(str[i]) before trying stoi, stringstream, atoi, etc... None of them really work. I have the same problem even without the for loop. I've tried Googling my problem, but no luck. Any suggestions, or anything that I can try?

You have to check character by character if it's a digit or not and, if it is, add it to a new string. In the end, you convert your new string to an int like you would normally. Look at the code below. Hope I could help!
string s = "pc2jjj10";
char temp;
string result;
for (int i = 0; i < s.length(); i++){
temp = s.at(i);
if (isdigit(temp)){
result.push_back(temp);
}
}
int number = stoi(result);

Related

Weird results when I iterate through string with "ñ" char

I have a string of characters and one of those possible characters is the letter "ñ". My problem is, my string seems to behave in a weird way when I try to modify it or iterate through the string. For example if I have the code:
std::ifstream infile (argv[1]);
std::string texto_crudo((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
for (int i = 0; i<texto_crudo.length(); i++){
if(es_enie(texto_crudo[i])) {
texto_crudo[i] = '$';
}
}
Where es_enie returns true if texto_crudo[i] = ñ. It seems like in the cell where ñ is located it behaves as if it has two values instead of one.
I managed to find a solution to my exact problem. As Some programmer dude commented, it was because my text was in UTF-8 and I needed to convert it to iso-8859-1 in order to be able to use "ñ" correctly.
Convert string from UTF-8 to ISO-8859-1

want to optimize this string manipulation program c++

I've just solve this problem:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3139
Here's my solution:
https://ideone.com/pl8K3K
int main(void)
{
string s, sub;
int f,e,i;
while(getline(cin, s)){
f=s.find_first_of("[");
while(f< s.size()){
e= s.find_first_of("[]", f+1);
sub = s.substr(f, e-f);
s.erase(f,e-f);
s.insert(0, sub);
f=s.find_first_of("[", f+1);
}
for(i=0; i<s.size(); i++){
while((s[i]==']') || (s[i]=='[')) s.erase(s.begin()+i);
}
cout << s << endl;
}
return 0;
}
I get TLE ,and I wanna know which operation in my code costs too expensive and somehow optimize the code..
Thanks in advance..
If I am reading your problem correctly, you need to rethink your design. There is no need for functions to search, no need for erase, substr, etc.
First, don't think about the [ or ] characters right now. Start out with a blank string and add characters to it from the original string. That is the first thing that speeds up your code. A simple loop is what you should start out with.
Now, while looping, when you actually do encounter those special characters, all you need to do is change the "insertion point" in your output string to either the beginning of the string (in the case of [) or the end of the string (in the case of ]).
So the trick is to not only build a new string as you go along, but also change the point of insertion into the new string. Initially, the point of insertion is at the end of the string, but that will change if you encounter those special characters.
If you are not aware, you can build a string not by just using += or +, but also using the std::string::insert function.
So for example, you always build your output string this way:
out.insert(out.begin() + curInsertionPoint, original_text[i]);
curInsertionPoint++;
The out string is the string you're building, the original_text is the input that you were given. The curInsertionPoint will start out at 0, and will change if you encounter the [ or ] characters. The i is merely a loop index into the original string.
I won't post any more than this, but you should get the idea.

NTL String to ZZ conversion and ZZ to String

So I'm working on a basic RSA decryption program and I'm trying to figure out how to convert between a string and a ZZ. I've looked at the following question: How can i convert a string into a ZZ number?, however, I'm a little confused, and the answer there didn't work for me. My code:
fromBase()
{
string message = "hello world";
ZZ number (INIT_VAL, message.c_str());
cerr << number;
}
Gives me the following output.
bad ZZ input
Aborted
So, I thought, no big deal, I'll just try to find what INIT_VAL is supposed to be and that should give me an idea of where to look. But no such luck, I couldn't find anything that looked like it. I trued it with INIT_VAL_STRUCT as well, and got the following error:
base.cpp: In function âNTL::ZZ fromBase(std::string)â:
base.cpp:24: error: âmessageâ is not a type
base.cpp:24: error: expected â,â or â...â before â.â token
Lastly, I tried the solution posted here: Regarding create a NTL class type thinking I could try some type casting. Here's my code:
ZZ fromBase(string message)
{
ZZ x;
x = conv<ZZ>(message);
return x;
}
This gave me the following:
g++ base.cpp -lntl
base.cpp: In function âNTL::ZZ fromBase(std::string)â:
base.cpp:19: error: expected primary-expression before â>â token
As if I didn't specify a type.
To conclude, I know that INIT_VAL is a constant, but it doesn't seem to be working with something. I sense I've just got a disconnect, but trying to find it isn't easy. Any help would be appreciated, and any references for the NTL would be greatly appreciated. Sorry for the long post!
(Also, NTL is pretty poorly documented, from what I've seen, do you have any sites that may help a newbie to the library?)
You want to convert a string, that actually contains non numeric characters into a number.
There is no canonical number of a string, so you cannot do this in one step. C++ can give you the number of a character, which is the ascii number. You can use this function to get the ascii number of a string:
ZZ stringToNumber(string str)
{
ZZ number = conv<ZZ>(str[0]);
long len = str.length();
for(long i = 1; i < len; i++)
{
number *= 128;
number += conv<ZZ>(str[i]);
}
return number;
}
You get the string back by this function
string numberToString(ZZ num)
{
long len = ceil(log(num)/log(128));
char str[len];
for(long i = len-1; i >= 0; i--)
{
str[i] = conv<int>(num % 128);
num /= 128;
}
return (string) str;
}
If you have some non ascii characters like ö or ß you have to use an other way of converting a character to a number.(But I don't know how exactly this works)

Arduino opening SD filename as string

I am trying to open up a file that I calculate the name into a string. However, it is just giving me compile errors as shown.
for(int i=1;;i++)
{
String temp = "data";
temp.concat(i);
temp.concat(".csv");
if(!SD.exists(temp))//no matching function for call to sdclass::exists(String&)
{
datur = SD.open(temp,FILE_WRITE);
}
}
I am a java person, so I don't see why this isn't working. I tried a few string object methods but none seem to have worked. I am a bit new at arduino programming but I understand java much better. The point of this for loop is to make a new file each time the arduino reboots.
SD.open expects a character array instead of a String, you need to convert it using the toCharArray method first. Try
char filename[temp.length()+1];
temp.toCharArray(filename, sizeof(filename));
if(!SD.exists(filename)) {
...
}
Completed Code:
for(int i=1;;i++)
{
String temp = "data";
temp.concat(i);
temp.concat(".csv");
char filename[temp.length()+1];
temp.toCharArray(filename, sizeof(filename));
if(!SD.exists(filename))
{
datur = SD.open(filename,FILE_WRITE);
break;
}
}
You will find a number of functions take char arrays instead of strings.

C++ is mixing my strings?

I have this really simple c++ function I wrote myself.
It should just strip the '-' characters out of my string.
Here's the code
char* FastaManager::stripAlignment(char *seq, int seqLength){
char newSeq[seqLength];
int j=0;
for (int i=0; i<seqLength; i++) {
if (seq[i] != '-') {
newSeq[j++]=seq[i];
}
}
char *retSeq = (char*)malloc((--j)*sizeof(char));
for (int i=0; i<j; i++) {
retSeq[i]=newSeq[i];
}
retSeq[j+1]='\0'; //WTF it keeps reading from memory without this
return retSeq;
}
I think that comment speaks for itself.
I don't know why, but when I launch the program and print out the result, I get something like
'stripped_sequence''original_sequence'
However, if I try to debug the code to see if there's anything wrong, the flows goes just right, and ends up returning the correct stripped sequence.
I tried to print out the memory of the two variables, and here are the memory readings
memory for seq: http://i.stack.imgur.com/dHI8k.png
memory for *seq: http://i.stack.imgur.com/UqVkX.png
memory for retSeq: http://i.stack.imgur.com/o9uvI.png
memory for *retSeq: http://i.stack.imgur.com/ioFsu.png
(couldn't include links / pics because of spam filter, sorry)
This is the code I'm using to print out the strings
for (int i=0; i<atoi(argv[2]); i++) {
char *seq;
if (usingStructure) {
seq = fm.generateSequenceWithStructure(structure);
}else{
seq = fm.generateSequenceFromProfile();
}
cout<<">Sequence "<<i+1<<": "<<seq<<endl;
}
Now, I have really no idea about what's going on.
If you can use std::string, simply do this:
std::string FastaManager::stripAlignment(const std::string& str)
{
std::string result(str);
result.erase(std::remove(result.begin(), result.end(), '-'), result.end());
return result;
}
This is called "erase-remove idiom".
This happens because you put the terminating zero of a C string outside the allocated space. You should be allocating one extra character at the end of your string copy, and adding '\0' there. Or better yet, you should use std::string.
char *retSeq = (char*)malloc((j+1)*sizeof(char));
for (int i=0; i<j; i++) {
retSeq[i]=newSeq[i];
}
retSeq[j]='\0';
it keeps reading from memory without this
This is by design: C strings are zero-terminated. '\0' signals to string routines in C that the end of the string has been reached. The same convention holds in C++ when you work with C strings.
Personally, I think you would be best off using std::string unless you have really very good reason otherwise:
std::string FastaManager::stripAlignment(std::string value)
{
value.erase(std::remove(value.begin(), value.end(), value.begin(), '-'), value.end());
return value;
}
When you are using C strings you need to realize that they are null-terminated: C strings reach up to the first null character found. With code you posted you introduced an out of range assignment as you allocated 'j' elements and you assign to retSeq[j + 1] which is two character past the end of the string (surely you mean retSeq[j] = 0; anyway).