Quick way to split string at first sign of a digit - c++

I have a list of data I need to parse that contains a name and phone number in a text file. The name and phone number must be split into different string vars, but I can't really think of a fast method to do so. I can easily run a for loop and do something like
//file line read into string `line`
string name;
string number;
for(int i = 0; i < line.length(); i++) {
if(isDigit(line[i])) {
name = line.substr(0, i-1);
number = line.substr(i, line.length()-i);
}
}
but I feel there has to be an easy way to do this in C++.

You could use find_first_of to find the first digit without using a loop:
string s("hello12345");
size_t i = s.find_first_of("0123456789");
string name(s.substr(0, i));
string number(s.substr(i));
Demo.
Note that if you wish to take a substring to the end of the original string, you do not need to pass the length: the library will figure it out automatically for you.

Related

C++ Most effective way to grab a substring with a value in the middle of a long string

I want to find the most effective way to do something like this:
A big string containing all kinds of data, for example:
plushieid:5637372&plushieposition:12757&plushieowner:null&totalplushies:5637373
I want to make a function that would have the input to be, let's say "plushieposition", and I would have it find and return the string with plushieposition:12757.
The only way I can think of is find the position of plushieposition and then scan for & and delete the rest. But, is there a cleaner way? If not, what would be the best way to do this in code?
I'm having a little bit of trouble understanding string scan practices.
Use std::string::find() to find the starting and stopping positions, and then use std::string::substr() to extract what is between them, eg:
string extract(const string &s, const string &name)
{
string to_find = name + ":";
string::size_type start = s.find(to_find);
if (start == string::npos) return "";
string::size_type stop = s.find('&', start + to_find.size());
return s.substr(start, stop - start);
}
string s = "plushieid:5637372&plushieposition:12757&plushieowner:null&totalplushies:5637373";
string found = extract(s, "plushieposition");
Online Demo

C++ read different kind of datas from file until there's a string beginning with a number

