Sameer Manek
Sameer Manek

Reputation: 97

placing strings from a string vector into main string

I want to place strings from a string vector to a string. here's the code I have tried:

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>

using namespace std;

int main()
{
    const char* event = "this is %s, %s and %s";
    std::vector<string> strs = {"sam", "joey", "chandler"};
    char buffer[200];

    std::vector<string>::iterator it;

    for(it = strs.begin(); it < strs.end(); it++)
    {
        sprintf(buffer, event, it->c_str());
    }

    std::cout << buffer;
    return 0;
}

the result i expected is it will replace %s flags in event strings with strings inside strs vector. however i got Segmentation fault (core dumped) error.

can you please point out my mistake.

EDIT

the length of the vector is variable. I have a template of strings with variable number of %s flags and I am trying to write a function where we can pass a vector and replace those flags with strings in vector.

example of these strings are: "hello %s, meet %s" "welcome %s" "today is %s, and we want %s to work with you"

Upvotes: 2

Views: 164

Answers (4)

neutrino_logic
neutrino_logic

Reputation: 1299

aCraig5075 has the right approach I think. Here's something similar that utilizes the vector:

int main()
{
    std::string event {"this is %s, %s and %s"};
    std::string flag = "%s";
    std::vector<std::string> strs = {"sam", "joey", "chandler", "fred"};
    std::vector<std::string>::iterator it = strs.begin();
    std::size_t found = event.find(flag);
    while (it != strs.end() && found != std::string::npos) {  //terminates at shortest
        event.replace(found, flag.length(), *it);
        found = event.find(flag);
        ++it;
    }
    std::cout << event << std::endl;
}

This will play nicely if there is a mismatch between the number of flags in the string and the number of strings in the vector, halting the loop if either is exhausted.

Upvotes: 2

acraig5075
acraig5075

Reputation: 10756

Your mistake is that printf is plain inappropriate for what you want to do. I suggest simple substring "%s" search and replace. It's easy enough and surely safer.

std::string formatter(const char* event, const std::vector<string> &strs) {
    std::string buffer(event);

    size_t off = 0;
    for (auto placeholder : strs) {
        size_t i = buffer.find("%s", off);
        if (i == std::string::npos)
            break;

        buffer.erase(i, 2);
        buffer.insert(i, placeholder);
        off = i;
    }

    return buffer;
}

int main() {
    std::cout << formatter("this is %s, %s and %s", { { "sam", "joey", "chandler" } }) << "\n";
    std::cout << formatter("welcome %s", { { "sam", "joey", "chandler" } }) << "\n";
    std::cout << formatter("today is %s, and we want %s to work with you", { { "sam", "joey", "chandler" } }) << "\n";
}

Produces

this is sam, joey and chandler
welcome sam
today is sam, and we want joey to work with you

Upvotes: 4

Yunus Temurlenk
Yunus Temurlenk

Reputation: 4352

You can have a look at the usage of sprintf, and if you want to continue to use your code format, my approach is:

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>

using namespace std;

int main()
{

    const char* event = "this is %s, %s and %s";
    std::vector<string> strs = {"sam", "joey", "chandler"};
    char buffer[200];

    sprintf(buffer, event, strs[0].c_str(),strs[1].c_str(),strs[2].c_str());

    std::cout << buffer<<endl;
    return 0;
}

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490108

You're trying to make three separate calls to sprintf, but in each call you're passing it three %s conversions, so the first time it tries to print out three strings, even though you've only passed one. If it finished executing the first iteration, on the second iterations you'd do the same thing again: pass one string, but tell it to expect three. Same again the third time.

It's not at all clear to me why you'd do any of this though. You can produce the output you seem to want with code on this order:

std::vector<string> strs = {"sam", "joey", "chandler"};
std::cout << "This is: " << strs[0] << ", " << strs[1] << " and " << strs[2];

Upvotes: 1

Related Questions