first repeated word in a sentence - c++11

I'm not sure where the bug is. I'm trying to find the first repeated word in a string where the delimiters are a space, tab, comma, colon, semicolon, dash, and period.
Does anyone see what I'm sure is an obvious error?
std::string repeat(std::string str) {
std::set<std::string> seen;
str.insert(str.end(), ' ');
std::string tmp;
for (auto const& s : str) {
if (s != ' '&&
s != '\t'&&
s != '.'&&
s != ','&&
s !=':'&&
s != ';'&&
s != '-')
tmp += s;
else {
if (seen.find(tmp) != seen.end())
return tmp;
else {
seen.insert(tmp);
tmp.clear();
}
}
}
return "no repeats";
}

The code as you've written here works fine, as per https://ideone.com/sbsUeI
Your problem is elsewhere. Perhaps check the input string in a debugger and see what is being passed.
Test program (from link):
#include <iostream>
#include <string>
#include <set>
using namespace std;
std::string repeat(std::string str) {
std::set<std::string> seen;
str.insert(str.end(), ' ');
std::string tmp;
for (auto const& s : str) {
if (s != ' '&&
s != '\t'&&
s != '.'&&
s != ','&&
s !=':'&&
s != ';'&&
s != '-')
tmp += s;
else {
if (seen.find(tmp) != seen.end())
return tmp;
else {
seen.insert(tmp);
tmp.clear();
}
}
}
return "no repeats";
}
int main() {
std::cout << repeat("cat dog cat man"); // prints "cat"
return 0;
}

Related

SIGSEGV Fault in infix to postfix using stack

When I tried making if condition to while loop to remove more than one operator from stack in bracket (f+g/h) here output should be (fgh/+) but i am not able to run the code with while loop my output is coming (fgh/) due to if condition , how do I put while loop without SIGSEGV, im getting run-time error SIGSEGV ?
#include<bits/stdc++.h>
using namespace std;
class Solution
{
public:
//Function to convert an infix expression to a postfix expression.
string infixToPostfix(string s)
{
// Your code here
stack<char> op;
string res;
int i=0;
while(i<s.length()){
if(s[i]>='a' && s[i]<='z' || s[i]>='A' && s[i]<='Z' ){
res.push_back(s[i]);
cout<<res<<" ";
}
else if(s[i]=='(')
op.push(s[i]);
else if(s[i]==')'){
if(op.top()!='('){ //here SIGSEGV I want this in while loop not if statement
res.push_back(s[i]);
op.pop();
cout<<res<<" ";
}
op.pop();
}
else {
if(op.empty())
op.push(s[i]);
else if(precedence(s[i])>precedence(op.top()))
op.push(s[i]);
else if(precedence(s[i])<precedence(op.top())){
while(precedence(s[i])<precedence(op.top())){
res.push_back(op.top());
op.pop();
}
op.push(s[i]);
}
else{
res.push_back(op.top());
op.pop();
op.push(s[i]);
}
}
i++;
}
return res;
}
int precedence(char a) //precedence function
{
if (a == '^')
return 3;
else if (a == '*' || a == '/')
return 2;
else if (a == '+' || a == '-')
return 1;
else if (a == '(' || a == ')')
return 0;
}
};
int main(){
int t;
t=1;
cin.ignore(INT_MAX, '\n');
while(t--){
string exp;
cin>>exp;
Solution ob;
cout<<ob.infixToPostfix(exp)<<endl;
}
return 0;
}

How to extract different datatype data from an ASCII array using templates

