I have an array of strings which need to be taken into a map. Since the array size is variable, I need a 2d vector to obtain the string character-wise. i need both formats of storage for operations i perform on them. Here's my attemp..gives errors in (EDIT:)run time.
#include "stdafx.h"
#include<iostream>
#include<string>
#include<fstream>
#include<map>
#include<vector>
#include<algorithm>
#include<iterator>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
std::map<int,string>col;
std::map<int,string>row;
std::map<int,string>::iterator p;
std::map<int,string>d1;
std::map<int,string>d2;
int main()
{
int i=0,r=0;
string s;
ifstream ip;
ip.open("a.in");
ofstream op;
op.open("a_out.in");
ip>>s;
const int c= s.length();
ip.seekg(0,std::ios::beg);
do {
ip>>s;row.insert(make_pair(r,s));
r++;
}while(s.length()==c);
p=row.find(--r);
row.erase(p);
p = row.begin();
while(p!=row.end())
{
cout<<(p->first)<<","<<(p->second)<<"\n";
p++;
}
vector<vector<char>>matrix(r,vector<char>(c));
rep(i,0,r){
int k=0;rep(j,0,c)(p->second).copy(&matrix[i][j],1,k++);
}
rep(i,0,r)
rep(j,0,c)
cout<<matrix[i][j];
return 0;
}
It looks like the problem occurs after you print out the map, before you copy the strings into the vector. You need two things:
while(p!=row.end())
{
cout<<(p->first)<<","<<(p->second)<<"\n";
p++;
}
p = row.begin(); // Must reset iterator!
vector<vector<char>>matrix(r,vector<char>(c));
rep(i,0,r){
int k=0;
rep(j,0,c)(p->second).copy(&matrix[i][j],1,k++);
++p; // Must advance the iterator.
}
That should fix the map/set iterator not dereferencable, as in the doubly nested for loop you referenced an invalid iterator (p was set to row.end()).
Edit:
Also, unless you can assume that all the strings are the same length, you might consider a different technique. When you use const int c = s.length(), you are telling the map<int,string> and vector<char> the length of EVERY string in your file are the exact same length. If the second string is shorter than the first, you will try to access characters in the string that don't exist! Note the
rep(j,0,c) (p->second).copy(&matrix[i][j],1,k++)
will fail since it thinks it has c characters, when it in fact will not.
Related
This is my code:
#include <iostream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
int main()
{
string word = "hi";
int i = 0;
vector<string> vec;
for(i ; i < word.length() ; i++)
{
vec.push_back(word[i]);
}
return 0;
}
I am trying to push each letter of string "hi" into a vector vec using for loop, but, it is throwing an error on the 14th line: "error: no matching function for call to ‘std::vector >::push_back(char&)’"
Indexed access ([] operator) on std::string returns char& and not std::string itself.
Vector declared is vector of string so insertion into vector requires string type not char&
If you want to have vector of char, change accordingly
You get the error because you have a vector of strings, not characters.
Change it to a vector of characters and it should work:
std::vector<char> vec;
As for what you're trying to do, there is a simpler way to do it:
std::vector<char> vec(begin(word), end(word));
The error lies in the fact that you have a std::vector of std::string's, but you are trying to push_back a char. There are multiple solutions to this:
Change your std::vector<string> to a std::vector<char>
Create a new std::string object every time you want to push_back a char like this (This is using an overloaded std::string constructor but there are many more possibilities.):
vec.push_back(string(1,word[i]));
Note: Please consider reading about Why is “using namespace std;” considered bad practice?.
I'm trying to make a list of stacks in C++ using the code below , but I'm getting the error
main.cpp:17:13: error: ‘__gnu_cxx::__alloc_traits > >::value_type {aka class std::stack}’ has no member named ‘push_back’
vs[i-1].push_back(s);
Code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<stack<int>> vs;
for(int i=1; i<4; i++)
{
stack<int> s;
s.push(i*2);
s.push(i*3);
s.push(i*4);
vs[i-1].push_back(s);
}
return 0;
}
you can't use this line:-
vs[i-1].push_back(s);
Either define the size of the list earlier.
For Eg
vector<stack<int> > vs(100);
else only write
vs.push_back(s);
Updated Solution
#include <iostream>
#include<stack>
#include<vector>
using namespace std;
int main()
{
vector< stack<int> > vs;
for(int i=1; i<4; i++)
{
stack<int> s;
s.push(i*2);
s.push(i*3);
s.push(i*4);
vs.push_back(s);
}
return 0;
}
First of all, your vector is empty, any indexing in it will be out of bounds and lead to undefined behavior.
Secondly, vs[any_valid_index] is a stack and not a vector.
What you probably want is
vs.push_back(s);
Its not a fact for only vector of stacks. It is actually basic property of vector. You have two options to add value into vector.
If you don't declare size of vector (what you did) like
vector<stack<int>> vs;
stack<int>s;
Then you can insert by using vs.push_back(s) It will automatically handle the index.
Another way is you can declare the size of the vector first. like
vector<stack<int>> vs(sz); //size(sz) is defined by user
stack<int>s;
Then you can insert by using vs[index]= s This time you have to manually handle the index.
The error says that no matching function to call for push_back().
I included <vector> so I don't understand why this error is occurring. If you could also show me how to take in a string and store it into a vector that would be really helpful!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> list;
char input;
while(cin>>input)
{
list.push_back(input);
}
for(int i=0;list.size();i--)
{
cout<<list[99-i];
}
}
Since your list is a vector of string, pushing single chars into it wouldn't work: you should either make it a vector of chars, or read strings:
string input;
while(cin>>input) {
list.push_back(input);
}
Note that list[99-i] is rather suspicious: it will work only if the list has exactly 99 elements, and only if you change i-- for i++. Otherwise, you would get undefined behavior either on accessing elements past the end of the vector, or accessing elements at negative indexes.
If you would like to print the list from the back, use list[list.size()-1-i] instead, and use i++ instead of i--, because otherwise the loop would not stop.
Well, the error is correct. It helps, though, to read all of it!
The class vector<string> has a function push_back(const string&).
It does not have a function push_back(char).
I don't know why you're extracting individual chars but storing whole strings; don't do that.
Because you are trying to put in char into a string vector.
Change input to string.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
string v;
vector<string> s;
for(int i=0;i<n;i++)
{
cin>>v;
s.push_back(v);
}
sort(s.begin(),s.end());
for(int i=0;i<n;i++)
{
cout<<s[i]<<endl;;
}
return 0;
}
This question already has answers here:
How to check if a string is in a list of strings?
(8 answers)
Closed 11 months ago.
#include <iostream>
#include <string>
using namespace std;
bool in_array(string value, string *array)
{
int size = (*array).size();
for (int i = 0; i < size; i++)
{
if (value == array[i])
{
return true;
}
}
return false;
}
int main() {
string tab[2] = {"sdasd", "sdsdasd"};
string n;
cin >> n;
if (in_array(n, tab)) {
}
return 0;
}
I want to check in C++ if n string is in tab array, but the code return an error.
What I am doing wrong? Maybe I should use the vectors?
int size = (*array).size();
It will not tell you the size of array, it tells you the length of first string in that array, you should pass the length of array to the function separately. The function should look like:
bool in_array(string value, string *array, int length)
But a better choice is using std::vector and std::find:
#include <vector>
#include <algorithm>
bool in_array(const std::string &value, const std::vector<std::string> &array)
{
return std::find(array.begin(), array.end(), value) != array.end();
}
and then, you can use it like:
std::vector<std::string> tab {"sdasd", "sdsdasd"};
if (in_array(n, tab))
{
...
}
When passing an array as an argument to a function which takes only a pointer, you can't query the size of the array within the function (since it got converted to a "stupid" pointer to the first element, nothing more). You typically add a "count" parameter to your signature or an "end" iterator instead.
What you're trying to implement is basically std::find. It takes two iterators (begin and end of the sequence) and the element to be found. Simply use this function.
std::find(std::begin(tab), std::end(tab), n);
will return an iterator to the element if it was found, the end iterator otherwise. Checking for equality with the end iterator will tell you if the element was found in the array.
If you don't like the "iterator interface" of the std algorithms, you can achieve your PHP-like signature by wrapping around std::find by using a template function:
template<class Element, class Container>
bool in_array(const Element & element, const Container & container)
{
return std::find(std::begin(container), std::end(container), element)
!= std::end(container);
}
Please note: This answer assumes C++11. If you use an older compiler, it might not work or it only works if you add -std=c++11 to the compiler flags.
masoud answer is correct but it overly complicated. all you need is this.
bool isInVect=false;
isInVect = std::find(vector.begin(), vector.end(), stringToFind) != vector.end();
if (isInVect == true)
{
cout << "Found string in Vector ..." << endl;
}
How can input a word and reverse the output of it. I made a function to calculate the length of the word and from here I have to reverse the word depending on the length of it.
How can I do that?
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
int LengthOfString( const char *); // declaring prototype for length of the string
int reverse(const char []);
int main()
{
char string1[100];
cout<<"Enter a string: ";
cin>>string1;
cout<<"Length of string is "<<LengthOfString(string1);
system("PAUSE");
return 0;
}
int LengthOfString( const char *x)
{
int index;
for(index = 0; *x!='\0';x++,index++);
return index;
}
int reverse(const char y[])
{
/* my attempted loop, its not right i know.
a[] = *index; // length of the word
for(int i=0; i<=index/2; i++)
for(j=0; j == length, j--) */
}
This wheel has already been invented, and exists in the standard library.
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string word;
std::cout << "Enter a word: ";
std::cin >> word;
std::reverse(word.begin(), word.end());
std::cout << "Reverse: " << word << std::endl;
return 0;
}
To understand exactly what's going on here, there are a few things that you must cover first:
data structures (classes)
containers
iterators
I hope you already know what a class is. In case you're still in introductory stuff, a class is basically a user defined collection of state and behavior. The author can choose to restrict access to the state or behavior of a class for a variety of reasons. In the case of std::string, the standard library string class, all of the state is hidden and only behavior is accessible.
The string class is a container that contains characters. There are numerous other container classes, each of which with different strengths and weaknesses. The string class contains a sequence of characters with a strict order. Other containers exist, such as std::set, std::vector, std::list, and others. std::string bears a passing resemblance to std::vector, and is a distant cousin of std::list. Each collection behaves differently and is suited for different things.
You might think you need to understand how the string class stores its data in order to reverse it, but you don't. This is where iterators come in. std::string owns a typedef, std::string::iterator, which is a special object which stores the location of a single element in a string. std::reverse is a library function which takes 2 iterators and repeatedly swaps their contents and moves them towards each other. This looks like this as it's happening:
v v <-- positions of iterators (start at the start, end at the end)
ABC <-- initial state
v v <-- the end iterator moved back
ABC
v v
CBA <-- the iterators swapped their values
vv <-- the begin iterator moved forward
CBA
V <-- the end iterator moved back; both iterators are in the same place
CBA <-- therefore, we're done, the string is reversed
One thing about iterators is they're kind of like pointers. In fact, you can pass pointers to some functions that expect iterators because they behave syntactically the same. Therefore, you should be able to write your own reverse function that uses pointers that basically does the same thing this did, except with char *s.
Here's some pseudocode that you should be able to write the function with (I won't write it out completely because it's homework):
namespace BaidNation
{
void reverse(char *begin, char *end)
{
loop forever
{
if (end equals begin):
done;
move end backwards;
if (end equals begin):
done;
swap end's and begin's characters;
move begin forwards;
}
}
}
Keep in mind that BaidNation::reverse (as well as std::reverse) expects for end the iterator that references the element AFTER the end of the collection, not the one that references the last element. How does it then make sense to use this?
Your LengthOfString function returns the number of non-null characters in a string. Since arrays are zero-indexed, we know that, like any other array, if we check string1 + LengthOfString(string1), we'll get a pointer to the character after the end which is, for once, exactly what we want.
Thus, we can use this to reverse the string:
BaidNation::reverse(string1, string1 + LengthOfString(string1));
If you have to use exactly the signature earlier, you can adapt this design into the other one:
int reverse(const char str[])
{
char *start = str, *end = str + LengthOfString(str);
BaidNation::reverse(start, end);
}
Based on the fact that the return type of your prototype function is int, it looks to me like you want to do an in-place reversal of a string. You first need to find out how long the string is (although you computed that before, you didn't pass the result to this function), then swap elements until you get to the middle. To make this work you need to pass, not a const char[], but just a char* (indicating that you will be changing the content):
int reverse(char* y)
{
int ii, n;
n = LengthOfString(y); // "no built in functions - otherwise, use strlen()
for(ii=0; ii<n/2;ii++) {
char temp;
temp = y[ii];
y[ii] = y[n - ii - 1];
y[n - ii] = temp;
}
}
Declare a new char* of the same length, and then loop as follows -
for(int i=0;i<stringLength;i++){
newString[i]=oldString[stringLength-i];
}
return newString;
Also you might want to consider using the String class instead of char*.