How to put an element of a string to a vector? - c++

I want to put specific elements of a string to a vector<string>.
To give you a better explanation of what i intend to do:
string str;
vector<string> in;
cin >> str; // input: abc
for(int i = 0;i < str.length();i++) {
in.push_back(&str[i]);
}
now i want the first element of vector<string> in to be "a" (in[0] = "a"), the second to be b etc.. i want to use strings for this. Is it possible to do it because when i print the vector it gives me that first it has abc then bc and in the end only c?

std::string has a constructor that takes a integral count and a single char to instantiate a string with n elements of the same value. You can use this and the fact that std::strings is much like a container of char:
for (auto c : str)
in.emplace_back(1ul, c);
Alternatively, you can store single char in the vector instead of std::string:
std::vector<char> in(str.begin(), str.end());

Either use std::vector<char> or use substr.
Example 1:
#include <string>
#include <iostream>
#include <vector>
int main()
{
std::string str;
std::vector<char> in;
std::cin >> str; // input: abc
for (std::string::size_type i = 0; i < str.length(); i++) {
in.push_back(str[i]);
}
}
Or a simpler variant:
int main()
{
std::string str;
std::cin >> str; // input: abc
std::vector<char> in(str.begin(), str.end());
}
Example 2:
#include <string>
#include <iostream>
#include <vector>
int main()
{
std::string str;
std::vector<std::string> in;
std::cin >> str; // input: abc
for (std::string::size_type i = 0; i < str.length(); i++) {
in.push_back(str.substr(i, 1));
}
}

Related

push_back all contents in vector<char> to combine them as the first element of vector<string>

I'm trying to parse a string with spaces into several strings and store them into a list, which consists of strings without any space. I do not know how long the input of the string will me and I have the following code:
#include <bits/stdc++.h>
#include <sstream>
using namespace std;
vector<string> myWords;
vector<char> myBuffer;
int main() {
string mySentence;
getline(cin, mySentence);
int j = 0;
for (int i = 0; i < mySentence.length(); i++) {
if (mySentence[i] != ' ') myBuffer.push_back(mySentence[i]);
else {
myWords.push_back(myBuffer);
myBuffer.clear();
j++;
}
}
return 0;
}
The error in which I'm getting is at myWords.push_back(myBuffer);. How do I get around this?
The problem is that you are trying to push a std::vector<char> where a std::string is expected. So simply change the type of myBuffer to a std::string:
#include <iostream>
#include <string>
int main() {
std::string mySentence;
std::getline(std::cin, mySentence);
std::vector<std::string> myWords;
std::string myBuffer;
for (int i = 0; i < mySentence.length(); i++) {
if (mySentence[i] != ' ')
myBuffer.push_back(mySentence[i]);
else {
myWords.push_back(myBuffer);
myBuffer.clear();
}
}
if (!myBuffer.empty()) {
myWords.push_back(myBuffer);
}
// use myWords as needed...
return 0;
}
That being said, using a std::istringstream would be much simpler, as operator>> reads whitespace-delimited values from a stream for you:
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::string mySentence;
std::getline(std::cin, mySentence);
std::vector<std::string> myWords;
std::string myBuffer;
std::istringstream iss(mySentence);
while (iss >> myBuffer) {
myWords.push_back(myBuffer);
}
// use myWords as needed...
return 0;
}
Alternatively, let the standard library handle the reading and pushing for you:
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
int main() {
std::string mySentence;
std::getline(std::cin, mySentence);
std::vector<std::string> myWords;
std::istringstream iss(mySentence);
std::copy(
std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(myWords)
);
// use myWords as needed...
return 0;
}

Counting occurrences of word in vector of characters