I'm trying to extract different datatype data from an ASCII array using templates where each datatype data is separated by a delimiter(':' in this case) also each datatype data can be preceded and succeeded by whitespaces which needs to removed. But I'm getting template instantiation error. Can somebody enlighten me how to accomplish this task. This is my sample code:
#include<iostream>
#include<string>
#include<cstring>
class Extract {
public:
inline Extract() {
length = 0;
std::memset(recvBuff, '\0', sizeof(recvBuff));
}
inline ~Extract() {
}
int length;
unsigned char recvBuff[1024];
template<typename T>
void extractData(short& start, short& end, T& val, char delimiter, short dataType) {
while(end <= length) {
if(recvBuff[end] == delimiter)
break;
end++;
}
if(end >= length)
return;
std::string token(recvBuff[start + 1], end - start - 1);
std::string trimmedToken;
std::string::size_type first = token.find_first_not_of(" \n\r\t\f\v");
std::string::size_type last = token.find_last_not_of(" \n\r\t\f\v");
if((first == std::string::npos) || (last == std::string::npos))
return;
else
trimmedToken.assign(token, first, (last - first + 1));
if(dataType == 1) { //char
if(trimmedToken.size() == 1)
val = trimmedToken.at(0);
}
else if(dataType == 2) { //int
if(trimmedToken.size() > 0)
val = std::stoi(trimmedToken);
}
else if(dataType == 3) { //float
if(trimmedToken.size() > 0)
val = std::stod(trimmedToken);
}
else if(dataType == 4) { //std::string
val.assign(trimmedToken);
}
}
};
int main(int argc, char* argv[]) {
//"contains mixed ascii data of char, int, float separated by :" for example
//" CMD : 123 : 3453.45646 : REP : T : 2424 : 3424 : 803424.2312 "
char buff[1024];
Extract objExtract;
objExtract.length = 60; // some dummy value for time being
std::memcpy(objExtract.recvBuff, buff, objExtract.length);
short start = 0;
short end = 1;
std::string data1;
objExtract.extractData(start, end, data1, ':', 4);
int data2;
objExtract.extractData(start, end, data2, ':', 2);
double data3;
objExtract.extractData(start, end, data3, ':', 3);
std::string data4;
objExtract.extractData(start, end, data4, ':', 4);
char data5;
objExtract.extractData(start, end, data5, ':', 1);
int data6;
objExtract.extractData(start, end, data6, ':', 2);
int data7;
objExtract.extractData(start, end, data7, ':', 2);
double data8;
objExtract.extractData(start, end, data8, ':', 3);
std::cout << data1 << "\t" << data2 << std::endl;
return 0;
}
When you call extractData for example for data2 the code
else if(dataType == 4) { //std::string
val.assign(trimmedToken);
}
is compiled. Type of val is int&. You got error because int doesn't have assign method.
With C++17 you can use if constexpr (condition) { block }, where condition is known at compile-time, if it is true, {block} will be compiled.
You can change signature of function to be:
template<typename T>
void extractData(short& start, short& end, T& val, char delimiter) {
and if block can be rewritten:
if constexpr (std::is_same_v<T,char>) { //char
if(trimmedToken.size() == 1)
val = trimmedToken.at(0);
}
else if constexpr(std::is_same_v<T,int>) { //int
if(trimmedToken.size() > 0)
val = std::stoi(trimmedToken);
}
else if constexpr (std::is_same_v<T,float>) { //float
if(trimmedToken.size() == 1)
val = std::stod(trimmedToken);
}
else if constexpr (std::is_same_v<T,std::string>) { //std::string
val.assign(trimmedToken);
}
you don't need to pass dataType, because it can be deduced from third parameter.
Under C++11 you can declare function template which does conversion, and you have to provide specialization for all types you want to support:
template<class T>
void convert(std::string, T&);
template<>
void convert<char>(std::string trimmedToken, char& val) {
if(trimmedToken.size() > 0)
val = std::stoi(trimmedToken);
}
template<>
void convert<int>(std::string trimmedToken, int& val) {
if(trimmedToken.size() > 0)
val = std::stoi(trimmedToken);
}
template<>
void convert<float>(std::string trimmedToken, float& val) {
if(trimmedToken.size() == 1)
val = std::stod(trimmedToken);
}
template<>
void convert<std::string>(std::string trimmedToken, std::string& val) {
val.assign(trimmedToken);
}
then remove if block and replace it by one line:
convert(trimmedToken,val);
when you call convert with val which is not supported by specializations, you will get linker's error. So you need to add version for double.

C++ .exe has stopped working - error in code

I wrote a small program in c++, and it doesn't have any error on compile time but when I run the program, I'm facing with an error.
Following is my code :
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include "QueType.h"
#include "StackType.h"
#include "tools.hpp"
#include <locale>
#include <list>
using namespace std;
bool isPalindrome(const string& stringToCheck)
{
string line2;
bool pal;
string wrdF;
stack<char> word1;
queue<char> word2;
char x,y;
line2=stringToCheck;
// make lowercase
for (size_t j=0; j< line2.length(); ++j)
{
line2[j] = tolower(line2[j]);
}
std::locale loc;
std::string str = line2 ;
std::string::size_type al=0;
wrdF = "";
std::string::size_type al2 = 0;
while ( (al<str.length()) ) {
if (std::isalnum(str[al])) {
wrdF += str[al];
al2++;
}
++al;
}
ItemType* items = new ItemType[al2];
strcpy(items,wrdF.c_str());
int oo=(int)al2;
for (int q=0;q<oo ;q++)
{
if (items[q] != ' ') {
word1.push(items[q]);
word2.push(items[q]);
}
}
pal = true;
while (!word1.empty() && !word2.empty())
{
x=word1.top();
y=word2.front();
if (x != y)
{
cout << "No palindrome" << endl;
pal=false;
break;
}
else
{
word1.pop();
word2.pop();
}
}
if (pal == true)
cout << " palindrome" << endl;
return(pal);
}
int main()
{
int row=0;
string line;
bool pali;
ifstream myfile ("palindrome-testfile.txt");
ofstream palin("palindromes.log");
ofstream nopalin("nopalindromes.log");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
// cout << line << '\n';
++row;
// cout<<row<<". ";
pali= isPalindrome(line);
if (pali)
{
palin << line << endl;
}
else
{
nopalin << line << endl;
}
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Please help me to resolve it. Thanks in advance.
Capture of error
As Igor Tandetnik pointed out the problem is with the ItemType pointer. Which also leaks memory.
I wrote a similar code that checks if a word is palindrome. The cppreference example for std::equal is a is_palindrome function.
I am not sure about why you need the step for std::isalnum. That one will return true for numbers too. std::isalpha will return true only if they are are letters, see cppreference doc for isalpha
Let me know if you need any clarifications.
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
bool isPalindrome(const std::string& str) {
return std::equal(str.begin(), str.begin() + str.size() / 2, str.rbegin());
}
int main() {
std::ifstream myfile("palindrome-testfile.txt");
if(!myfile.is_open()) {
std::cerr<< "Could not open file" << std::endl;
} else {
std::string word;
//operator >> will read words until you reach eof()
myfile >> word;
while(!myfile.eof()){
auto str = word;
//here I delete anything that is not alnum
str.erase(std::find_if(str.begin(), str.end(),
[](unsigned char c) { return !std::isalnum(c); }));
//Making all characters of the string lower case
std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); });
if(isPalindrome(str)) {
std::cout << "[" << str <<"] is palindrome" << std::endl;
} else {
std::cout << "[" << str <<"] is not palindrome" << std::endl;
}
myfile >> word;
}
myfile.close();
}
return 0;
}