In C++, I'd like to read from an input file which contains different kind of datas: first the name of a contestant (2 or more strings with whitespaces), then an ID (string without whitespaces, always beginning with a number), then another strings without ws and a numbers (the sports and their achieved places).
For example:
Josh Michael Allen 1063Szinyei running 3 swimming 1 jumping 1
I show you the code what I started to write and then stucked..
void ContestEnor::next()
{
string line;
getline(_f , line);
if( !(_end = _f.fail()) ){
istringstream is(line);
is >> _cur.contestant >> _cur.id; // here I don't know how to go on
_cur.counter = 0;
//...
}
}
Thank you for your help in advance.
You should look into using std::getline with a delimiter. This way, you can delimit on a space character and read until you find a string where the first character in a number. Here is a short code example (this seems rather homework-like, so I don't want to write too much of it for you ;):
std::string temp, id;
while (std::getline(_f, temp, ' ')) {
if (temp[0] >= 0 && temp[0] <= '9') {
id = temp;
}
// you would need to add more code for the rest of the data on that line
}
/* close the file, etc. */
This code should be pretty self-explanatory. The most important thing to know is that you can use std::getline to get data up until a delimiter. The delimiter is consumed, just like the default behavior of delimiting on a newline character. Thus, the name getline isn't entirely accurate - you can still get only part of a line if you need to.

C++ retrieve numerical values in a line of string

Here is the content of txt file that i've managed read.
X-axis=0-9
y-axis=0-9
location.txt
temp.txt
I'm not sure whether if its possible but after reading the contents of this txt file i'm trying to store just the x and y axis range into 2 variables so that i'll be able to use it for later functions. Any suggestion? And do i need to use vectors? Here is the code for reading of the file.
string configName;
ifstream inFile;
do {
cout << "Please enter config filename: ";
cin >> configName;
inFile.open(configName);
if (inFile.fail()){
cerr << "Error finding file, please re-enter again." << endl;
}
} while (inFile.fail());
string content;
string tempStr;
while (getline(inFile, content)){
if (content[0] && content[1] == '/') continue;
cout << endl << content << endl;
depends on the style of your file, if you are always sure that the style will remain unchanged, u can read the file character by character and implement pattern recognition stuff like
if (tempstr == "y-axis=")
and then convert the appropriate substring to integer using functions like
std::stoi
and store it
I'm going to assume you already have the whole contents of the .txt file in a single string somewhere. In that case, your next task should be to split the string. Personally, yes, I would recommend using vectors. Say you wanted to split that string by newlines. A function like this:
#include <string>
#include <vector>
std::vector<std::string> split(std::string str)
{
std::vector<std::string> ret;
int cur_pos = 0;
int next_delim = str.find("\n");
while (next_delim != -1) {
ret.push_back(str.substr(cur_pos, next_delim - cur_pos));
cur_pos = next_delim + 1;
next_delim = str.find("\n", cur_pos);
}
return ret;
}
Will split an input string by newlines. From there, you can begin parsing the strings in that vector. They key functions you'll want to look at are std::string's substr() and find() methods. A quick google search should get you to the relevant documentation, but here you are, just in case:
http://www.cplusplus.com/reference/string/string/substr/
http://www.cplusplus.com/reference/string/string/find/
Now, say you have the string "X-axis=0-9" in vec[0]. Then, what you can do is do a find for = and then get the substrings before and after that index. The stuff before will be "X-axis" and the stuff after will be "0-9". This will allow you to figure that the "0-9" should be ascribed to whatever "X-axis" is. From there, I think you can figure it out, but I hope this gives you a good idea as to where to start!
std::string::find() can be used to search for a character in a string;
std::string::substr() can be used to extract part of a string into another new sub-string;
std::atoi() can be used to convert a string into an integer.
So then, these three functions will allow you to do some processing on content, specifically: (1) search content for the start/stop delimiters of the first value (= and -) and the second value (- and string::npos), (2) extract them into temporary sub-strings, and then (3) convert the sub-strings to ints. Which is what you want.

Replace substring within a string c++

I want to replace substring within a string,
For eg: the string is aa0_aa1_bb3_c*a0_a,
so I want to replace the substring a0_a with b1_a, but I dont want aa0_a to get replaced.
Basically, no alphabet should be present before and after the substring "a0_a" (to be replaced).
That's what regexes are good at. It exists in standard library since C++11, if you have an older version, you can also use Boost.
With the standard library version, you could do (ref):
std::string result;
std::regex rx("([^A-Za-Z])a0_a[^A-Za-Z])");
result = std::regex_replace("aa0_aa1_bb3_c*a0_a", rx, "$1b1_a$2");
(beware: untested)
Easy enough to do if you loop through each character. Some pseudocode:
string toReplace = "a0_a";
for (int i = 0; i < myString.length; i++) {
//filter out strings starting with another alphabetical char
if (!isAlphabet(myString.charAt(i))) {
//start the substring one char after the char we have verified to be not alphabetical
if (substring(myString(i + 1, toReplace.length)).equals(toReplace)) {
//make the replacement here
}
}
}
Note that you will need to check for indexing out of bounds when looking at the substrings.

Replace string in a vector string

I want to replace a string in a vector string. I mean, I have a vector string, define vector tmpback , with info like this: name_lastname_phonenumber
I want to replace some last names. For example if someone is john_smith_5551234, I want to replace smith to smith100.
this is my code, o part of it:
vector<string> tmpback = names;
for (Int_t i = 0; i < tmpback.size(); i++) {
replace(tmpback[i].begin(),tmpback[i].end(),"smith", "smith"+number);
}
(i defined number previously as Int_t number = 0 and give some values later).
did someone have any idea of what am I doing wrong?
Thanks
std::replace does not replace sequences with other sequences. It replaces single elements with other single elements. Besides that, your method of appending a number to a string does not work.
Try boost::replace_first or boost::replace_all along with either boost::lexical_cast or std::to_string(c++11 only) for converting a number to a string.
using namespace boost;
std::string replace_str = std::string("smith") + lexical_cast<std::string>(number);
replace_first(tmpback[i], "smith", replace_str);
You could also search for the sub-string, and if you find it, insert the number (converted to a string) after it:
std::string::size_type pos = tmpback[i].find("smith");
if (pos != std::string::npos)
{
// adding 5 because that's the length of "smith"
tmpback[i].insert(pos + 5, std::to_string(number));
}
My immediate reaction would be to wonder why you're putting yourself in this situation at all. Instead of jamming three separate items into a string, then manipulating pieces of that string, why not create a struct so you can work with each piece separately?
struct person {
std::string first_name;
std::string last_name;
int record_no;
std::string phone_number;
};
This way, instead of tacking the record number (or whatever exactly your '100' represents) onto the end of the last name, you just give it its own field, and write an appropriate number as needed:
vector<person> tmpback;
for (int i=0; i<tmpback.size(); i++)
tmpback[i].record_no = number;