My trouble is that my function not always work, and i don't know why.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <string>
using namespace std;
void fill_zeros(std::string& fill_zeros_str, int fill_zeros_num){
if (fill_zeros_str.length()<fill_zeros_num){
int i = 0;
for (i=0;i<=((int)fill_zeros_num)-((int)fill_zeros_str.length());i++){
fill_zeros_str = "0"+fill_zeros_str;
}
}
}
int main(){
string testString = to_string(2);
fill_zeros(testString,7);
cout << testString << "\n";
return 0;
}
The second argument of fill_zeros (fill_zeros_num) does not work all the time, and I don't know why.
Because in
for (i=0;i<=((int)fill_zeros_num)-((int)fill_zeros_str.length());i++)
the length of fill_zeros_str changes as you add zeros(decrease by one), and you are also adding one to i(so, the start is adding by one, and the end is decreasing by one). So the best way is to define a length at the beginning of the function to store the string length.
Your loop is modifying the std::string on each iteration, which affects its length(). The loop is re-evaluating the length() on each iteration.
You need to calculate the number of zeros wanted and save that value to a local variable first, and then use that variable in your loop. Also, your loop needs to use < instead of <=.
Try this:
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
size_t fill_zeros_num = min_length - str.length();
for (size_t i = 0; i < fill_zeros_num; ++i){
str = "0" + str;
// or: str.insert(0, "0");
// or: str.insert(0, '0');
// or: str.insert(str.begin(), '0');
}
}
}
Live Demo
However, there is a much simpler way to implement fill_zeros() that doesn't involve using a manual loop at all:
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
str = std::string(min_length - str.length(), '0') + str;
// or: str.insert(0, std::string(min_length - str.length(), '0'));
// or: str.insert(str.begin(), std::string(min_length - str.length(), '0'));
// or: str.insert(0, min_length - str.length(), '0');
// or: str.insert(str.begin(), min_length - str.length(), '0');
}
}
Live Demo
Alternatively:
#include <sstream>
#include <iomanip>
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
std::ostringstream oss;
oss << std::setw(min_length) << std::setfill('0') << str;
str = oss.str();
}
}
Live Demo
In which case, you could simply get rid of fill_zeros() altogether and apply the I/O manipulators directly to std::cout in main() instead:
#include <iostream>
#include <iomanip>
int main(){
std::cout << std::setw(7) << std::setfill('0') << 2 << "\n";
return 0;
}
Live Demo
Related
I've been looking for ways to count the number of words in a string, but specifically for strings that may contain typos (i.e. "_This_is_a___test" as opposed to "This_is_a_test"). Most of the pages I've looked at only handle single spaces.
This is actually my first time programming in C++, and I don't have much other programming experience to speak of (2 years of college in C and Java). Although what I have is functional, I'm also aware it's complex, and I'm wondering if there is a more efficient way to achieve the same results?
This is what I have currently. Before I run the string through numWords(), I run it through a trim function that removes leading whitespace, then check that there are still characters remaining.
int numWords(string str) {
int count = 1;
for (int i = 0; i < str.size(); i++) {
if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') {
bool repeat = true;
int j = 1;
while (j < (str.size() - i) && repeat) {
if (str[i + j] != ' ' && str[i + j] != '\t' && str[i + j] != '\n') {
repeat = false;
i = i + j;
count++;
}
else
j++;
}
}
}
return count;
}
Also, I wrote mine to take a string argument, but most of the examples I've seen used (char* str) instead, which I wasn't sure how to use with my input string.
You don't need all those stringstreams to count word boundary
#include <string>
#include <cctype>
int numWords(std::string str)
{
bool space = true; // not in word
int count = 0;
for(auto c:str){
if(std::isspace(c))space=true;
else{
if(space)++count;
space=false;
}
}
return count;
}
One solution is to utilize std::istringstream to count the number of words and to skip over spaces automatically.
#include <sstream>
#include <string>
#include <iostream>
int numWords(std::string str)
{
int count = 0;
std::istringstream strm(str);
std::string word;
while (strm >> word)
++count;
return count;
}
int main()
{
std::cout << numWords(" This is a test ");
}
Output:
4
Albeit as mentioned std::istringstream is more "heavier" in terms of performance than writing your own loop.
Sam's comment made me write a function that does not allocate strings for words. But just creates string_views on the input string.
#include <cassert>
#include <cctype>
#include <vector>
#include <string_view>
#include <iostream>
std::vector<std::string_view> get_words(const std::string& input)
{
std::vector<std::string_view> words;
// the first word begins at an alpha character
auto begin_of_word = std::find_if(input.begin(), input.end(), [](const char c) { return std::isalpha(c); });
auto end_of_word = input.begin();
auto end_of_input = input.end();
// parse the whole string
while (end_of_word != end_of_input)
{
// as long as you see text characters move end_of_word one back
while ((end_of_word != end_of_input) && std::isalpha(*end_of_word)) end_of_word++;
// create a string view from begin of word to end of word.
// no new string memory will be allocated
// std::vector will do some dynamic memory allocation to store string_view (metadata of word positions)
words.emplace_back(begin_of_word, end_of_word);
// then skip all non readable characters.
while ((end_of_word != end_of_input) && !std::isalpha(*end_of_word) ) end_of_word++;
// and if we haven't reached the end then we are at the beginning of a new word.
if ( end_of_word != input.end()) begin_of_word = end_of_word;
}
return words;
}
int main()
{
std::string input{ "This, this is a test!" };
auto words = get_words(input);
for (const auto& word : words)
{
std::cout << word << "\n";
}
return 0;
}
You can use standard function std::distance with std::istringstream the following way
#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
int main()
{
std::string s( " This is a test" );
std::istringstream iss( s );
auto count = std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
std::cout << count << '\n';
}
The program output is
4
If you want you can place the call of std::distance in a separate function like
#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
size_t numWords( const std::string &s )
{
std::istringstream iss( s );
return std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
}
int main()
{
std::string s( " This is a test" );
std::cout << numWords( s ) << '\n';
}
If separators can include other characters apart from white space characters as for example punctuations then you should use methods of the class std::string or std::string_view find_first_of and find_first_not_of.
Here is a demonstration program.
#include <iostream>
#include <string>
#include <string_view>
size_t numWords( const std::string_view s, std::string_view delim = " \t" )
{
size_t count = 0;
for ( std::string_view::size_type pos = 0;
( pos = s.find_first_not_of( delim, pos ) ) != std::string_view::npos;
pos = s.find_first_of( delim, pos ) )
{
++count;
}
return count;
}
int main()
{
std::string s( "Is it a test ? Yes ! Now we will run it ..." );
std::cout << numWords( s, " \t!?.," ) << '\n';
}
The program output is
10
you can do it easily with regex
int numWords(std::string str)
{
std::regex re("\\S+"); // or `[^ \t\n]+` to exactly match the question
return std::distance(
std::sregex_iterator(str.begin(), str.end(), re),
std::sregex_iterator()
);
}
I am a beginner and I just need a bit of help on why I getline is showing an error:
this is what I have so far
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
const double TAX_RATE = 0.0825;
const int MAX_ITEMS = 1000;
const int MAX_TRANSACTIONS = 100;
int main(int argc, char const *argv[]){
string fname = "";
int itemCnt = 0, start = 0, end = 0;
int ids[MAX_ITEMS], qtys[MAX_ITEMS];
double costs[MAX_ITEMS], subtotals[MAX_TRANSACTIONS],
taxes[MAX_TRANSACTIONS], totals[MAX_TRANSACTIONS];
string names[MAX_ITEMS], paymentTypes[MAX_ITEMS], payments[MAX_ITEMS];
ifstream iFile;
if ( argc != 2 ) {
cout<<"usage: "<< argv[0]<< " <file name>" <<endl;
return 0;
} else {
iFile.open(argv[1]);
}
if (!iFile) {
cout<<"Error: Invalid file name"<<endl;
cin.clear();
}
while (!iFile.eof())
{
getline(iFile,str); //this isn't working
int commaLoc = str.find(',');
ids[itemCnt]= str.substr(0,commaLoc);
str = str.substr(commaLoc +1, str.length());
//string to int I'm not sure how to do I know its something with stoi() but not sure how to format it
}
return 0;
}
I am able to get the file to open but I'm not sure why getline isn't working it keeps saying something like
no instance of overload function
My csv file looks like:
1,Laptop,799.99,1,cash,1100
I need it to read the first number and because Its a string i don't know how to save it as an int
Multiple errors. First there is nothing called 'str' in your program. I will guess its just a string used as a temp buffer
do not do this (!File.eof) it doesnt do what you think.
while (iFile)
{
string str; <<<<<==== added
getline(iFile,str); //this isn't working <<<===is now
int commaLoc = str.find(',');
Next this line doesnt work because ids are ints and substring returns a string.
// ids[itemCnt]= str.substr(0,commaLoc);
ids[itemCnt]= stoi(str.substr(0,commaLoc)); <<<<==== fixed
str = str.substr(commaLoc +1, str.length());
}
I strongly recommend you use std::vector instead of c-style fixed size arrays. Takes 5 minutes to learn how to use them and they have huge benefits. If you must use fixed size arrays use std::array instead of c-style
You can read a string and try to convert it to a number in different ways. For example, since C++17, you can use from_chars. One of its overloads:
Receives a pair of begin and end char pointers, and an int variable,
tries to parse an int number, and
and returns the parsed number, together with a pointer to the first character that wasn't part of the match.
int i{};
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), i);
if (ec == std::errc{}) { /* do something with i */} else { /* error */ }
[Demo]
Full code (using a istrinstream instead of a ifstream):
#include <charconv> // from_chars
#include <iomanip>
#include <iostream>
#include <sstream> // istringstream
#include <system_error> // errc
constinit const int MAX_ITEMS = 10;
int main() {
std::istringstream iss{
"1,Laptop,799.99,1,cash,1100\n"
"2,PC,688.88,2,card,1101\n"
"blah,Keyboard,39.00,3,cash,1102"
};
size_t itemCnt{};
int ids[MAX_ITEMS]{};
std::string str{};
while (std::getline(iss, str)) {
// Parse counter
int i{};
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), i);
if (ec == std::errc{}) {
ids[itemCnt] = i;
// Remaining string
std::string remaining_string{ str.substr(ptr - str.data() + 1) };
std::cout << ids[itemCnt] << ", " << remaining_string << "\n";
}
else {
std::cout << "Error: invalid counter.\n";
}
++itemCnt;
}
}
// Outputs:
//
// 1, Laptop,799.99,1,cash,1100
// 2, PC,688.88,2,card,1101
// Error: invalid counter.
I want to make proggram wchich will be generete numbers in binary base from o to n, and i want thme all have the same numbers of chars.
That's the code:
#include <iostream>
#include <bitset>
#include <string>
#include <vector>
#include <cmath>
#include <stdio.h>
using namespace std;
vector<string> temp;
int BinaryNumbers(int number)
{
const int HowManyChars= ceil(log(number));
for(int i = 0; i<number; i++)
{
bitset<HowManyChars> binary(i);
temp.push_back(binary.to_string());
}
}
int main(){
BinaryNumbers(3);
for(int i=0; i<temp.size();i++)
{
cout<<temp[i]<<endl;
}
return 0;
}
My problem is that I can't set bitset<> number(HowManyChars)"[Error] 'HowManyChars' cannot appear in a constant-expression"
A possible solution is to use the maximum sized bitset to create the string. Then only return the last count characters from the string.
In C++17 there is a new function to_chars.
One of the functions (1), takes the base in the last parameter.
// use numeric_limits to find out the maximum number of digits a number can have
constexpr auto reserve_chars = std::numeric_limits< int >::digits10 + 1; // +1 for '\0' at end;
std::array< char, reserve_chars > buffer;
int required_size = 9; // this value is configurable
assert( required_size < reserve_chars ); // a check to verify the required size will fit in the buffer
// C++17 Structured bindings return value. convert value "42" to base 2.
auto [ ptr, err ] = std::to_chars( buffer.data(), buffer.data() + required_size, 42 , 2);
// check there is no error
if ( err == std::errc() )
{
*ptr = '\0'; // add null character to end
std::ostringstream str; // use ostringstream to create a string pre-filled with "0".
str << std::setfill('0') << std::setw(required_size) << buffer.data();
std::cout << str.str() << '\n';
}
I'm new to programming so I'm sorry if my question is hard to understand.
I have a string modelAnswer as such
string modelAnswer = "ABABACDA";
So it's supposed to be the answers to a quiz and I'm trying to make it so that if user's input is
string studentAnswer = "ABADBDBB"; for example the program will show that I have gotten 3 points as the first three letters of the studentAnswer string matches the modelAnswer.
You can use standard algorithm std::inner_product as for example
#include <iostream>
#include <string>
#include <numeric>
#include <functional>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(), modelAnswer.end(),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
The program output is
3
It is assumed that the strings have the same length. Otherwise you should use the less string as the first pair of arguments.
For example
#include <iostream>
#include <string>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iterator>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(),
std::next( modelAnswer.begin(), std::min( modelAnswer.size(), studentAnswer.size() ) ),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
If you are using standard strings, with the proper includes (Mainly #include <string>), you can write a simple for loop to iterate over each character, comparing them.
std::string answer = "ABABACDA";
std::string stringToCompare = "ABADBDBB";
int score = 0;
for (unsigned int i = 0; (i < answer.size()) && (i < stringToCompare.size()); ++i)
{
if (answer[i] == stringToCompare[i])
{
++score;
}
}
printf("Compare string gets a score of %d.\n", score);
The above code works for me, printing the following result:
Compare string gets a score of 3.
Using a stringstream, you can push one character at a time into temporary variables and test for equivalence in a loop.
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::istringstream model("ABABACDA");
std::istringstream student("ABADBDBB");
int diff = 0;
char m, s;
while ((model >> m) && (student >> s))
if (m != s) diff++;
std::cout << diff << std::endl; // 5
return 0;
}
I implemented the following code, which does what it's supposed to, but I think that it can / should be simplified.
Basically, I need to create a vector of numbers, each containing one of the digits found in testString. Is there any way to construct the stringstream directly from a char (i. e. testString[i])? I'd rather not involve C-style functions, like atoi, if it can be done in a C++ way.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main ()
{
std::string testString = "abc123.bla";
std::string prefix = "abc";
std::vector<unsigned short> digits;
if (0 == testString.find(prefix))
{
for (size_t i = prefix.size(); i < testString.find("."); ++i)
{
int digit;
std::stringstream digitStream;
digitStream << testString[i];
digitStream >> digit;
digits.emplace_back(digit);
}
}
for (std::vector<unsigned short>::iterator digit = digits.begin(); digit < digits.end(); ++digit)
{
std::cout << *digit << std::endl;
}
return 0;
}
Assuming testString[i] is between '0' and '9', just do:
digits.emplace_back(testString[i] - '0');
See my original comment; subtract '0' from each digit character.
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <functional>
#include <iostream>
...
std::string input = "abc123.bla";
std::string prefix = "abc";
std::vector<unsigned short> digits;
auto input_b = input.begin();
std::copy_if(input_b, std::find(input_b, input.end(), '.'),
std::back_inserter(digits), (int (*)(int)) std::isdigit);
auto digits_b = digits.begin();
auto digits_e = digits.end();
std::transform(digits_b, digits_e, digits_b,
std::bind2nd(std::minus<unsigned short>(), '0'));
std::copy(digits_b, digits_e,
std::ostream_iterator<unsigned short>(std::cout, "\n"));
It can even be shortened if you don't need digits to contain the intermediate digit values.
std::transform(digits.begin(), digits.end(),
std::ostream_iterator<unsigned short>(std::cout, "\n"),
std::bind2nd(std::minus<unsigned short>(), '0'));