Converting Infix to Postfix Using Stack

I'm having trouble creating a program that will convert infix to postfix. My code is as follows:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define DEFAULT_SIZE 20
/*
*
*/
class Stack {
char *arr;
int tos, capacity;
public:
//Constructors
Stack();
Stack(int size);
//Destructor
~Stack();
//Methods
void push(char a);
char pop();
int get_size();
bool is_empty();
bool is_full();
void display();
char get_top();
};
Stack::Stack() {
arr = new char[DEFAULT_SIZE];
tos = 0;
capacity = DEFAULT_SIZE;
}
Stack::Stack(int size) {
arr = new char[size];
tos = 0;
capacity = size;
}
Stack::~Stack() {
delete[] arr;
}
void Stack::push(char a) {
if (!is_full())
arr[tos++] = a;
else
cout << "Sorry, the stack is full. Push failed!" << endl;
}
char Stack::pop() {
if (!is_empty())
return arr[--tos];
else {
cout << "Sorry, the stack is empty. Pop failed!" << endl;
return -1;
}
}
char Stack::get_top() {
if (!is_empty())
return arr[tos - 1];
else {
cout << "Sorry, the stack is empty. Pop failed!" << endl;
return 'E';
}
}
int Stack::get_size() {
return tos;
}
bool Stack::is_empty() {
if (tos == 0)
return true;
else
return false;
}
bool Stack::is_full() {
if (tos == capacity)
return true;
else
return false;
}
void Stack::display() {
if (tos == 0)
cout << "The stack is empty" << endl;
else {
for (int i = 0; i<tos;i++)
cout << arr[i] << " ";
cout << endl;
}
}
int main() {
Stack stack(50);
string infix = "(1+3)*2/(6-4)^2";
stringstream ss;
for (char c : infix) {
if ('0' <= c && c <= '9') {
ss << c;
}
else if (c == '(') {
continue;
}
else if (c == ')') {
ss << stack.pop();
stack.pop();
}
else if (c == '^' || c == '*' || c == '/' || c == '+' || c == '-') {
stack.push(c);
}
}
string postfix = ss.str();
cout << postfix;
I know what my issue is, I just dont understand or comprehend how to solve it. This code currently outputs 13+264-2. It needs to output 13+2*64-2^/. I know my issues is with my last else if statement in int main(). I dont understand how to rearrange the operators behind the operands.
Anything in parentheses is passed into the stream correctly, because I can wait until the closing parenthesis is hit to add in the operator. I can't visualize how to make that work for things not in parentheses though. Can anyone offer any advice?

Extract IP from text file C++

Im a new programmer in C++ and I want to creat a code that extract IP from text files
I tried to convert txt file to Vector(string) to be easy filtering but i cant get all formes like XXX.XXX.XXX.XXX
Given that the ip could be embedded in some text, we'll parse the string and fetch it.
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <sstream>
using namespace std;
string ip(string str)
{
//middle portion
auto firstDot = str.find_first_of('.');
auto lastDot = str.find_last_of('.');
int dotCount = 0;
for(auto i = firstDot; i <= lastDot; i++)
{
if(!isdigit(str.at(i)) && str.at(i) != '.') //e.g 127.ss.0y.1
return string("");
if(str.at(i) == '.')
dotCount++;
}
if(dotCount != 3) //eg. 127.0.1 (not sure if this is wrong though)
return string("");
string result = str.substr(firstDot,lastDot-firstDot + 1);
//left portion
size_t x = 0; //number consegative digits from the first dot
for(auto i = firstDot-1; i >= 0; i--)
{
if(!isdigit(str.at(i)))
break;
else if(x == 3) //take first 3
break;
x++;
}
if(x == 0)
return string("");
result.insert(0,str.substr(firstDot-x,x));
//right portion
size_t y = 0;
for(auto i = lastDot + 1; i < str.length(); i++)
{
if(isdigit(str.at(i)))
{
if(y == 3)
break;
result.push_back(str.at(i));
y++;
}
else
break;
}
if(y == 0)
result.push_back('0');
return result;
}
int main()
{
string test = "1111127.0.0.11111 xx23.45.12.# xxxx.34.0.13 124.sd.2.1 sd.45.56.1";
string x,y;
vector<string> ips;
stringstream stream;
stream<<test;
while(stream>>x)
if(!(y = ip(x)).empty())
ips.push_back(y);
for(auto z : ips)
cout<<z<<"\t";
cout<<endl;
system("pause");
return 0;
}
#include<iostream>
#include<fstream>
using namespace std;
int main() {
ifstream myReadFile;
myReadFile.open("text.txt");
char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
myReadFile >> output;
cout<<output;
}
}
myReadFile.close();
return 0;
}
Use this if the text file only includes IP's on each line.
Or depending on what c++ you're using:
std::ifstream file("Read.txt");
std::string str;
std::string file_contents;
while (std::getline(file, str))
{
file_contents += str;
file_contents.push_back('\n');
}
I'm new to C++11. I did the following simple example for you. It's based on the regex library. Hope it works for you!
#include <iostream>
#include <string>
#include <regex>
int main ()
{
std::string s ("There's no place like 127.0.0.1\n");
std::smatch m;
std::regex e ("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
while (std::regex_search (s,m,e)) {
for (auto x:m) std::cout << x << " ";
std::cout << std::endl;
s = m.suffix().str();
}
return 0;
}

Resources