I have written a program to store a text file in vector of characters .
#include<iostream>
#include<fstream>
#include <algorithm>
#include<vector>
using namespace std;
int main()
{
vector<char> vec;
ifstream file("text.txt");
if(!file.eof() && !file.fail())
{
file.seekg(0, std::ios_base::end);
std::streampos fileSize = file.tellg();
vec.resize(fileSize);
file.seekg(0, std::ios_base::beg);
file.read(&vec[0], fileSize);
}
int c = count(vec.begin(), vec.end(), 'U');
cout << c;
return 0;
}
I want to count occurrence of "USER" in the text file , but using count i can only count number of characters . How can i count number of occurrences of "USER" in the vector of character?
For example
text.txt
USERABRUSER#$$* 34 USER ABC RR IERUSER
Then the count of "USER" is 4. Words can only be in uppercase.
std::string has a find member function that will find an occurrence of one string inside another. You can use that to count occurrences something like this:
size_t count(std::string const &haystack, std::string const &needle) {
auto occurrences = 0;
auto len = needle.size();
auto pos = 0;
while (std::string::npos != (pos = haystack.find(needle, pos))) {
++occurrences;
pos += len;
}
return occurrences;
}
For example:
int main() {
std::string input{ "USERABRUSER#$$* 34 USER ABC RR IERUSER" };
std::cout << count(input, "USER");
}
...produces an output of 4.
This is how I would do it:
#include <fstream>
#include <sstream>
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int main() {
unordered_map<string, size_t> data;
string line;
ifstream file("text.txt");
while (getline(file, line)) {
istringstream is(line);
string word;
while (is >> word) {
++data[word];
}
}
cout << data["USER"] << endl;
return 0;
}
Let's try again. Once again, a vector isn't necessary. This is what I would consider to be the most C++ idiomatic way. It uses std::string's find() method to repeatedly find the substring in order until the end of the string is reached.
#include <fstream>
#include <iostream>
#include <string>
int main() {
// Read entire file into a single string.
std::ifstream file_stream("text.txt");
std::string file_contents(std::istreambuf_iterator<char>(file_stream),
std::istreambuf_iterator<char>());
unsigned count = 0;
std::string substr = "USER";
for (size_t i = file_contents.find(substr); i != std::string::npos;
i = str.find(substr, i + substr.length())) {
++count;
}
}

How can I read the numbers in a char array as integers?

I want to pass dimension parameters of a matrix class as a char array, I can get the number of dimensions by counting the number of commas written in the parameters but I cant seem to read the numbers in a char as integers.
When I try to convert from char to int I get huge unrelated numbers. How can I read the numbers in a char array as integers?
template <class T>
matrix <T>::matrix (char * dimensions)
{
int nod = 0;
for(int i=0;dimensions[i];i++)
{
if (dimensions[i] == ',') nod++;
}
Number_of_dimensions = nod+1;
//...
}
You can use the following idea, illustrated with a rough pseudo-code snipper:
std::string s = "1234,4556";
//While you still have a string to parse
while (s.length()) {
//Use a comma to delimit a token
std::string delimiter = ",";
//Find the position of the comma or the end of the string
unsigned int comma_pos = s.find(delimiter);
//Find the sub-string before the comma
std::string token = s.substr(0, comma_pos); // token is "1234"
//Find your int
int i = std::stoi(token);
//"Eat" the token, continue
s.erase(0, comma_pos+1);
}
This is a particularly rough example, but the core idea is there: use std::string::substr() to find your sub-string with a comma delimiter, then convert the token to an int.
You also might want to consider looking for several delimiters, such as '\n'.
Split() function splits string by delimiter. In our case delimiter is comma. The number of elements is dimension. Than we convert each element to number using std::stringstream (C++98, or std::stoi in C++11).
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
std::vector<std::string> Split(const std::string &s, char delim)
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
elems.push_back(item);
return elems;
}
std::vector<int> GetDim(char *dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}
int main() {
std::string s = "1234,4556";
std::vector<int> d = GetDim(&*s.begin());
std::cout << "Dimensions: " << d.size() << std::endl;
std::cout << "Values: ";
for (size_t i = 0; i < d.size(); ++i) {
std::cout << d[i] << " ";
}
std::cout << std::endl;
return 0;
}
I suggest you not to use pointer as arguments. Use std::string or std::vector instead. Do not forget const qualifier. So GetDim() can be:
std::vector<int> GetDim(const std::string& dimensions)
{
std::vector<std::string> dim_str = Split(dimensions, ',');
std::vector<int> elems(dim_str.size());
for (size_t i = 0; i < dim_str.size(); ++i) {
std::stringstream ss(dim_str[i]);
ss >> elems.at(i);
}
return elems;
}

Initializer but incomplete type?

