How to find the position of the first blank in a string - c++

So I have an array of names and I need to find the position of the blank and put anything that comes before it into fname and put everything that comes after the blank into lname. I have absolutely no idea what I'm doing and I got help from my teacher and she gave me the 3 lines of code that come after posit_of_blank, fname and lname and said that all I had to do was figure out what goes in place of the ... and I haven't got a clue.
using namespace std;
#include "PersonNameFileCreator.h"
#include "PersonName.h"
int main()
{
string arr_names[] = {"Adam Burke", "Madeline Kramer", "Scott Gardner",
"Tonya Lopez", "Christoper Hamilton",
"Andrew Mitchell", "Lori Smith" };
PersonNameFileCreator fil_names("names.txt);
for (auto one_name : arr_names)
{
int posit_of_blank = ?
string fname = ?
string lname = ?
PersonName onePerson(fname, lname);
fil_names.write_to_file(onePerson);
}
return 0;
}

If you refer to the std::string documentation, it will have what you need.
Given a string std::string name = "Justin Jones" you can find the space using the std::string::find() or the std::string::find_first_of() function. From the example above, you can find the space with unsigned int spacePosition = name.find(" ");. This will return the position of the space and then you can use the std::string::substr function to split it where you need it.
Here is a link to the find function: https://cplusplus.com/reference/string/string/find/
Here is a link to the substr function: https://cplusplus.com/reference/string/string/substr/

Related

I need to swap out two values in a string for one (C++)

I am making a roman numeral converter. I have everything figured out except there is one problem at the end.
The string looks like IVV
I need to make it IX
I have split the string at each new letter, then appended them back on, then using an if statement to see if it contains 2 "V"s. I want to know if there is a simpler way to do this.
Using std::string should help you tremendously as you can leverage its search and replace functionality. You'll want to start with the find function which allows you to search for a character or a string and returns an index where what you are searching for exists or npos if the search fails.
You can then call replace passing it the index returned by find, the number of characters you want to replace and what replace the range with.
The code below should help you get started.
#include <string>
#include <iostream>
int main()
{
std::string roman("IVV");
// Search for the string you want to replace
std::string::size_type loc = roman.find("VV");
// If the substring is found replace it.
if (loc != std::string::npos)
{
// replace 2 characters staring at position loc with the string "X"
roman.replace(loc, 2, "X");
}
std::cout << roman << std::endl;
return 0;
}
You could use std string find and rfind operations, these find the position of the first and the last occurrence of the entered parameter, check if these are not equal and you will know
Answer updated
#include <string>
int main()
{
std::string x1 = "IVV";
if (x1.find('V') !=x1.rfind('V'))
{
x1.replace(x1.find('V'), 2, 'X');
}
return 0;
}

Strings; substrings. Not understanding a block of codes

This is a program that creates a username for a user who enters their first name and last name.
Username = user's first initial + up to 7 letters of user's last name.
Ex: John Smith becomes 'jsmith'
John Smoother becomes 'jsmoothe'
#include <iostream>
#include <string>
using namespace std;
int main()
{
string fullname, fname, lname, uname, u2;
int l, len;
cout<<"FULLNAME: ";
getline(cin, fullname);
l=fullname.length();
cout<<"Fullname length: "<<l<<endl;
/*
len=0;
while (len!=(l-1))
{
if (fullname[len]!=' ')
len++;
else
break;
}
fname=fullname.substr(0,len);
lname=fullname.substr(len+1, (l-len));
*/
cout<<"FName: "<<fname<<endl;
cout<<"LName: "<<lname<<endl;
if(isupper(fname[0]))
{
fname[0]=fname[0] + 32;
}
if(isupper(lname[0]))
{
lname[0]=lname[0] + 32;
}
cout<<"FName: "<<fname<<endl;
cout<<"LName: "<<lname<<endl;
uname=fname.substr(0,1);
u2=lname.substr(0,7);
uname+=u2;
cout<<"USERNAME: "<<uname;
return 0;
}
I am having difficulties understand the block of codes i put between comments (/.../).
It is a silly code so do not try to understand it. It would have been much better if you had wrote the code by yourself. In this case, you would not ask such a question.
The author of the code tries to count first non-space characters and then to extract them using method substr and to place them in fname. Remaining characters are placed in lname.
Take into account that the code is invalid. For example the entered string can start with blanks. Also between the two names there can be more than one blank.
Also, it would have been much better if it was written for example
fname[0] = tolower( fname[0] );
instead of
fname[0]=fname[0] + 32;
And I think you need to convert all the characters of names to lower case.
It is simple ,if your string is "John Hoffman",len will equal to 4

C++ Get String between two delimiter String

Is there any inbuilt function available two get string between two delimiter string in C/C++?
My input look like
_STARTDELIMITER_0_192.168.1.18_STOPDELIMITER_
And my output should be
_0_192.168.1.18_
Thanks in advance...
You can do as:
string str = "STARTDELIMITER_0_192.168.1.18_STOPDELIMITER";
unsigned first = str.find(STARTDELIMITER);
unsigned last = str.find(STOPDELIMITER);
string strNew = str.substr (first,last-first);
Considering your STOPDELIMITER delimiter will occur only once at the end.
EDIT:
As delimiter can occur multiple times, change your statement for finding STOPDELIMITER to:
unsigned last = str.find_last_of(STOPDELIMITER);
This will get you text between the first STARTDELIMITER and LAST STOPDELIMITER despite of them being repeated multiple times.
I have no idea how the top answer received so many votes that it did when the question clearly asks how to get a string between two delimiter strings, and not a pair of characters.
If you would like to do so you need to account for the length of the string delimiter, since it will not be just a single character.
Case 1: Both delimiters are unique:
Given a string _STARTDELIMITER_0_192.168.1.18_STOPDELIMITER_ that you want to extract _0_192.168.1.18_ from, you could modify the top answer like so to get the desired effect. This is the simplest solution without introducing extra dependencies (e.g Boost):
#include <iostream>
#include <string>
std::string get_str_between_two_str(const std::string &s,
const std::string &start_delim,
const std::string &stop_delim)
{
unsigned first_delim_pos = s.find(start_delim);
unsigned end_pos_of_first_delim = first_delim_pos + start_delim.length();
unsigned last_delim_pos = s.find(stop_delim);
return s.substr(end_pos_of_first_delim,
last_delim_pos - end_pos_of_first_delim);
}
int main() {
// Want to extract _0_192.168.1.18_
std::string s = "_STARTDELIMITER_0_192.168.1.18_STOPDELIMITER_";
std::string s2 = "ABC123_STARTDELIMITER_0_192.168.1.18_STOPDELIMITER_XYZ345";
std::string start_delim = "_STARTDELIMITER";
std::string stop_delim = "STOPDELIMITER_";
std::cout << get_str_between_two_str(s, start_delim, stop_delim) << std::endl;
std::cout << get_str_between_two_str(s2, start_delim, stop_delim) << std::endl;
return 0;
}
Will print _0_192.168.1.18_ twice.
It is necessary to add the position of the first delimiter in the second argument to std::string::substr as last - (first + start_delim.length()) to ensure that the it would still extract the desired inner string correctly in the event that the start delimiter is not located at the very beginning of the string, as demonstrated in the second case above.
See the demo.
Case 2: Unique first delimiter, non-unique second delimiter:
Say you want to get a string between a unique delimiter and the first non unique delimiter encountered after the first delimiter. You could modify the above function get_str_between_two_str to use find_first_of instead to get the desired effect:
std::string get_str_between_two_str(const std::string &s,
const std::string &start_delim,
const std::string &stop_delim)
{
unsigned first_delim_pos = s.find(start_delim);
unsigned end_pos_of_first_delim = first_delim_pos + start_delim.length();
unsigned last_delim_pos = s.find_first_of(stop_delim, end_pos_of_first_delim);
return s.substr(end_pos_of_first_delim,
last_delim_pos - end_pos_of_first_delim);
}
If instead you want to capture any characters in between the first unique delimiter and the last encountered second delimiter, like what the asker commented above, use find_last_of instead.
Case 3: Non-unique first delimiter, unique second delimiter:
Very similar to case 2, just reverse the logic between the first delimiter and second delimiter.
Case 4: Both delimiters are not unique:
Again, very similar to case 2, make a container to capture all strings between any of the two delimiters. Loop through the string and update the first delimiter's position to be equal to the second delimiter's position when it is encountered and add the string in between to the container. Repeat until std::string:npos is reached.
To get a string between 2 delimiter strings without white spaces.
string str = "STARTDELIMITER_0_192.168.1.18_STOPDELIMITER";
string startDEL = "STARTDELIMITER";
// this is really only needed for the first delimiter
string stopDEL = "STOPDELIMITER";
unsigned firstLim = str.find(startDEL);
unsigned lastLim = str.find(stopDEL);
string strNew = str.substr (firstLim,lastLim);
//This won't exclude the first delimiter because there is no whitespace
strNew = strNew.substr(firstLim + startDEL.size())
// this will start your substring after the delimiter
I tried combining the two substring functions but it started printing the STOPDELIMITER
Hope that helps
Hope you won't mind I'm answering by another question :)
I would use boost::split or boost::split_iter.
http://www.boost.org/doc/libs/1_54_0/doc/html/string_algo/usage.html#idp166856528
For example code see this SO question:
How to avoid empty tokens when splitting with boost::iter_split?
Let's say you need to get 5th argument (brand) from output below:
zoneid:zonename:state:zonepath:uuid:brand:ip-type:r/w:file-mac-profile
You cannot use any "str.find" function, because it is in the middle, but you can use 'strtok'. e.g.
char *brand;
brand = strtok( line, ":" );
for (int i=0;i<4;i++) {
brand = strtok( NULL, ":" );
}
This is a late answer, but this might work too:
string strgOrg= "STARTDELIMITER_0_192.168.1.18_STOPDELIMITER";
string strg= strgOrg;
strg.replace(strg.find("STARTDELIMITER"), 14, "");
strg.replace(strg.find("STOPDELIMITER"), 13, "");
Hope it works for others.
void getBtwString(std::string oStr, std::string sStr1, std::string sStr2, std::string &rStr)
{
int start = oStr.find(sStr1);
if (start >= 0)
{
string tstr = oStr.substr(start + sStr1.length());
int stop = tstr.find(sStr2);
if (stop >1)
rStr = oStr.substr(start + sStr1.length(), stop);
else
rStr ="error";
}
else
rStr = "error"; }
or if you are using Windows and have access to c++14, the following,
void getBtwString(std::string oStr, std::string sStr1, std::string sStr2, std::string &rStr)
{
using namespace std::literals::string_literals;
auto start = sStr1;
auto end = sStr2;
std::regex base_regex(start + "(.*)" + end);
auto example = oStr;
std::smatch base_match;
std::string matched;
if (std::regex_search(example, base_match, base_regex)) {
if (base_match.size() == 2) {
matched = base_match[1].str();
}
rStr = matched;
}
}
Example:
string strout;
getBtwString("it's_12345bb2","it's","bb2",strout);
getBtwString("it's_12345bb2"s,"it's"s,"bb2"s,strout); // second solution
Headers:
#include <regex> // second solution
#include <string.h>

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;

