Extracting integers from a string which has no space - c++

so i'm currently trying to extract integers from a string. This is what i've done so far
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string s="VA 12 RC13 PO 44";
stringstream iss;
iss << s;
string temp;
vector<int> a1;
int j;
while (!iss.eof()) {
iss >> temp;
if (stringstream(temp)>>j) {
a1.push_back(j);
}
temp="";
}
}
Now, this works fine, but if i change the string to something like s="VA12RC13PO44", aka with no spaces this code doesn't work. Does anyone know how to go about solving this?
Thanks

There are really many many possible solutions. It depends on how advanced you are. Personally I would always use a std::regex approach for such tasks, but this is maybe too complicated.
A simple handcrafted solution could be this:
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
int main() {
std::string s = "VA 12 RC13 PO 44";
std::vector<int> a;
// We want to iterate over all characters in the string
for (size_t i = 0; i < s.size();) {
// Basically, we want to continue with the next character in the next loop run
size_t increments{1};
// If the current character is a digit, then we convert this and the following characters to an int
if (std::isdigit(s[i])) {
// The stoi function will inform us, how many characters ahve been converted.
a.emplace_back(std::stoi(s.substr(i), &increments));
}
// Either +1 or plus the number of converted characters
i += increments;
}
return 0;
}
So, here we check character for character of the string. If we find a digit, then we build a substring of the string, starting at the current character position and hand it of to std::stoi for conversion.
std::stoi will convert all characters it can get an convert it to an int. If there is a non-digit character, it stops conversion and informs on how many characters have been converted. We add this value to the current position of the evaluated character, to avoid to convert the digits from the same integer substring over and over again.
At the end, we put the resulting integer into the vector. We use emplace_back to avoid unnecessary temporary value.
This will of course work with or without blanks.

Related

Understanding String::Find In C++

I've been given a programming task that involves taking away certain letters in a string. I was trying out different ways to do this when I found the public member function string find. To put it short I was testing out the function via this program :
#include <iostream>
#include <string>
using namespace std;
int main()
{
string Word = "Applejuice";
cout<<Word.find("e")<<endl;
return 0;
}
So when I put in a letter such as "e" I get the number 4 which confuses me because I thought the function will count all the letters in that specific word such as apple juice. Also, when I use a letter that is not used in that word I get numbers like 18446744073709551615 for example when I put in X for e in the code above.
Could someone explain why this is happening, please?
string.find() will return the position of the first character of the first match.
If no matches were found, the function returns string::npos.
Therefore the number (18446744073709551615) you are getting is the string::npos
If you want to search for an only a single character in the string you can use the following code
#include <iostream>
#include <string>
using namespace std;
// Function that return count of the given
// character in the string
int count(string s, char c)
{
// Count variable
int res = 0;
for (int i=0;i<s.length();i++)
// checking character in string
if (s[i] == c)
res++;
return res;
}
// Driver code
int main()
{
string str= "Applejuice";
char c = 'e';
cout << count(str, c) << endl;
return 0;
}
If you want to avoid some random large values as output i.e. string::npos you can just add check for it like following:
if(Word.find("e") != string::npos)
{
...
}
Method find from class string return the position of the first character of the first match. Return type of find is size_t and since size_t is unsigned integral so if no match were found return string::nopos so you should compare the outputof find with string::nopos.
if(Word.find("e") != string::nopos)
{
...
}

How to delete part of a string c++ [duplicate]