The following code gives me 2 errors when i compile
#include <iostream>
#include <fstream>
#include <cstring>
#include "Translator.h"
using namespace std;
void Dictionary::translate(char out_s[], const char s[])
{
int i;
char englishWord[MAX_NUM_WORDS][MAX_WORD_LEN];
for (i=0;i < numEntries; i++)
{
if (strcmp(englishWord[i], s)==0)
break;
}
if (i<numEntries)
strcpy(out_s,elvishWord[i]);
}
char Translator::toElvish(const char elvish_line[],const char english_line[])
{
int j=0;
char temp_eng_words[2000][50];
//char temp_elv_words[2000][50]; NOT SURE IF I NEED THIS
std::string str = english_line;
std:: istringstream stm(str);
string word;
while( stm >> word) // read white-space delimited tokens one by one
{
int k=0;
strcpy (temp_eng_words[k],word.c_str());
k++;
}
for (int i=0; i<2000;i++) // ERROR: out_s was not declared in this scope
{
Dictionary::translate (out_s,temp_eng_words[i]); // ERROR RELATES TO THIS LINE
}
}
Translator::Translator(const char dictFileName[]) : dict(dictFileName)
{
char englishWord[2000][50];
char temp_eng_word[50];
char temp_elv_word[50];
char elvishWord[2000][50];
int num_entries;
fstream str;
str.open(dictFileName, ios::in);
int i;
while (!str.fail())
{
for (i=0; i< 2000; i++)
{
str>> temp_eng_word;
str>> temp_elv_word;
strcpy(englishWord[i],temp_eng_word);
strcpy(elvishWord[i],temp_elv_word);
}
num_entries = i;
}
str.close();
}
}
The first one is at std::string istringstream stm(str); where it says it the variable has an initializer but incomplete type. If I put in std::string istringstream stm(str); it says expected initializer before stm andstm was not declared in the scope.
It also says out_s was not declared in this scope at Dictionary::translate (out_s,temp_eng_words[i]);. I don't see why one parameter is recognisied and one is not?
Thanks in advance.
You have to include header file:
#include <sstream>
#include <string>
when you want to use stringstream and string.
Meanwhile:
Dictionary::translate (out_s,temp_eng_words[i]);
If out_s is not a member of the class, you seems forgot to define out_s before using it inside toElvish.
Meanwhile:
while( stm >> word) // read white-space delimited tokens one by one
{
int k=0; //^^Why do you initialize k everytime you read a word?
strcpy (temp_eng_words[k],word.c_str());
k++;
}
You just need to include sstream
Your translator would be much simpler if you used std::map.
#include <map>
#include <string>
// map[english word] returns the elvish word.
typedef std::map<std::string, std::string> Dictionary;
// Define the dictionary
Dictionary english_to_elvish_dictionary;
std::string To_Elvish(const std::string& english_word)
{
Dictionary::iterator iter;
std::string elvish_word;
iter = english_to_elvish_dictionary.find(english_word);
if (iter != english_to_elvish_dictionary.end())
{
// English word is in dictionary, return the elvish equivalent.
elvish_word = *iter;
}
return elvish_word;
}
The above code fragment replaces most of your code and reduces your issues with arrays of arrays of C-strings. Less code == less problems.
To see a list of issues your having, search StackOverflow for "[c++] elvish english".

Tokenize a String in C++

I have a string currentLine="12 23 45"
I need to extract 12, 23, 45 from this string without using Boost libraries. Since i am using string, strtok fails for me. I have tried a number of things still no success.
Here is my last attempt
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
int countVar=0;
int inputArray[10];
char* tokStr;
tokStr=(char*)strtok(currentLine.c_str()," ");
while(tokstr!=NULL)
{
inputArray[countVar]=(int)tokstr;
countVar++;
tokstr=strtok(NULL," ");
}
}
}
the one without strtok
string currentLine;
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
cout<<atoi(currentLine.c_str())<<" "<<endl;
int b=0,c=0;
for(int i=1;i<currentLine.length();i++)
{
bool lockOpen=false;
if((currentLine[i]==' ') && (lockOpen==false))
{
b=i;
lockOpen=true;
continue;
}
if((currentLine[i]==' ') && (lockOpen==true))
{
c=i;
break;
}
}
cout<<b<<"b is"<<" "<<c;
}
Try this:
#include <sstream>
std::string str = "12 34 56";
int a,b,c;
std::istringstream stream(str);
stream >> a >> b >> c;
Read a lot about c++ streams here: http://www.cplusplus.com/reference/iostream/
std::istringstream istr(your_string);
std::vector<int> numbers;
int number;
while (istr >> number)
numbers.push_back(number);
Or, simpler (though not really shorter):
std::vector<int> numbers;
std::copy(
std::istream_iterator<int>(istr),
std::istream_iterator<int>(),
std::back_inserter(numbers));
(Requires the standard headers <sstream>, <algorithm> and <iterator>.)
You can also opt for Boost tokenizer ......
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int argc, char** argv)
{
string str= "India, gold was dear";
char_separator<char> sep(", ");
tokenizer< char_separator<char> > tokens(str, sep);
BOOST_FOREACH(string t, tokens)
{
cout << t << "." << endl;
}
}
stringstream and boost::tokenizer are two possibilities. Here is a more explicit solution using string::find and string::substr.
std::list<std::string>
tokenize(
std::string const& str,
char const token[])
{
std::list<std::string> results;
std::string::size_type j = 0;
while (j < str.length())
{
std::string::size_type k = str.find(token, j);
if (k == std::string::npos)
k = str.length();
results.push_back(str.substr(j, k-j));
j = k + 1;
}
return results;
}
Hope this helps. You can easily turn this into an algorithm that writes the tokens to arbitrary containers or takes a function handle that processes the tokens.