I am trying to write a program hat removes the character 'p' in Pineapple to output the word Pineale. Here is my current code. I found similar problems to this and thought this code would work but it is not unfortunately. Any help is appreciated!
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <limits>
using namespace std;
int main(){
remove(c,s);
}
string remove(char c, const string & s){
string s = "Pineapple";
char chars[] = "p";
for (unsigned int i = 0; i < strlen(chars); ++i)
{
s.erase(remove(s.begin(), s.end(), chars[i]), s.end());
}
cout << s << endl;
return s;
}
First, you did not define any c or s variables.
Second, your parameter in remove function is const, that means s is unchangeable.
The code below works in my VS2013.
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <limits>
using namespace std;
string remove(char* charToRemove, string &str){
//string s = "Pineapple";
//char chars[] = "p";
for (unsigned int i = 0; i < strlen(charToRemove); ++i)
{
str.erase(remove(str.begin(), str.end(), charToRemove[i]), str.end());
}
cout << str << endl;
return str;
}
int _tmain(int argc, _TCHAR* argv[])
{
string str("Pineapple");
char chars[] = "p";
remove(chars, str);
int i;
cin >>i;
}
Simply get the position of first 'p' from "Pineapple" using string::find(), then use string::erase(). No need to put string::erase() inside the loop.
string remove(char to_rem, string s) {
size_t pos = s.find( to_rem );
s.erase(pos, count(s.begin(), s.end(), to_rem) );
return s;
}
Modified code:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
string remove(char to_rem, string s) {
size_t pos = s.find( to_rem );
s.erase(pos, count(s.begin(), s.end(), to_rem) );
return s;
}
int main() {
cout << remove('p', "Pineapple");
}
Output:
Pineale
Try this:
struct slash_pred
{
char last_char;
slash_pred()
: last_char( '\0' ) // or whatever as long as it's not '/'
{
}
bool operator()(char ch)
{
bool remove = (ch == '/') && (last_char == '/');
last_char = ch;
}
};
path.erase( std::remove_if( path.begin(), path.end(),
slash_pred() ), path.end() );
Related
I'm a beginner with C++ and not too familiar with the language yet. So what would be the simplest way to fix my code? I think there's something wrong with userInput.insert(i, ""); but I'm not sure what.
Example: If the input is: -Hello, 1 world$!
The output would be: Helloworld
#include <iostream>
#include<string>
using namespace std;
int main() {
string userInput;
string lowerAlpha = "abcdefghijklmnopqrstuvwxyz";
string upperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
getline(cin, userInput);
for (int i = 0; i < userInput.size(); ++i) {
for (int j = 0; j < 26; ++j) {
if ((userInput.at(i) != lowerAlpha.at(j)) || (userInput.at(i) != upperAlpha.at(j))) {
userInput.insert(i, "");
}
}
}
cout << userInput << endl;
return 0;
}
If your compiler supports the C++ 20 then you can use standard function std::erase_if with a lambda as for example
#include <string>
#include <cctype>
//...
std::erase_if( userInput, []( unsigned char c ) { return not isalpha( c ); } );
Otherwise use the standard algorithm std::remove_if with the member function erase as for example
#include <string>
#include <iterator>
#include <algorithm>
#include <cctype>
//...
userInput.erase( std::remove_if( std::begin( userInput ),
std::end( userInput ),
[]( unsigned char c )
{
return not isalpha( c );
} ), std::end( userInput ) );
If to use your approach with for-loops then the code of the loops can look for example the following way
#include <iostream>
#include <string>
#include <string_view>
#include <cctype>
int main()
{
const std::string_view lowerAlpha = "abcdefghijklmnopqrstuvwxyz";
const std::string_view upperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::string userInput = "-Hello, 1 world$!";
std::cout << userInput << '\n';
for ( std::string::size_type i = 0; i < userInput.size(); )
{
if ( lowerAlpha.find( userInput[i] ) == std::string_view::npos &&
upperAlpha.find( userInput[i] ) == std::string_view::npos )
{
userInput.erase( i, 1 );
}
else
{
++i;
}
}
std::cout << userInput << '\n';
}
The program output is
-Hello, 1 world$!
Helloworld
My assignment says I should write a function called removeChar that;
Takes 4 inputs: an integer num, a string str, a string s and a character c, but does not return
anything.
Finds the number of all the occurrences of c in s (both capital and lower case (hint: you may
use ASCII codes for comparison)) and saves it in num
Copies the trimmed string in str
Write in the same file a main() function containing a series of tests to showcase the correct
behavior of removeChar ().
But all printing operations should be done from the main() function. I have this code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string removeChar(int num, string s, string str, char c);
int main()
{
string s = "asdfasdf";
s = removeChar(1, "a", "hello", 'h');
cout << s;
}
string removeChar(int num, string s, string str, char c)
{
int i;
for (i = 0; i < s.length(); i++)
if (int(s.at(i)) == int(c))
num = int(c);
str.erase(std::remove(str.begin(), str.end(), (char)num), str.end());
return str;
}
It doesn't work, and even if it did, I need to have a void function.
If I have understood the description of the assignment correctly,
then you need something like the following:
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <cctype>
void removeChar( std::string::size_type &n, std::string &str, const std::string &s, char c )
{
str.clear();
c = std::toupper( ( unsigned char )c );
auto equal_to_c = [&c]( const auto &item )
{
return std::toupper( ( unsigned char )item ) == c;
};
std::remove_copy_if( std::begin( s ), std::end( s ),
std::back_inserter( str ),
equal_to_c );
n = s.size() - str.size();
}
int main()
{
std::string::size_type n = 0;
std::string str;
removeChar( n, str, "This is a silly assignment", 's' );
std::cout << "n = " << n << ", str = " << str << '\n';
return 0;
}
The program output is:
n = 5, str = Thi i a illy aignment
I deleted my old post to be more precise. I'm using c++. I have a csv with ; as separator. With the following code i read a row, then i read all the elements of the row and convert them into int. My problem is that i need to convert them into int16_t or int32_t. The code is:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main (int argc, const char * argv[]) {
string line, csvItem;
ifstream myfile ("modifica1.csv");
int lineNumber = 0;
int lineNumberSought = 7462;
if (myfile.is_open()) {
while (getline(myfile,line)) {
lineNumber++;
if(lineNumber == lineNumberSought) {
istringstream myline(line);
string bus1s;
string bus2s;
string bus3s;
string bus4s;
string bus5s;
string bus6s;
string bus7s;
string bus8s;
string bus9s;
getline(myline,bus1s,';');
getline(myline,bus2s,';');
getline(myline,bus3s,';');
getline(myline,bus4s,';');
getline(myline,bus5s,';');
getline(myline,bus6s,';');
getline(myline,bus7s,';');
getline(myline,bus8s,';');
getline(myline,bus9s,'\n');
int bus1;
int bus2;
int bus3;
int bus4;
int bus5;
int bus6;
int bus7;
int bus8;
int bus9;
bus1=stoi(bus1s);
bus2=stoi(bus2s);
bus3=stoi(bus3s);
bus4=stoi(bus4s);
bus5=stoi(bus5s);
bus6=stoi(bus6s);
bus7=stoi(bus7s);
bus8=stoi(bus8s);
bus9=stoi(bus9s);
}
}
myfile.close();
}
return 0;
}
Here is an example of how to parse a csv file (with any separator) into a vector of tuples:
#include <sstream>
#include <vector>
#include <string>
#include <tuple>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
template<class... ColumnTypes>
class CsvRowParser
{
char const separator_;
template<size_t... Idxs>
std::tuple<ColumnTypes...>
convert_csv_row(std::vector<std::string> const& columns, std::integer_sequence<size_t, Idxs...>) {
return std::tuple<ColumnTypes...>{boost::lexical_cast<ColumnTypes>(boost::algorithm::trim_copy(columns[Idxs]))...};
}
public:
using RowType = std::tuple<ColumnTypes...>;
CsvRowParser(char separator)
: separator_(separator)
{}
RowType parse_row(std::string const& csv_row) {
std::vector<std::string> columns;
boost::algorithm::split(columns, csv_row, [this](char c) { return c == separator_; });
if(columns.size() != sizeof...(ColumnTypes))
throw std::runtime_error("Invalid csv row: " + csv_row);
return convert_csv_row(columns, std::make_index_sequence<sizeof...(ColumnTypes)>{});
}
};
int main() {
std::string my_csv;
my_csv += "abc, 1, 1.1\n";
my_csv += "def, 2, 2.2\n";
std::istringstream s(my_csv);
using Parser = CsvRowParser<std::string, int, double>;
Parser parser(',');
std::vector<Parser::RowType> rows;
for(std::string line; getline(s, line);)
rows.push_back(parser.parse_row(line));
}
There is a string like this: M90I4D7
I need to push it in to this kind of struct:
struct CigarOp {
char Type; //!< CIGAR operation type (MIDNSHPX=)
uint32_t Length; //!< CIGAR operation length (number of bases)
//! constructor
CigarOp(const char type = '\0',
const uint32_t& length = 0)
: Type(type)
, Length(length)
{ }
};
which means I need to split it into 3 groups and each of them is a CigarOp( 'M' ,90 'I', 4 'D' ,7 )
Assuming that the string is of the form ([A-Z][0-9]+)*, you could quite simply do something like this:
#include <sstream>
...
std::vector<CigarOp> cigars;
std::istringstream parser("M90I4D7");
char c;
std::uint32_t l;
while(parser >> c >> l) {
cigars.push_back(CigarOp(c, l));
}
Note that this code doesn't do any sort of validation. If validation is necessary, one way to achieve it is to use Boost.Spirit (found on http://boost.org):
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <cstdint>
#include <iostream>
struct CigarOp {
char Type;
std::uint32_t Length;
};
BOOST_FUSION_ADAPT_STRUCT(CigarOp, (char, Type) (std::uint32_t, Length))
int main() {
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::char_;
using boost::spirit::qi::uint_;
using boost::spirit::qi::standard::space;
std::vector<CigarOp> cigars;
std::string s = "M90I4D7";
std::string::const_iterator first = s.begin(), last = s.end();
bool r = phrase_parse(first, last, *(char_ >> uint_), space, cigars);
if(r && first == last) {
// string was well-formed
for(auto const &cigar : cigars) {
std::cout << cigar.Type << ", " << cigar.Length << '\n';
}
}
}
how about:
#include <cstdio>
#include <cctype>
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
struct CigarOp {
char op; //!< CIGAR operation type (MIDNSHPX=)
int size; //!< CIGAR operation length (number of bases)
static int parse(const char* s,vector<CigarOp>& v)
{
char* p=(char*)(s);
while(*p!=0)
{
char* endptr;
CigarOp c;
c.op = *p;
if(!isalpha(c.op)) return -1;
++p;
if(!isdigit(*p)) return -1;
c.size =strtol(p,&endptr,10);
if(c.size<=0) return -1;
v.push_back(c);
p=endptr;
}
return 0;
}
};
int main(int argc,char** argv)
{
vector<CigarOp> cigar;
if(CigarOp::parse("M90I4D7",cigar)!=0) return -1;
for(size_t i=0;i< cigar.size();++i)
{
cout << cigar[i].op << ":" << cigar[i].size << endl;
}
return 0;
}
btw , for bioinformatics, you should ask biostars.org.
I have a vector of strings. Need help figuring out how to convert it into vector of integers in order to be able to work with it arithmetically. Thanks!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
//HELP NEEDED HERE
//CONVERSION CODE from vector<string> to vector<int>
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
There are mulitple ways of converting a string to an int.
Solution 1: Using Legacy C functionality
int main()
{
//char hello[5];
//hello = "12345"; --->This wont compile
char hello[] = "12345";
Printf("My number is: %d", atoi(hello));
return 0;
}
Solution 2: Using lexical_cast(Most Appropriate & simplest)
int x = boost::lexical_cast<int>("12345");
Surround by try-catch to catch exceptions.
Solution 3: Using C++ Streams
std::string hello("123");
std::stringstream str(hello);
int x;
str >> x;
if (!str)
{
// The conversion failed.
}
Use boost::lexical_cast. And surround it with try-catch block.
try
{
for (size_t i=0; i<vectorOfStrings.size(); i++)
{
vectorOfIntegers.push_back(boost::lexical_cast<int>(vectorOfStrings[i]));
}
}
catch(const boost::bad_lexical_cast &)
{
//not an integer
}
Or you can use Boost.Spirit parser (which someone claims is faster than even atoi()) as:
int get_int(const std::string & s)
{
int value = 0;
std::string::const_iterator first = s.begin();
bool r = phrase_parse(first,s.end(),*int_[ref(value)=_1], space);
if ( !r || first != s.end()) throw "error";
return value;
}
//Usage
int value = get_int("17823");
std::cout << value << std::endl; //prints 17823
The full demo using your code : http://ideone.com/DddL7
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/lexical_cast.hpp>
using namespace std;
int stringToInteger(const std::string& s)
{
return boost::lexical_cast<int>(s);
}
int main(int /*argc*/, char* /*argv*/[])
{
vector<string> vectorOfStrings;
// ..
vector<int> vectorOfIntegers;
std::transform(vectorOfStrings.begin(), vectorOfStrings.end(), std::back_inserter(vectorOfIntegers), stringToInteger);
// ..
}
You can replace the implementation of stringToInteger(..) with your preferred conversion function.
Here is the working version made up using the above comments.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
int x;
for (int i=0; i<vectorOfStrings.size(); i++)
{
stringstream str(vectorOfStrings.at(i));
str >> x;
vectorOfIntegers.push_back(x);
}
int sum = 0;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
What about:
#include <algorithm>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
It can convert vector<string> into vector<int>, and also other container<T1> into container2<T2>, e.g.: list -> list.
Full code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
template<typename T, typename T2>
std::vector<T>& operator<<(std::vector<T>& v, T2 t)
{
v.push_back(T(t));
return v;
}
main(int argc, char *argv[])
{
std::vector<std::string> v1;
v1 << "11" << "22" << "33" << "44";
std::cout << "vector<string>: ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<std::string>(std::cout, ", "));
std::cout << std::endl;
std::vector<int> v2;
castContainer(v1, v2);
std::cout << "vector<int>: ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
There are two independent tasks.
Convert a single string to an integer
Having something that can convert from A to B, convert std::vector<A> to std::vector<B>
I suggest you try to do them separately, and then combine the results. If one of these tasks proves difficult, you will be able to ask a more focused question.
The most general way to convert strings to integers is with stringstream and a function template. You can optionally set the base for the conversion if you're dealing with hexadecimal. The boost library would also be helpful in your example.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/foreach.hpp>
/******************************************************************************
* Handy string to type conversion
* First parameter is the string to convert
* Second optional parameter is the number base, e.g. std::hex
*
* Because this is a function template, the compiler will instantiate one
* instance of the function per type
*****************************************************************************/
// the std::dec thingy is actually a function, so extra glue required.
typedef std::ios_base& (*ios_base_fn)( std::ios_base& str );
template <class T>
T strtotype( const std::string& s, ios_base_fn base = std::dec )
{
// C++ can't convert 8-bit values, they are *always* treated
// as characters. :( At least warn the user.
// this gives a cryptic error message, but better than nothing.
BOOST_STATIC_ASSERT( sizeof(T) > 1 );
T val;
std::istringstream iss(s);
iss >> base >> val;
if( iss.fail() )
throw std::runtime_error( "Error: strtotype(): Can't convert string '" + s + "' to numeric value" );
return val;
}
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
for( size_t i = 0; i < vectorOfStrings.size(); i++ )
vectorOfIntegers.push_back( strtotype<int>( vectorOfStrings[i] ));
// or better yet, use boost_foreach
BOOST_FOREACH( const string& s, vectorOfStrings )
vectorOfIntegers.push_back( strtotype<int>( s ));
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
If you don't want or can't use boost, you can remove the sizeof() check in strtotype. However, be careful never to try to convert to strings to individual bytes. Doing so will fail silently by only converting the first nibble of the byte.
If you're suing GNU tools, then compile like so:
g++ -Wall -O3 -I /path/to/boost/include main.cpp
or, if you delete the boost related bits:
g++ -Wall -O3 main.cpp