How to Cut String C++ - c++

Hello i want to cut string in this situation:
if (std::count(text.begin(), text.end(), ',') > 3 {
//Cut String after 3 ','
}
text look like this:
"item1, item2, item3, item4, item5"
and i want this:
"item1, item2, item3, item4[Cut everything out on the right side >>], item5"
and return
"item1, item2, item3, item4"
Looking on first answer im looking for something like this(but working):
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
string s1 = "item1, item2, item3, item4, item5";
if(std::count(s1.begin(), s1.end(), ',') > 3) {
int comma = 0;
int x = sizeof(s1);
for(int i = 0; i < x; i++) {
if (comma == 3) {
string sub = s1.substr(0, i);
cout << "String is: " << sub;
}
if(s1[i] == ',') {
comma++;
}
}
}
return 0;
}

Look at std::string::substr
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
// Take any string
string s1 = "item1, item2, item3, item4, item5";
// Start at position 0 to position of character ',' in "item4,"
string sub = s1.substr(0, 26);
// prints item1, item2, item3, item4
cout << "String is: " << sub;
return 0;
}

You need to change little code as below.
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
string s1 = "item1, item2, item3, item4, item5";
int comma = 0;
int x = s1.length();
bool flag = false;
for(int i = 0; i < x; i++) {
if (comma == 4) {
string sub = s1.substr(0, i-1);
cout << "String is: " << sub;
flag = false;
return 0;
}
if(s1[i] == ',') {
comma++;
}
else{
flag = true;
}
}
if(flag)
cout<<"String not contain more then 3 comma's \n String is :: "<<s1;
return 0;
}

#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
string s1 = "item1, item2, item3, item4, item5";
if(std::count(s1.begin(), s1.end(), ',') > 3) {
int comma = 0;
int x = s1.length();
for(int i = 0; i < x; i++) {
if (comma == 3) {
string sub = s1.substr(0, i-1);
cout << "String is: " << sub;
return sub;
}
if(s1[i] == ',') {
comma++;
}
}
}
return 0;
}

There is no need to use std::count(), that is just wasted overhead. You are scanning the string twice when once would suffice.
Also, your use of sizeof() is wrong, you need to use std::string::size() instead. sizeof(s1) tells you the byte size of s1 (ie, of the std::string class itself) at compile-time, whereas s1.size() tells you how many characters are in s1 at runtime.
I suggest using std::string::find() in a loop, eg:
#include <string>
#include <iostream>
std::string cutAtNComma(const std::string &s, int n) {
std::string::size_type idx = 0;
while (n-- > 0) {
idx = s.find(',', idx);
if (idx == std::string::npos) break;
if (n == 0) return s.substr(0, idx);
++idx;
}
return s;
}
int main() {
std::string s1 = "item1, item2, item3, item4, item5";
std::string sub = cutAtNComma(s1, 4);
std::cout << "String is: " << sub;
return 0;
}
Live Demo
Alternatively, you can use std::find_if() instead, eg:
#include <string>
#include <iostream>
#include <algorithm>
std::string cutAtNComma(const std::string &s, int n) {
auto iter = std::find_if(s.cbegin(), s.cend(),
[n](char c) mutable {
if (c == ',') {
if (--n == 0) return true;
}
return false;
}
);
if (iter != s.cend()) return std::string(s.cbegin(), iter);
return s;
}
int main() {
std::string s1 = "item1, item2, item3, item4, item5";
std::string sub = cutAtNComma(s1, 4);
std::cout << "String is: " << sub;
return 0;
}
Live Demo

Related

How to take a function using stringstream to parse the numbers, and put them into an array?

