Hi I am new to community.
I have a question regarding std::string.
Is it possible to write into specific index of string keeping rest of string empty ?
e.g.
std::string tempString = "";
tempString ->insert(10, "Some String I want to Insert");
//index position and string to insert
and final answer would be tempString = "__________Some String I want to Insert"
where characters 0 through 9 are uninitialized.
this is possible with char * once memory is allocated.
but is this possible with std::strings ?
Thank you in advance and thank you for having me in this community :)
Given some insertion position
size_t insertion_position = 10;
And some std::string or const char* to be inserted
const char *text = "Some String I want to Insert";
This will do it efficiently.
std::string tempString( insertion_position, ' ' );
tempString += text;
Or as a one liner:
std::string tempString = std::string( insertion_position, ' ' ) + text;
check this out, you may be able to use a stringstream instead of cout. Then you can just get the output into a string instead of seeing it dumped on the console
// using the fill character
#include <iostream> // std::cout
int main () {
char prev;
std::cout.width (10);
std::cout << 40 << '\n';
prev = std::cout.fill ('x');
std::cout.width (10);
std::cout << 40 << '\n';
std::cout.fill(prev);
return 0;
}
Output:
40
xxxxxxxx40
Is it possible to write into specific index of string keeping rest of string [uninitialized] ?
No.
std::basic_string is not designed to represent collections of uninitialized values.
Related
I'm working on a program that takes user input two times. The user will input a sentence, and then enter a key phrase to remove each found match throughout the sentence, and return what's left. The code I have below for the 'logic' is...
char delim[AFFIX];
strcpy(delim, userInput); //storing the phrase user wants to remove
char *token = strtok(sentence, delim);
while (token)
{
cout << token << endl;
token = strtok(NULL, delim);
}
The issue I'm having is that strtok removes every single instance of a character found. For example, if the user wishes to remove all instances of 'pre' then the word "preformed" would turn into "fo m d" instead of formed. Is there a way to restrict strtok from removing EVERY instance of a character found, and only remove the series of characters?
I understand that working with strings or vectors would make my life much easier, but I want to work with arrays of chars. I'm really sorry if this isn't clear enough, I'm very new to c++. Any advice on how to approach this problem would be greatly appreciated. Thank you for your time.
A easy and more or less dirty solution would be to just add spaces before and after your search word. To ensure it's actually a full word and not part of a word.
Eg:
Input: "pre"
Check: " pre "
To ensure you also cut the first word you would need to check the first part of the string and add a space before it if the first word is also the inputted word.
Example:
#include <string>
#include <iostream>
void removeSubstrs(std::string& s, std::string& p) {
std::string::size_type n = p.length();
for (std::string::size_type i = s.find(p);
i != std::string::npos;
i = s.find(p))
s.erase(i, n);
}
void check(std::string& s, std::string& p) {
int slen = s.length();
int plen = p.length();
std::string firstpart = s.substr (0,plen);
std::string lastpart = s.substr (slen-plen,slen);
if (firstpart == p) {
s = " " + s;
}
if (lastpart == p) {
s += " ";
}
}
int main ()
{
std::string str = "pre test inppre test pre";
std::string search = "pre";
std::string pattern = " " + search + " ";
check(str, search);
removeSubstrs(str, pattern);
std::cout << str << std::endl;
return 0;
}
strtok isn't the right choice here, you can think of strtok's 2nd argument as a list of delimiters (each char in that list is a delimiter) and it breaks the string into tokens using those delimiters.
A better solution would be something along the lines of strstr and strcat.
maybe something like this (using MSVC++)
void removeSubstr(char *string, const char *sub, int n) {
char *match;
int len = strlen(sub);
while ((match = strstr(string, sub))) {
*match = '\0';
strcat_s(string, n, match + len);
}
}
int main() {
char test[] = "abcxyz123xyz";
removeSubstr(test, "xyz", sizeof(test) / sizeof(char));
cout << test << endl;
}
strcat_s is a more secure version of strcat (MSVC++ likes it way more than strcat :p)
There are better ways of doing this ofc but I'm restricting myself to char arrays here as you requested...
Suppose i have a string as below
input = " \\PATH\MYFILES This is my sting "
output = MYFILES
from RHS when first char '\' is found get the word (ie MYFILES) and erase the rest.
Below is my approach i tired but its bad because there is a Runtime error as ABORTED TERMINATED WITH A CORE.
Please suggest cleanest and/or shortest way to get only a single word (ie MYFILES ) from the above string?
I have searching and try it from last two days but no luck .please help
Note: The input string in above example is not hardcoded as it ought to be .The string contain changes dynamically but char '\' available for sure.
std::regex const r{R"~(.*[^\\]\\([^\\])+).*)~"} ;
std::string s(R"(" //PATH//MYFILES This is my sting "));
std::smatch m;
int main()
{
if(std::regex_match(s,m,r))
{
std::cout<<m[1]<<endl;
}
}
}
To erase the part of a string, you have to find where is that part begins and ends. Finding somethig inside an std::string is very easy because the class have six buit-in methods for this (std::string::find_first_of, std::string::find_last_of, etc.). Here is a small example of how your problem can be solved:
#include <iostream>
#include <string>
int main() {
std::string input { " \\PATH\\MYFILES This is my sting " };
auto pos = input.find_last_of('\\');
if(pos != std::string::npos) {
input.erase(0, pos + 1);
pos = input.find_first_of(' ');
if(pos != std::string::npos)
input.erase(pos);
}
std::cout << input << std::endl;
}
Note: watch out for escape sequences, a single backslash is written as "\\" inside a string literal.
This question already has answers here:
C's strtok() and read only string literals
(5 answers)
Closed 8 years ago.
I have a simple code where Iam trying to go through a char* and spit it into separate words. Here is the simple code I have.
#include <iostream>
#include <stdio.h>
int main ()
{
char * string1 = "- This is a test string";
char * character_pointer;
std::cout << "Splitting stringinto tokens:" << string1 << std::endl;
character_pointer = strtok (string1," ");
while (character_pointer != NULL)
{
printf ("%s\n", character_pointer);
character_pointer = strtok (NULL, " ");
}
return 0;
}
I am getting an error that will not allow me to do this.
So my question is, how do I go through and find each word in a char*. For my actual program I am working on, one of my libraries returns a paragraph of words as a const char* and I need to stem each word using a stemming algorithm (I know how to do this, I just do not know how to send each individual word to the stemmer). If someone could just solve how to get the example code to work, I will be able to figure it out. All of the examples online use a char[] for string1 instead of a char* and I cannot do that.
This is the simplest (codewise) way I know to split a string in c++:
std::string string1 = "- This is a test string";
std::string word;
std::istringstream iss(string1);
// by default this splits on any whitespace
while(iss >> word) {
std::cout << word << '\n';
}
or like this if you want to specify a delimiter.
while(std::getline(iss, word, ' ')) {
std::cout << word << '\n';
}
Here's a corrected version, try it out:
#include <iostream>
#include <stdio.h>
#include <cstring>
int main ()
{
char string1[] = "- This is a test string";
char * character_pointer;
std::cout << "Splitting stringinto tokens:" << string1 << std::endl;
character_pointer = strtok (string1," ");
while (character_pointer != NULL)
{
printf ("%s\n", character_pointer);
character_pointer = strtok (NULL, " ");
}
return 0;
}
There are different ways you could do this in C++.
If space is your delimited then you can get the tokens this way:
std::string text = "- This is a test string";
std::istringstream ss(text);
std::vector<std::string> tokens;
std::copy(std::istream_iterator<std::string>(ss),
std::istream_iterator<std::string>(),
std::back_inserter<std::vector<std::string>>(tokens));
You can also tokenize the string in C++ using regular expressions.
std::string text = "- This is a test string";
std::regex pattern("\\s+");
std::sregex_token_iterator it(std::begin(text), std::end(text), pattern, -1);
std::sregex_token_iterator end;
for(; it != end; ++it)
{
std::cout << it->str() << std::endl;
}
Forget about strtok. To get exactly what you seem to be
aiming for:
std::string const source = "- This is a test string";
std::vector<std::string> tokens;
std::string::const_iterator start = source.begin();
std::string::const_iterator end = source.end();
std::string::const_iterator next = std::find( start, end, ' ' );
while ( next != end ) {
tokens.push_back( std::string( start, next ) );
start = next + 1;
next = std::find( start, end, ' ' );
}
tokens.push_back( std::string( start, next ) );
Of course, this can be modified as much as you want: you can use
std::find_first_of is you want more than one separator, or
std::search if you want a multi-character separator, or even
std::find_if for an arbitrary test (with a lambda, if you have
C++11). And in most of the cases where you're parsing, you can
just pass around two iterators, rather than having to construct
a substring; you only need to construct a substring when you
want to save the extracted token somewhere.
Once you get used to using iterators and the standard
algorithms, you'll find it a lot more flexible than strtok,
and it doesn't have all of the drawbacks which the internal
state implies.
I've been looking thousand of questions and answers about what I'm going to ask, but I still didn't find the way to do what I'm gonna to explain.
I have a text file from which I have to extract information about several things, all of them with the following format:
"string1":"string2"
And after that, there is more information, I mean:
The text file is something like this:
LINE 1
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string1":"string2"XXXXXXXXXXXXXXXXXXXXXXXXXX"string3":"string4"XXXXXXXXXXXXXXXXXXXXXXXXXXXX...('\n')
LINE 2
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string5":"string6"XXXXXXXXXXXXXXXXXXXXXXXXXX"string7":"string8"XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
XXX represents irrelevant information I do not need, and theEntireString (string used in the code example) stores all the information of a single line, not all the information of the text file.
I have to find first the content of string1 and store the content of string2 into another string without the quotes. The problem is that I have to stop when I reache the last quote and I don't know how exactly do this. I suppose I have to use the functions find() and substr(), but despite having tried it repeatedly, I did not succeed.
What I have done is something like this:
string extractInformation(string theEntireString)
{
string s = "\"string1\":\"";
string result = theEntireString.find(s);
return result;
}
But this way I suppose I store into the string the last quote and the rest of the string.
"find" function just give you the position of matched string to get the resulting string you need to use the "subst" function. Try This
string start,end;
start = theEntireString.substr(1,theEntireString.find(":")-2);
end = theEntireString.substr(theEntireString.find(":")+2,theEntireString.size()-1);
That will solve you problem
Assuming either the key or value contains a quotation mark. The following will output the value after the ":". You can also use it in a loop to repeatedly extract the value field if you have multiple key-value pairs in the input string, provided that you keep a record of the position of last found instance.
#include <iostream>
using namespace std;
string extractInformation(size_t p, string key, const string& theEntireString)
{
string s = "\"" + key +"\":\"";
auto p1 = theEntireString.find(s);
if (string::npos != p1)
p1 += s.size();
auto p2 = theEntireString.find_first_of('\"',p1);
if (string::npos != p2)
return theEntireString.substr(p1,p2-p1);
return "";
}
int main() {
string data = "\"key\":\"val\" \"key1\":\"val1\"";
string res = extractInformation(0,"key",data);
string res1 = extractInformation(0,"key1",data);
cout << res << "," << res1 << endl;
}
Outputs:
val,val1
Two steps:
First we have to find the position of the : and splice the string into two parts:
string first = theEntireString.substr(0, theEntireString.find(":"));
string second = theEntireString.substr(theEntireString.find(":") + 1);
Now, we have to remove the "":
string final_first(first.begin() + 1, first.end() - 1);
string final_second(second.begin() + 1, second.end() - 1);
You don't need any string operation. I hope the XXXXX doesn't contain any '"', so You can read the both strings directly from the file:
ifstream file("input.txt");
for( string s1,s2; getline( getline( file.ignore( numeric_limits< streamsize >::max(), '"' ), s1, '"' ) >> Char<':'> >> Char<'"'>, s2, '"' ); )
cout << "S1=" << s1 << " S2=" << s2 << endl;
the little help-function Char is:
template< char C >
std::istream& Char( std::istream& in )
{
char c;
if( in >> c && c != C )
in.setstate( std::ios_base::failbit );
return in;
}
#include <regex>
#include <iostream>
using namespace std;
const string text = R"(
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string1":"string2"XXXXXXXXXXXXXXXXXXXXXXXXXX"string3" :"string4" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string5": "string6"XXXXXXXXXXXXXXXXXXXXXXXXXX"string7" : "string8" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
)";
int main() {
const regex pattern{R"~("([^"]*)"\s*:\s*"([^"]*)")~"};
for (auto it = sregex_iterator(begin(text), end(text), pattern); it != sregex_iterator(); ++it) {
cout << it->format("First: $1, Second: $2") << endl;
}
}
Output:
First: string1, Second: string2
First: string3, Second: string4
First: string5, Second: string6
First: string7, Second: string8
Running (with clang and libc++): http://coliru.stacked-crooked.com/a/f0b5fd383bc227fc
This is how raw string literals look in an editor that understand them: http://bl.ocks.org/anonymous/raw/9442865/
I'm trying to compare a char * to a to a std::string
const char *s = "0#s072116\tblah\tblah\blah";
std::string id = "072116";
I need to compare these two, basically before the first \t and after the first 3 chars on the left. The width of the id can vary. :(
I'm not very good at C++. Any ideas??
Thanks
You can do it as follows:
#include <iostream>
#include <string>
using namespace std;
...
int main() {
const char *s = "0#s072116\tblah\tblah\blah";
string ss = s;
string id = "072116";
int found = ss.find(id);
cout << "found is: " << found;
}
If id is a substring in ss, then found will be the position of the first occurrence of id in ss.
If id is not a substring in ss, then found will be a negative number.
More examples on find.
Caveat:
The code above is based on the assumption your meant "...basically before the first \t and after the first 3 chars on the left..." as a way to point out where the substring would be matched in this particular example.
If instead it is a requirement that must be met for all instances (i.e. const char *s = "0#s\tblah\tblah\blah072116" should not be matched), then the provided code sample is not sufficient.
const char *position = std::search(s, s + std::strlen(s), id.begin(), id.end());
if (*position == '\0')
std::cout << "Not found\n";
else
std::cout << "Found at offset " << (position - s) << '\n';