I got a string and I want to remove all the punctuations from it. How do I do that? I did some research and found that people use the ispunct() function (I tried that), but I cant seem to get it to work in my code. Anyone got any ideas?
#include <string>
int main() {
string text = "this. is my string. it's here."
if (ispunct(text))
text.erase();
return 0;
}
Using algorithm remove_copy_if :-
string text,result;
std::remove_copy_if(text.begin(), text.end(),
std::back_inserter(result), //Store output
std::ptr_fun<int, int>(&std::ispunct)
);
POW already has a good answer if you need the result as a new string. This answer is how to handle it if you want an in-place update.
The first part of the recipe is std::remove_if, which can remove the punctuation efficiently, packing all the non-punctuation as it goes.
std::remove_if (text.begin (), text.end (), ispunct)
Unfortunately, std::remove_if doesn't shrink the string to the new size. It can't because it has no access to the container itself. Therefore, there's junk characters left in the string after the packed result.
To handle this, std::remove_if returns an iterator that indicates the part of the string that's still needed. This can be used with strings erase method, leading to the following idiom...
text.erase (std::remove_if (text.begin (), text.end (), ispunct), text.end ());
I call this an idiom because it's a common technique that works in many situations. Other types than string provide suitable erase methods, and std::remove (and probably some other algorithm library functions I've forgotten for the moment) take this approach of closing the gaps for items they remove, but leaving the container-resizing to the caller.
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string text = "this. is my string. it's here.";
for (int i = 0, len = text.size(); i < len; i++)
{
if (ispunct(text[i]))
{
text.erase(i--, 1);
len = text.size();
}
}
std::cout << text;
return 0;
}
Output
this is my string its here
When you delete a character, the size of the string changes. It has to be updated whenever deletion occurs. And, you deleted the current character, so the next character becomes the current character. If you don't decrement the loop counter, the character next to the punctuation character will not be checked.
ispunct takes a char value not a string.
you can do like
for (auto c : string)
if (ispunct(c)) text.erase(text.find_first_of(c));
This will work but it is a slow algorithm.
Pretty good answer by Steve314.
I would like to add a small change :
text.erase (std::remove_if (text.begin (), text.end (), ::ispunct), text.end ());
Adding the :: before the function ispunct takes care of overloading .
The problem here is that ispunct() takes one argument being a character, while you are trying to send a string. You should loop over the elements of the string and erase each character if it is a punctuation like here:
for(size_t i = 0; i<text.length(); ++i)
if(ispunct(text[i]))
text.erase(i--, 1);
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str = "this. is my string. it's here.";
transform(str.begin(), str.end(), str.begin(), [](char ch)
{
if( ispunct(ch) )
return '\0';
return ch;
});
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;//string is defined here.
cout << "Please enter a string with punctuation's: " << endl;//Asking for users input
getline(cin, s);//reads in a single string one line at a time
/* ERROR Check: The loop didn't run at first because a semi-colon was placed at the end
of the statement. Remember not to add it for loops. */
for(auto &c : s) //loop checks every character
{
if (ispunct(c)) //to see if its a punctuation
{
c=' '; //if so it replaces it with a blank space.(delete)
}
}
cout << s << endl;
system("pause");
return 0;
}
Another way you could do this would be as follows:
#include <ctype.h> //needed for ispunct()
string onlyLetters(string str){
string retStr = "";
for(int i = 0; i < str.length(); i++){
if(!ispunct(str[i])){
retStr += str[i];
}
}
return retStr;
This ends up creating a new string instead of actually erasing the characters from the old string, but it is a little easier to wrap your head around than using some of the more complex built in functions.
I tried to apply #Steve314's answer but couldn't get it to work until I came across this note here on cppreference.com:
Notes
Like all other functions from <cctype>, the behavior of std::ispunct
is undefined if the argument's value is neither representable as
unsigned char nor equal to EOF. To use these functions safely with
plain chars (or signed chars), the argument should first be converted
to unsigned char.
By studying the example it provides, I am able to make it work like this:
#include <string>
#include <iostream>
#include <cctype>
#include <algorithm>
int main()
{
std::string text = "this. is my string. it's here.";
std::string result;
text.erase(std::remove_if(text.begin(),
text.end(),
[](unsigned char c) { return std::ispunct(c); }),
text.end());
std::cout << text << std::endl;
}
Try to use this one, it will remove all the punctuation on the string in the text file oky.
str.erase(remove_if(str.begin(), str.end(), ::ispunct), str.end());
please reply if helpful
i got it.
size_t found = text.find('.');
text.erase(found, 1);

c++ extract an int from inside a string using stringstream

So I have the following string, line is it possible to extract the int that's inside?
I can use a very rudimentary regex expression but some stringstream solutions I found here look way cleaner and convert to type int.
string line = " <li id="episode_275">"
I have the following code, but I don't know to deal with the rest of the string like: the 4 tab indent,the "
int value;
stringstream ss(line);
ss >> value;
This can be done quite simply by just looking for the first digit, then having strtol do the integer parsing for you from that point:
#include <string>
#include <cctype>
#include <cstdlib>
int extractFirstIntInString(std::string const& s)
{
for (std::size_t i = 0; i != s.size(); ++i)
if (std::isdigit(s[i]))
return std::strtol(s.c_str() + i, nullptr, 10);
return 0; // no integer in string
}

Elegant solution for string parsing

so i got a dozen of strings which i download, example's below which i need to parse.
"Australija 036 AUD 1 4,713831 4,728015 4,742199"
"Vel. Britanija 826 GBP 1 10,300331 10,331325 10,362319"
So my first idea was to count manually where the number i need is (the second one, 4,728015 or 10,331325 in exampels up) and get substring.(52,8)
But then i realized that few of the the strings im parsing has a >9 number in it, so i would need a substring of (51,9) for that case, so i cant do it this way
Second idea was to save all the number like chars in a vector, and then get vector[4] and save it into a seperate variable.
And third one is to just loop the string until i position myself after the 5th group of spaces and then substring it.
Just looking for some feedback on what would be "best".
The problem
is that we can have multiple words at the beginning of the string. I.e. the first element may contain spaces.
The solution
Start from the end of the string where we are stable.
Split the string up at the spaces. Start counting from the end, and pick the previous-last element.
Solution 1: Boost string algorithms
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
string extractstring(string & fullstring)
{
vector<string> vs;
split(vs, fullstring);
return vs[vs.size() - 2];
}
Solution 2: QString (from Qt framework)
#include <QString>
QString extractstring(QString & fullstring)
{
QStringlist sl = fullstring.split(" ");
return sl[vs.size() - 2];
}
Solution 3: STL only
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
string extractstring(string & fullstring)
{
istringstream iss(fullstring);
vector<string> elements;
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter(elements));
return elements[elements.size() - 2];
}
Other solutions: regex, C-pointer acrobatic.
Update:
I would not use sscanf based solutions because it may be difficult to identify multiple words at the beginning of the string.
I believe you can do it with a single line using sscanf?
http://www.cplusplus.com/reference/cstdio/sscanf/
For example (http://ideone.com/e2cCT9):
char *str = "Australija 4,713831 4,728015 4,742199";
char tmp[255];
int a,b,c,d;
sscanf(str, "%*[^0-9] %d,%d %d,%d", &a, &b, &c, &d);
printf("Parsed values: %d %d %d %d\n",a,b,c,d);
The hurdle is that the first field is allowed to have spaces, but the remaining fields are separated by spaces.
This may not be elegant, but the concept should work:
std::string text_line;
getline(my_file, text_line);
std::string::size_type field_1_start;
const unsigned int text_length = text_line.length();
for (field_1_start = 0; field_1_start < text_length; ++field_1_start)
{
if (is_digit(text_line[field_1_start])
{
break;
}
}
if (field_1_start < text_length)
{
std::string remaining_text = text_line.substr(field_1_start, text_length - field_1_start);
std::istringstream input_data(remaining_text);
int field_1;
std::string field2;
input_data >> field_1;
input_data >> field_2;
//...
}

Scanning ASCII value of each character of a string

Is there anyway , if I enter any string , then I want to scan ASCII value of each character inside that string , if I enter "john" then I should get 4 variables getting ASCII value of each character, in C or C++
Given a string in C:
char s[] = "john";
or in C++:
std::string s = "john";
s[0] gives the numeric value of the first character, s[1] the second an so on.
If your computer uses an ASCII representation of characters (which it does, unless it's something very unusual), then these values are the ASCII codes. You can display these values numerically:
printf("%d", s[0]); // in C
std::cout << static_cast<int>(s[0]); // in C++
Being an integer type (char), you can also assign these values to variables and perform arithmetic on them, if that's what you want.
I'm not quite sure what you mean by "scan". If you're asking how to iterate over the string to process each character in turn, then in C it's:
for (char const * p = s; *p; ++p) {
// Do something with the character value *p
}
and in (modern) C++:
for (char c : s) {
// Do something with the character value c
}
If you're asking how to read the string as a line of input from the terminal, then in C it's
char s[SOME_SIZE_YOU_HOPE_IS_LARGE_ENOUGH];
fgets(s, sizeof s, stdin);
and in C++ it's
std::string s;
std::cin >> s; // if you want a single word
std::getline(std::cin, s); // if you want a whole line
If you mean something else by "scan", then please clarify.
You can simply get the ascii value of a char by casting it to type int:
char c = 'b';
int i = c; //i contains ascii value of char 'b'
Thus, in your example the code to get the ascii values of a string would look something like this:
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
int main()
{
string text = "John";
for (int i = 0; i < text.size(); i++)
{
cout << (int)text[i] << endl; //prints corresponding ascii values (one per line)
}
}
To get the corresponding char from an integer representing an entry in the ascii table, you just have to cast the int back to char again:
char c = (char)74 // c contains 'J'
The code given above was written in C++ but it basically works the same way in C (and many other languages as well I guess)
There is no way to turn a string of length 'x' into x variables. In C or C++ you can only declare a fixed number of variables. But probably you don't need to do what you are saying. Perhaps you just need an array, or most likely you just need a better way to solve whatever problem you are trying to solve. If you explain what the problem is in the first place, then I'm sure a better way can be explained.
Ya,I think there are some more better solutions are also available but this one also be helpful.
In C
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main(){
char s[]="abc";
int cnt=0;
while(1){
if(s[cnt++]==NULL)break;
}
int *a=(int *)malloc(sizeof(int)*cnt);
for(int i=0;i<cnt;i++)a[i]=s[i];
for(int i=0;i<cnt-1;i++)printf("%d\n",a[i]);
return 0;
}
In C++
#include <iostream>
#include <string>
using namespace std;
int main(){
string s="abc";
//int *a=new int[s.length()];
//for(int i=0;i<s.length();i++)a[i]=s[i];
for(int i=0;i<s.length();i++)
cout<<(int)s[i]<<endl;
return 0;
}
I hope this one will be helpful..
yeah it's very easy ..just a demo
int main()
{
char *s="hello";
while(*s!='\0')
{
printf("%c --> %d\n",*s,*s);
s++;
}
return 0;
}
But make sure your machine is supporting the ASCII value format.
In C every char has one integral value associted with it called ASCII.
Using %d format specifier you can directly print the ASCII of any char as above.
NOTE: It's better to get good book and practice this kind of program yourself.