I'm trying to make a basic REPL that parse for special characters entered by a user. This post shows how to split on whitespace but I get this compiling error when I try to store the stringstream into the vector of strings.
repl.cpp: In function ‘int main(int, char**)’:
repl.cpp:52:25: error: range-based ‘for’ expression of type ‘std::__cxx11::basic_istringstream<char>’ has an ‘end’ member but not a ‘begin’
for (string s : iss)
^~~
repl.cpp:52:25: error: ‘std::ios_base::end’ cannot be used as a function
make: *** [repl.o] Error 1
Here is the full code below:
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
using namespace std;
int main(int argc, char *argv[])
{
size_t pos;
int pipe = 0;
int pid = 0;
vector <size_t> positions;
vector <string> arguments;
do
{
cout << "repl$ ";
getline(cin, cmd);
pos = cmd.find( "|", 0);
while ( pos != string::npos )
{
positions.push_back(pos);
pos = cmd.find( "|", pos+1);
pipe += 1;
pid += 1;
}
istringstream iss(cmd);
while (iss >> cmd)
arguments.push_back(cmd);
for (string s : iss)
cout << s << endl;
} while (cmd != "q");
return EXIT_SUCCESS;
}
You need to use a std::istream_iterator<std::string> to read successive strings. Boost has a wrapper to create a pseudo-container representing the sequence of objects read from an istream; for example:
for (const auto& s : boost::range::istream_range<std::string>(iss))
std::cout << s << '\n';
An alternative in this specific case would be to copy directly to an output iterator:
std::copy(std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>{},
std::ostream_iterator<std::string>{std::cout, '\n'});
Related
this is my code
the error is Segmentation fault,and i can't understand why
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char* szword[100];
int i = 0;
do
{
cin >> szword[i];
cout << szword[i];
i++;
}while(strcmp(szword[i - 1], "done"));
cout << i + 1;
return 0;
}
For starters neither declaration from headers <cstdio> and <string> is used in your program. So you should remove these directives
#include <cstdio>
#include <string>
You declared an initialized array with the element type char *. Thus this statement
cin >> szword[i];
invokes undefined behavior because the pointer szword[i] has indeterminate value.
Moreover this call even if the argument of the operator will be correct
cin >> szword[i];
can fail. You should check whether it was successful. And I think there is no great sense to output the string "done".
Also in this statement
cout << i + 1;
you are outputting a value that is greater than the number of inputted strings.
If to use character arrays then your program could look the following way
#include <iostream>
#include <cstring>
int main()
{
const size_t N = 100;
char szword[N][N];
size_t i = 0;
while ( std::cin.getline( szword[i], sizeof( szword[i] ) ) &&
std::strcmp( szword[i], "done" ) != 0 )
{
std::cout << szword[i++] << '\n';
}
std::cout << i << '\n';
return 0;
}
The program output might look like
Hello
World
2
This below code works fine, if you want to use char *, for C++ string you can use the C++ version
C Version:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char *tmp;
int i = 0;
do
{
cin >> tmp;
cout << tmp;
i++;
}while(strcmp(tmp, "done"));
cout << i + 1;
return 0;
}
C++ Version:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
string tmp;
int i = 0;
do
{
cin >> tmp;
cout << tmp;
i++;
}while(tmp != "done"));
cout << i + 1;
return 0;
}
I am using STL map in C++ for counting the frequency of words in a text file and words must be sort in lexicographic order. Input data is given as a text file. Ive already read and added them in map but i got a problem with sorting.
Example, i have { "Abc", "abc", "bag", "Boom", "great"}. When i added them in map, i got
Abc 1 Boom 1 abc 1 bag 1 great 1
but expected result is
Abc 1 abc 1 Boom 1 bag 1 great 1
#include <iostream>
#include <cstring>
#include <map>
#include <fstream>
using namespace std;
typedef map<string, int> word_count;
int main(){
word_count wc;
fstream f_in;
f_in.open("test.in");
string x;
while( !f_in.eof()){
f_in >> x;
wc[x]++;
}
f_in.close();
return 0;
}
Here is my code for reading input. Any help for my problem? Thanks
The OP wants a custom sort order that's subtly different from the standard lexicographical order. A map with a custom sort order can be achieved by passing in a custom Compare (Compare is the third template parameter of map):
#include <algorithm>
#include <cctype>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <vector>
using std::string;
using std::transform;
using std::map;
using std::cout;
struct Compare {
bool operator() (const string& s0, const string& s1) const {
// construct all lowercase versions of s0 and s1
string str0(s0.length(),' ');
string str1(s1.length(),' ');
transform(s0.begin(), s0.end(), str0.begin(), tolower);
transform(s1.begin(), s1.end(), str1.begin(), tolower);
if (!str0.empty() and !str1.empty() and str0.front()==str1.front()) {
// do a standard lexicographic sort if the first character is the same
return s0 < s1;
}
else {
// otherwise, do a case-insensitive lexicographic sort using the lowercased strings
return str0 < str1;
}
}
};
typedef map<string, int, Compare> word_count;
int main(){
word_count wc;
auto words = { "Abc", "abc", "bag", "Boom", "great"};
for (auto word : words)
wc[word]++;
for(auto elem : wc)
cout << elem.first << " " << elem.second << '\n';
return 0;
}
This indeed produces the desired output:
Abc 1
abc 1
Boom 1
bag 1
great 1
Try out a live version of the code online
By default, the third template parameter of a map is less<key> (in this case, less<string>), which will sort strings in the standard lexicographical A-z order.
Here is a complete example with file reading included, and using the base sorting functionality of std::map.
#include <iostream>
#include <cstring>
#include <map>
#include <fstream>
typedef std::map<std::string, int> word_count;
int main(int argc, char** argv){
if(argc < 2){
std::cout << "Please provide a file name." << std::endl;
return 1;
}
word_count wc;
std::ifstream inputfile(argv[1]);
if (inputfile.is_open()){
std::string x;
while(inputfile >> x){
wc[x]++;
}
inputfile.close();
}else {std::cout << "Program aborted: unable to open input file" << std::endl; return 1;}
for(auto word: wc){
std::cout << word.first << "\t" << word.second << std::endl;
}
return 0;
}
How can I change all \ to \\?
I want to make address to work with files:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string str = "C:\\user\\asd";
replace(str.begin(), str.end(), '\\', '\\\\');
cout << str;
return 0;
}
I am getting an error:
F:\c++\tests\regex\main.cpp|8|error: no matching function for call to 'replace(std::basic_string<char>::iterator, std::basic_string<char>::iterator, char, int)'|
How can I do this work with a char array in C++ (without a function)?
You are using std::replace(), which replaces values within a range of iterators. In this situation, you are using iterators from a std::string, so the value being searched for, and the value to replace it with, must both be single char values. However, '\\\\' is a multi-byte character, and thus can't be used as a char value. That is why you are getting the compiler error.
std::string has its own overloaded replace() methods, several of which can replace portions of the std::string with multi-character strings.
Try this instead, eg:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "C:\\user\\asd";
string::size_type pos = 0;
while ((pos = str.find('\\', pos)) != string::npos)
{
str.replace(pos, 1, "\\\\");
pos += 2;
}
cout << str;
return 0;
}
Live demo
However, you say you "want to make address to work with files", which implies to me that you want to create a file: URI. If so, then you need something more like this instead (this is a gross over-simplification, a proper URI generator would be more complex then this, as URIs have many rules to them, but this will get you started):
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
const char* safe_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~!$&'()*+,;=:#/";
int main()
{
string str = "C:\\user\\ali baba";
replace(str.begin(), str.end(), '\\', '/');
string::size_type pos = 0;
while ((pos = str.find_first_not_of(safe_chars, pos)) != string::npos)
{
ostringstream oss;
oss << '%' << hex << noshowbase << uppercase << (int) str[pos];
string newvalue = oss.str();
str.replace(pos, 1, newvalue);
pos += newvalue.size();
}
str = "file:///" + str;
cout << str;
return 0;
}
Live demo
I want to sort the string from N to M where N indicates the starting index and M indicates the ending index.
However, my code is getting failed with segmentation fault.
Here is my code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
string s;
int M=0,N=0;
cout<<"Enter String"<<endl;
getline(cin,s);
vector<char> data(s.begin(), s.end());
cout<<"Enter start_index and end_index for sorting";
cin>>N>>M; //Passed externally as N=start_index, M=end_index
std::sort(data.begin()+N, data.begin()+M, std::greater<char>());
for (std::vector<char>::const_iterator i = data.begin(); i != data.end(); ++i)
std::cout << *i << ' ';
return 0;
}
This example does work fine for me:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
string s = "ABCDEFG";
int N = 1;
int M = 5;
vector<char> data(s.begin(), s.end());
std::sort(data.begin() + N, data.begin() + M, std::greater<char>());
for (auto& character : data)
std::cout << character << ' ';
return 0;
}
http://coliru.stacked-crooked.com/a/ee7c5f05afe85115
I suspect you get an empty string with cin, and therefore your data.begin() is invalid.
Be cautious with user entered data. Always do proper checking for input that may break your code.
Additonally your templated greater is the comparing function for the wrong type.
The answer to the above question is from the guidance of Trevir.
In order to avoid the segmentation fault, check the size of the input
string and then apply operations on it.
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
string s;
int M,N;
cout<<"Enter String"<<endl;
getline(cin,s);
if ( s.size() == 0 )
{
std::cout << "Empty Input" << std::endl;
return 0;
}
vector<char> data(s.begin(), s.end());
cout<<"Enter start_index and end_index for sorting";
cin>>N>>M; //Passed externally as N=start_index, M=end_index
std::sort(data.begin()+N, data.begin()+M, std::greater<char>());
for (std::vector<char>::const_iterator i = data.begin(); i != data.end(); ++i)
std::cout << *i;
return 0;
}
So i'm trying to make a program for c++ that will split up text by spaces and I keep getting the error Access violation writing location 0x0120FA68. Here's the code:
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <list>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<char*> testVector;
char* string1 = "test f";
char seperators[] = " ";
char* token1;
char *next_token1;
int counter = 0;
token1 = strtok_s(string1, seperators, &next_token1);
while (token1 != NULL)
{
if (token1 != NULL)
{
std::cout << "\n" << token1 << std::endl;
testVector.push_back(token1);
token1 = strtok_s(NULL, seperators, &next_token1);
counter++;
}
}
std::cout << testVector.at(0);
system("pause");
return 0;
}
The strtok() family of functions modify their input strings. You are calling it on a string literal, which some compilers store in memory that is not user writeable. You can fix this by using strcpy() to copy the string literal into a buffer that you are then free to modify.