Parsing a string by a delimeter in C++

Ok, so I need some info parsed and I would like to know what would be the best way to do it.
Ok so here is the string that I need to parse. The delimeter is the "^"
John Doe^Male^20
I need to parse the string into name, gender, and age variables. What would be the best way to do it in C++? I was thinking about looping and set the condition to while(!string.empty()
and then assign all characters up until the '^' to a string, and then erase what I have already assigned. Is there a better way of doing this?
You can use getline in C++ stream.
istream& getline(istream& is,string& str,char delimiter=ā€™\nā€™)
change delimiter to '^'
You have a few options. One good option you have, if you can use boost, is the split algorithm they provide in their string library. You can check out this so question to see the boost answer in action: How to split a string in c
If you cannot use boost, you can use string::find to get the index of a character:
string str = "John Doe^Male^20";
int last = 0;
int cPos = -1;
while ((cPos = str.find('^', cPos + 1)) != string::npos)
{
string sub = str.substr(last, cPos - last);
// Do something with the string
last = cPos + 1;
}
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "This is a sample string";
char * pch;
printf ("Looking for the 's' character in \"%s\"...\n",str);
pch=strchr(str,'s');
while (pch!=NULL)
{
printf ("found at %d\n",pch-str+1);
pch=strchr(pch+1,'s');
}
return 0;
}
Do something like this in an array.
You have a number of choices but I would use strtok(), myself. It would make short work of this.