So I am using stringstream in a function in c++ to take the numbers from a string, and then return the numbers to an array in main, but for some reason, they always return as 0 instead of the actual numbers. Code is below, does anyone know how to fix this?
int main()
{
for(int i = 0; i < userInput.length(); i++)
{
...
else
{
chemNumbers[i] = extractIntegerWords(userInput);
cout << chemNumbers[i] << endl;
}
}
int extractIntegerWords(string str)
{
stringstream ss;
int num = 0;
ss << str;
/* Running loop till the end of the stream */
string temp;
int found;
if(!ss.eof())
{
ss >> temp;
if (stringstream(temp) >> found)
{
num = found;
}
temp = "";
}
return found;
}
The original if statement doesn't pertain to the function only what is seen in the else statement, which is in main
This is off the top of my head and I don't have much time to test it, but this should put you in the right direction:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using std::cout;
using std::endl;
using std::istringstream;
using std::string;
using std::vector;
inline bool tryGetInt(const string& str, string& out) { istringstream sStream(str); return !(sStream >> out).fail(); } /*!< Tries to parse a string to int. */
void splitString(const string &str, const string &delimiters, vector<string> &tokens) {
// Skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
int32_t main(int argCount, char* argValues[]) {
for (int32_t i = 0; i < argCount; i++) {
cout << "Found argument " << argValues[i] << endl;
auto foundIntegers = getIntegerFromString(string(argValues[i]));
// Do whatever
}
return 0;
}
vector<int64_t> getIntegerFromString(string formula) {
vector<int64_t> foundInts;
string temp;
if (tryGetInt(formula, temp)) {
vector<string> intsAsStrings;
splitString(temp, " ", intsAsStrings);
for (auto item : intsAsStrings) {
foundInts.push_back(stol(item));
}
}
return foundInts;
}
Regular expression might help:
std::vector<std::pair<std::string, std::size_t>> Extract(const std::string& s)
{
std::vector<std::pair<std::string, std::size_t>> res;
const std::regex reg{R"(([a-zA-Z]+)(\d*))"};
for (auto it = std::sregex_iterator(s.begin(), s.end(), reg);
it != std::sregex_iterator();
++it)
{
auto m = *it;
res.push_back({m[1], m[2].length() == 0 ? 1 : std::stoi(m[2])});
}
return res;
}
int main()
{
for (auto p : Extract("C6H12O6")) {
std::cout << p.first << ": " << p.second << std::endl;
}
}
Demo
I add option for array instead vector for #I'mbadatCS
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
vector<int> extractIntegerWords(const string& _str)
//for array option: void extractIntegerWords(const string& _str, int* numArr)
{
stringstream ss;
ss << _str;
vector<int> vec;
string temp;
int found;
//for array option: int idx = 0;
while(!ss.eof())
{
ss >> temp;
if (stringstream(temp) >> found)
{
vec.push_back(found);
//for array option:numArr[idx++] = found;
}
temp = "";
}
return vec;
//for array option: return;
}
int main()
{
string s = "bla 66 bla 9999 !"
vector<int> res = extractIntegerWords(s);
for (int i = 0; i < res.size(); ++i)
{
cout << res[i] << ", " << endl;
}
}
a few comments:
const string& in input argument, not string. you don't want harm your source data
you need a loop not "if" (like ths the operation will run just one time)
where your array??
in C++ prefer use vector and not array

How to make sure that two strings only have certain alphabets in c++

Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.

why whould this while loop won't stop? c++

This is a code for reading in .txt file and spliting it by : and printing out the result. But I got stuck on the while-loop. This is my code.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
string* split(const string& str, const string& delim) {
string* string_list = new string[10];
int idx = 0;
char *token = strtok(const_cast<char*>(str.c_str()), delim.c_str());
while (token != NULL) {
string_list[idx] = token;
token = strtok(NULL, delim.c_str());
++idx;
}
return string_list;
}
struct Item {
string name;
string age;
string id;
string subject[10];
};
struct Item* create_item() {
struct Item* pitem = new Item;
return pitem;
};
void insert_item(struct Item *prev_item, struct Item *item) {
item = (prev_item + 5);
}
int main() {
string student, student2;
string *string_list, *subject, *string_list2, *subject2;
struct Item* pstudent, *pstudent2;
ifstream fin;
fin.open("input.txt");
fin >> student;
while (student != "\n") {
string_list = split(student, ":");
pstudent = create_item();
pstudent->name = *string_list;
pstudent->age = *(string_list + 1);
pstudent->id = *(string_list + 2);
subject = split(*(string_list + 3), ",");
for (int i = 0; i < 10; i++) {
if (*(subject + i) != "") {
pstudent->subject[i] = *(subject + i);
}
}
cout << *(string_list+1) << endl;
fin >> student2;
string_list = split(student2, ":");
pstudent2 = create_item();
insert_item(pstudent, pstudent2);
pstudent2->name = *(string_list);
pstudent2->age = *(string_list + 1);
pstudent2->id = *(string_list + 2);
subject2 = split(*(string_list + 3), ",");
for (int i = 0; i < 10; i++) {
if (*(subject2 + i) != "") {
pstudent2->subject[i] = *(subject2 + i);
}
}
}
cout << pstudent2->name << endl;
fin.close();
return 0;
}
I am still working on this code, but the while-loop in the main() will not stop. I wanted it to stop when the input.txt file input is a new line.
input.txt is
Mary:20:287:Math,Algorithm\n
Tom:21:202:Math,English\n
Hee:20:256:Math
thanks in advance!
Don't try to process more than one student in the body of the loop.
Rather than trying to write a linked-list type, use an existing collection type.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using strings_view = std::vector<std::string_view>;
strings_view split(std::string_view str, char delim) {
strings_view view;
while (str.size())
{
auto pos = str.find(delim);
view.push_back(str.substr(0, pos - 1));
str = str.substr(pos + 1);
}
return view;
}
struct Item {
std::string name;
std::string age;
std::string id;
std::vector<std::string> subject;
};
int main() {
std::vector<Item> students;
std::ifstream fin("input.txt");
for (std::string line; get_line(fin, line);) {
strings_view view = split(line, ':');
Item student;
student.name = view[0];
student.age = view[1];
student.id = view[2];
string_view subject = split(view[3], ',')
student.subject.assign(subject.begin(), subject.end());
students.push_back(student);
}
std::cout << students[1].name << std::endl;
return 0;
}

converting strings to integers by using "stringstream "

I am trying to convert strings of data to integers, (to use it for some calculations ) by using stringstream , but it fails when there is a space.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
if(stream >> ch) {
values.push_back(n);
}
else {
values.push_back(n);
}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
input : 1,182,08 51 15 --> output : 1 182 8 1 5
there are some digits lost after spaces.
so, what can I do to avoid it?
Complete working code based on seccpur's answer. Visual Studio 2017 Community:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define BUFSZ 100 // Set max size of the numbers as a single string
int convertToIntegers(char *s, vector<int> &values);
int main()
{
int count;
int i;
char data[BUFSZ];
vector<int> values;
strcpy_s(data, "1,182,08 51 15");
count = convertToIntegers(data, values);
// for (auto val : values) // Show the result
// cout << val << '\n';
// *** OR ***
for (i = 0; i < count; i++)
cout << values[i] << '\n';
}
//////////////////////////////////////
// Convert a C string to integers
//
int convertToIntegers(char *s, vector<int> &values)
{
vector<string> numbers;
char *next_token;
char* ptr = strtok_s(s, " -.,;", &next_token);
while (ptr)
{
string str(ptr);
numbers.push_back(str);
ptr = strtok_s(NULL, " -.,;", &next_token); // Next number
}
//
// Convert the resulting strings to integers
//
for (auto str : numbers)
values.push_back(stoi(str));
return (int)values.size();
}
If you know you have exactly one character as a separator, either a space, either a comma, the following code will work:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
char c = stream.get();
//if(stream >> ch) {
// values.push_back(n);
//}
//else {
values.push_back(n);
//}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
You are using multiple delimiters in the input ( like whitespace : , ; -) which complicates the matter. Here's a possible snippet using std::strtok:
//Enter a line
string line;
getline(cin, line);
// Convert string to char* so that std::strtok could be used later
char *cstr = new char[line.length() + 1];
std::strcpy(cstr, line.c_str());
vector<string> words;
// split line into multiple strings using multiple delimiters
char* ptr = std::strtok(cstr, " -.,;");
while (ptr)
{
string str(ptr);
words.push_back(str);
ptr = strtok(NULL, " -.,;");
}
delete[] cstr;
// Convert string to int
vector<int> values;
for (auto str : words){
values.push_back(std::stoi(str));
}
// Print the values
for (auto val : values){
cout << val << '\n';
}

How to insert an integer with leading zeros into a std::string?

In a C++14 program, I am given a string like
std::string s = "MyFile####.mp4";
and an integer 0 to a few hundred. (It'll never be a thousand or more, but four digits just in case.) I want to replace the "####" with the integer value, with leading zeros as needed to match the number of '#' characters. What is the slick C++11/14 way to modify s or produce a new string like that?
Normally I would use char* strings and snprintf(), strchr() to find the "#", but figure I should get with modern times and use std::string more often, but know only the simplest uses of it.
What is the slick C++11/14 way to modify s or produce a new string like that?
I don't know if it's slick enough but I propose the use of std::transform(), a lambda function and reverse iterators.
Something like
#include <string>
#include <iostream>
#include <algorithm>
int main ()
{
std::string str { "MyFile####.mp4" };
int num { 742 };
std::transform(str.rbegin(), str.rend(), str.rbegin(),
[&](auto ch)
{
if ( '#' == ch )
{
ch = "0123456789"[num % 10]; // or '0' + num % 10;
num /= 10;
}
return ch;
} // end of lambda function passed in as a parameter
); // end of std::transform()
std::cout << str << std::endl; // print MyFile0742.mp4
}
I would use regex since you're using C++14:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main()
{
std::string text = "Myfile####.mp4";
std::regex re("####");
int num = 252;
//convert int to string and add appropriate number of 0's
std::string nu = std::to_string(num);
while(nu.length() < 4) {
nu = "0" + nu;
}
//let regex_replace do it's work
std::regex_replace(std::ostreambuf_iterator<char>(std::cout),
text.begin(), text.end(), re, nu);
std::cout << std::endl;
return 0;
}
WHy not use std::stringstream and than convert it to string.
std::string inputNumber (std::string s, int n) {
std::stringstream sstream;
bool numberIsSet = false;
for (int i = 0; i < s; ++i) {
if (s[i] == '#' && numberIsSet == true)
continue;
else if (s[i] == '#' && numberIsSet == false) {
sstream << setfill('0') << setw(5) << n;
numberIsSet = true;
} else
sstream << s[i];
}
return sstream.str();
}
I would probably use something like this
#include <iostream>
using namespace std;
int main()
{
int SomeNumber = 42;
std:string num = std::to_string(SomeNumber);
string padding = "";
while(padding.length()+num.length()<4){
padding += "0";
}
string result = "MyFile"+padding+num+".mp4";
cout << result << endl;
return 0;
}
Mine got out of control while I was playing with it, heh.
Pass it patterns on its command line, like:
./cpp-string-fill file########.jpg '####' test###this### and#this
#include <string>
#include <iostream>
#include <sstream>
std::string fill_pattern(std::string p, int num) {
size_t start_i, end_i;
for(
start_i = p.find_first_of('#'), end_i = start_i;
end_i < p.length() && p[end_i] == '#';
++end_i
) {
// Nothing special here.
}
if(end_i <= p.length()) {
std::ostringstream os;
os << num;
const std::string &ns = os.str();
size_t n_i = ns.length();
while(end_i > start_i && n_i > 0) {
end_i--;
n_i--;
p[end_i] = ns[n_i];
}
while(end_i > start_i) {
end_i--;
p[end_i] = '0';
}
}
return p;
}
int main(int argc, char *argv[]) {
if(argc<2) {
exit(1);
}
for(int i = 1; i < argc; i++) {
std::cout << fill_pattern(argv[i], 1283) << std::endl;
}
return 0;
}
I would probably do something like this:
using namespace std;
#include <iostream>
#include <string>
int main()
{
int SomeNumber = 42;
string num = std::to_string(SomeNumber);
string guide = "myfile####.mp3";
int start = static_cast<int>(guide.find_first_of("#"));
int end = static_cast<int>(guide.find_last_of("#"));
int used = 1;
int place = end;
char padding = '0';
while(place >= start){
if(used>num.length()){
guide.begin()[place]=padding;
}else{
guide.begin()[place]=num[num.length()-used];
}
place--;
used++;
}
cout << guide << endl;
return 0;
}