c++ split int value string - c++

I am trying to split specific string with couple of different ways. The example of my input is (-5,3,0,1,-2).
And this is my first code,
// code 1
string s = "(-5,3,0,1,-2)";
int j = 0;
int * temp = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
if (s[i] != '(' && s[i] != ',' && s[i] != ')') {
temp[j++] = (s[i]-'0');
}
}
code 1 works well except, it converts - sign to ascii value(45) not negative int value.
//code2
char *first = _strdup(s.c_str());
char * temp2 = NULL;
char *temp = strtok_s(first, "(,)", &temp2);
/* Expected output is
temp[0] = -5
temp[1] = 3
temp[2] = 0
temp[3] = 1
temp[4] = -2
*/
However middle of debugging, temp contains ascii value, not string value. Also not sure code2 is correctly working.
Thanks in advances!

You need a proper string to int conversion. Use std::stoi. I used the boost tokenizer. It is very handy for your case.
#include <string>
#include <boost/tokenizer.hpp>
#include <vector>
using namespace std;
using namespace boost;
int main() {
vector<int> intList
string text = "(-5,3,0,1,-2)";
char_separator<char> sep(",");
tokenizer<char_separator<char>> tokens(text, sep);
for (const auto& t : tokens)
intList.push_back(std::stoi(t));
}
PS. you forgot the delete for you new. Please use a proper container (e.g. std::vector).

Use istrstream::get method. You can avoid the open and close braces by replacing those.
void _parse_(istrstream &str,string &strText, char ch = ',')
{
char chText[MAX_PATH];
str.get(chText, MAX_PATH,ch);
str.get(ch);
strText = chText;
}
string s = "(-5,3,0,1,-2)";
istrstream inputStream(s);
string sTemp;
//Replace here the open and close braces.
do
{
_parse_(inputStream, sTemp,',');
//Your value in sTemp
}while(!sTemp.empty())

If you need use c++ without any library, you can use flowing code:
#include <string>
#include <vector>
using namespace std;
int main()
{
string s = "(-5 2,3 0 1, 0 , 1 , -21 0 )";
int location = 0;
vector<int> array;
string sub;
while (location <= s.length())
{
if ((s[location] >= 48 && s[location] <= 57) || s[location] == 45 || s[location] == 32)
{
if (s[location] != 32)
{
sub += s[location];
}
}
else
{
if (sub.length() != 0)
{
std::string::size_type sz;
int num = stoi(sub, &sz);
array.push_back(num);
}
sub.clear();
}
location++;
}
return 0;
}

#include <sstream>
#include <iomanip>
using namespace std;
const string INTEGER_CHARS {"0123456789+-"};
vector<int> readIntFromString(const string src) {
const char stopFlag{'\0'};
const string str {src + stopFlag};
vector<int> numbers;
stringstream ss(str);
int tmp;
for(char nextChar = ss.peek(); nextChar != stopFlag; nextChar = ss.peek()) {
if (INTEGER_CHARS.find(nextChar) != string::npos) {
ss >> setbase(0) >> tmp;
numbers.push_back(tmp);
} else {
ss.ignore();
}
}
return numbers;
}
setbase(0): make >> operator to recognize other based numbers, e.g. 0b01, 070, 0xF
ss.ignore(): skip the char we don't care

You can use the following,
string s = "(-5,3,0,1,-2)";
int j = 0;
string temp;
std::vector<int> values;
for (int i = 0; i < s.length(); i++)
{
if (s[i] != '(' && s[i] != ')')
{
while (s[i] != ',' && s[i] != ')')
{
temp += s[i];
++i;
}
values.push_back(std::atoi(temp.c_str()));
temp.clear();
}
}

Related

Recursive program to insert a star between pair of identical characters

void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
what is the mistake in this code. I couldn't find out.
if I entered aaaa, abaa etc. it runs perfect.
but when i entered scatter is shows scat*ter?#
so what is the perfect solution ?
input string is aaaa . so output is a*a*a*a instead of a*aa*a.
You do not copy terminating character \0!
So when you have inserted a character termination of string is undefined.
Note also that proper answer for aaaa should be a*a*a*a (or a*aa*a depending on problem definition).
Split argument to define soruce and destination and use separate buffers.
void copyAddStarToPairs(const char *src, char *dst)
{
*dst = *src;
if (!*dst) return;
dst++;
char prev = *src++;
if (prev = *src) *dst++ = '*';
copyAddStarToPairs(src, dst);
}
May be you should use std::string as your char buffer may not be long enough.
#include <string>
using std::string;
void pairStar(string & s, int st) {
if (st >= (int)s.size() - 1)
return;
else if (s[st] == s[st + 1]) {
s += ' ';
for (int i = (int)s.size() - 1; i > st + 1; i--)
s[i] = s[i - 1];
s[st + 1] = '*';
st++;
}
pairStar(s, st + 1);
}
int main() {
string s = "aadqwedabbbbb*dqwdasd";
pairStar(s, 0);
cout << s << endl;
}
Add the line input[len+1]='\0'; after the lineinput[1]='*';.
What happens actually is that once you append '*',you aren't appending the '\0' character. This line will append it to the end that means string end here for the first call that you made. So recursive function will also do the same, it will add '\0' character at the end letting know that string ends here.
Consider an example:
aa is a string of length 2 and and after adding star the length of string will become 3 so input[len+1] will be input[2+1]=input[3].
So character next to the moved character will be '\0' character everytime.
PS: this is my first time adding an answer on stackoverflow...
I offer to solve this problem, using the algorithm Depth first search.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int maximumSize=40;
string symbols="aadqwedabbbbb*dqwdasd";
string symbolsNew;
vector<int> visited(maximumSize, 0);
template<class Type>
void showContent(Type input)
{
for(int index=0; index<input.size(); ++index)
{
cout<<input[index];
}
return;
}
void depthFirstSearch(int current, int previous)
{
if(visited[current]==1)
{
return;
}
visited[current]=1;
symbolsNew.push_back(symbols[current]);
int interactions=0;
for(int next=(current+1); next<symbols.size(); ++next)
{
if(interactions!=0)
{
break;
}
if(symbols[current]==symbols[next])
{
symbolsNew.push_back('*');
}
++interactions;
}
for(int next=current; next<symbols.size(); ++next)
{
depthFirstSearch(next, current);
}
return;
}
void solve()
{
depthFirstSearch(0, -1);
cout<<"symbols <- ";
showContent(symbols);
cout<<endl<<"symbolsNew <- ";
showContent(symbolsNew);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
symbols <- aadqwedabbbbb*dqwdasd
symbolsNew <- a*adqwedab*b*b*b*b*dqwdasd
void pairStar(char input[]) {
int len = strlen(input);
if(input[0] == '\0'){
return ;
}
if(input[0] == input[1]){
for(int i = len+1; i >= 2; i--){
input[i] = input[i-1];
}
input[2] = input[1];
input[1] = '*';
}
pairStar(input+1);
}
void helper(char input[], int start)
{
if (input[start] == '\0')
{
return;
}
helper(input, start + 1);
if (input[start] == input[start + 1])
{
for (int i = strlen(input); i >= start + 1; i--)
{
input[i + 1] = input[i];
}
input[start + 1] = '*';
}
}
void pairStar(char input[])
{
helper(input, 0);
}

How to solve this Floating Point expection: 8 error

This program is suppose to take a json in the format of a dict. The keys are zipcodes and the values are vectors of rent prices.
When i run it using g++ I get a floating point exception 8: error. To my knowledge that error only triggers if the value overflows its data type but that could only occur if the averager function's mean variable is surpassing the max value of an unsigned long long which shouldn't occur.
I am also open to a more elegant way to write this code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using namespace std;
unsigned int average(unsigned int n1,unsigned int n2){
unsigned int mean;
mean = (n1 + n2)/2;
return mean;
}
unsigned long long average(vector<unsigned int> nValues){
unsigned long long mean = 0;
for(auto element : nValues){
mean += element;
}
mean /= nValues.size();
return mean;
}
unsigned int strCleaner(string str){
unsigned int na = 0;
string temp;
if(str == "N/A"){
return na;
}
for(auto element : str){
if(element == '$' || element == ',' || element == ' ' || element == '"'){
continue;
}
temp += element;
}
cout << temp << endl;
int newStr = stoi(temp);
return (unsigned int)newStr;
}
int main(void)
{
string line;
ifstream my_json("records_v1.json");
ifstream zips("zip_set.txt");
json my_stat;
json j;
my_json >> j;
while(getline(zips,line)){
vector<unsigned int> summation;
auto map = j[line];
for(auto element: map){
string element_str = element.dump();
size_t result = element_str.find("-");
if(result != string::npos){
string n1, n2;
for (int i = 0; i < element_str.size(); i++)
{
if(i < result){
n1 += element_str[i];
}
if(i > result){
n2 += element_str[i];
}
}
auto mean = average(strCleaner(n1),strCleaner(n2));
summation.push_back(mean);
}else if(element_str != "N/A"){
continue;
}else{
unsigned int cleanedInt = strCleaner(element);
summation.push_back(cleanedInt);
}
}
auto city_mean = average(summation);
my_stat[line] = city_mean;
}
ofstream f_myrecord("fileZ.json");
f_myrecord << setw(4) << my_stat << endl;
}

Detecting if input is a string or an integer

Please tell me what is wrong in my approach.
#include <iostream>
#include <string>
using namespace std;
string datatype(string x) {
for (int k = 0; k < strlen(x.c_str());) {
for (int i = 0; i < 10; i++) {
char z = i;
if (x[k] == z) {
k++;
}
else {
return "string";
}
}
}
return "int";
}
int main() {
string inp;
cin >> inp;
cout << datatype(inp);
}
Whatever i enter, it always returns "string".
I have seen the other questions posted here but please tell me what is wrong in my approach.
The standard library has the isdigit function that tells you if the char is a digit.
Here you check that each char of your input is a digit, as soon as a character that is not a digit is found string is returned, else int.
For example 1234 returns int, sdf returns string.
string datatype(string str) {
for (unsigned char c : str) {
if (!isdigit(c)) {
return "string";
}
}
return "int";
}
Edit:
This solution also handles leading - and +. It will return int for -10 and +10 but returns string for +1+1 or -10+10.
string datatype(string str) {
if (str.size() == 1) {
return isdigit(str[0]) ? "int" : "string";
}
bool isInt = true;
for (int i = 1; i < str.size(); i++) {
isInt = isInt && isdigit(static_cast<unsigned char>(str[i]));
if (!isInt) {
break;
}
}
if (isInt) {
unsigned char c = str[0];
isInt = isInt && (c == '-' || c == '+' || isdigit(c));
}
return isInt ? "int" : "string";
}
First of all Include (cstring) as header since x.c_str is not in iostream and string. Then,
When you are doing char z=i; here you are not storing the character equivalent of i in z but the ascii value of i.
Next, You are returning string at the first mismatch between i and x[k]. You should return string if you cannot find a match with any of the possible 10 digits.
You can have a look at the modified code.
#include <iostream>
#include<cstring>
#include <string>
using namespace std;
string datatype(string x) {
for (int k = 0; k < strlen(x.c_str());k++) {
int flag=0;
for (int i = 0; i < 10; i++) {
// char z = i;
if ((x[k]-'0') == i || (k==0 && x[k]=='-')) {
flag=1;
break;
}
}
if(flag==0)
return "string";
}
return "int";
}
int main() {
string inp;
cin >> inp;
cout << datatype(inp);
}

Implementation of a function that evaluates simple mathematical expressions. (C++)

I am trying to write a function that evaluates simple mathematical expressions (only four operations). I used stack and vector to do this. But stack operations don't behave as I expect. I couldn't find the cause. I am open to different solutions.
The function should take a string like this:
"5 * 44 + 3 / 2 * 4 - 12"
And return the result as a double.
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <cstdlib>
using namespace std;
vector<string> split(const std::string& str, char delim = ' ')
{
vector<string> elements;
stringstream ss(str);
string token;
while (getline(ss, token, delim)) {
elements.push_back(token);
}
return elements;
}
double evaluate(string operation)
{
vector<string> values = split(operation, ' ');
stack<string> result_stack;
double result = 0;
for(unsigned int i = 0; i < values.size(); i++){
if(values[i] == "*"){
double mini_result = stod(result_stack.top()) * stod(values[i+1]);
result_stack.pop();
i++;
result_stack.push(to_string(mini_result));
}
else if(values[i] == "/"){
double mini_result = stod(result_stack.top()) / stod(values[i+1]);
result_stack.pop();
i++;
result_stack.push(to_string(mini_result));
}
else{
result_stack.push(values[i]);
}
}
for(unsigned int i = 0; i<result_stack.size(); i++){
if(result_stack.top() == "-"){
result_stack.pop();
result = stod(result_stack.top()) - result;
result_stack.pop();
}
else if(result_stack.top() == "+"){
result_stack.pop();
result += stod(result_stack.top());
result_stack.pop();
}
else{
result += stod(result_stack.top());
result_stack.pop();
}
}
return result;
}
int main()
{
cout<<evaluate("5 * 44 + 3 / 2 * 4 - 12");
}
Before the second for loop, values in the result_stack should be like this for this example. "12 | - | 6 | + | 220" . And the returning value should be 214.
But before the second for loop, stack contains only "12 | - | 6" values. "+" and "220" values are not there. Some extra pops occur which I don't expect.
stack content should be like this for this example
Your operands for the subtraction operation are swapped. This because when you process the stack for the + and - operations you're parsing the equation from right-to-left.
With your example, when the - is found in the stack, result is 12. You pop the -, then subtract the 6, leaving 6 in result when it should be -6.
You should use
result = stod(result_stack.top()) - result;
for subtraction.
There is also no error checking in your code for invalid equations.
Answered here: answer of the question
Completed code is here:
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <stack>
using namespace std;
string trim(const string& str)
{
size_t first = str.find_first_not_of(' ');
if (string::npos == first)
{
return str;
}
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last - first + 1));
}
vector<string> split(const std::string& str, char delim = ' ')
{
vector<string> elements;
stringstream ss(str);
string token;
while (getline(ss, token, delim)) {
elements.push_back(token);
}
return elements;
}
double evaluate(string operation)
{
vector<string> values = split(operation, ' ');
vector<string> result_vector;
double result = 0;
for(unsigned int i = 0; i < values.size(); i++){
if(values[i] == "*"){
double mini_result = stod(result_vector.back()) * stod(values[i+1]);
result_vector.pop_back();
i++;
result_vector.push_back(to_string(mini_result));
}
else if(values[i] == "/"){
double mini_result = stod(result_vector.back()) / stod(values[i+1]);
result_vector.pop_back();
i++;
result_vector.push_back(to_string(mini_result));
}
else{
result_vector.push_back(values[i]);
}
}
auto iterator = result_vector.begin();
while(iterator != result_vector.end()){
if(*iterator == "-"){
iterator++;
result -= stod(*iterator);
}
else if(*iterator == "+"){
iterator++;
result += stod(*iterator);
}
else{
result += stod(*iterator);
}
iterator++;
}
return result;
}
int main()
{
cout<<evaluate("5 * 44 + 3 / 2 * 4 - 12");
}

Converting binary to ASCII

I have a text full of binary values(0-1) and i'm trying to convert it to ASCII , I made a code but it didn't work well and it takes too long time and writing, this is a part of it:
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
ofstream fout("C:\\test.txt",ios :: binary);
ifstream file("E:\\mnmn.txt");
string content;
while(file >> content)
{
for (size_t i = 0; i < content.size(); i++)
{
while((content[i] == '0')
&& (content[i+1] == '0')
&& (content[i+2] == '0')
&& (content[i+3] == '0')
&& (content[i+4] == '0')
&& (content[i+5] == '0')
&& (content[i+6] == '0')
&& (content[i+7] == '0')
{
char *data = "00000000";
char c = strtol(data, 0, 2);
fout<<c;
}
}
}
}
i have to do the same for all values and even if i did the program repeats the values because the zeros and ones is connected without any spaces between , isn't there a better way to convert it?
the text contains:
00001111101010001001010101110
etc..
GCC 4.8.2: g++ -Wall -Wextra -std=c++11 read-01.cpp
#include <bitset>
#include <fstream>
int main() {
std::ofstream fout("test.txt");
std::ifstream fin("mnmn.txt");
char ic;
std::bitset<8> oc;
int i = 8;
while (fin >> ic) {
oc[--i] = ic - '0';
if (0 == i) {
fout << static_cast<char>(oc.to_ulong());
i = 8; } }
return 0; }
You can read the contents of the file character by character and accumulate the characters in a variable. After reading 8 characters, you have the ASCII value. The core of your function can be changed to:
int inChar = 0;
int outChar = 0;
int count = 0;;
while( (inChar = file.get()) != EOF )
{
int x = inChar - '0';
// Ignore newlines and other characters that are not '0' or '1'.
if ( x == 0 || x == 1 )
{
// Accumulate the bit into the output char.
outChar = (outChar << 1) + x;
++count;
if ( count == 8 )
{
fout.put(outChar);
outChar = 0;
count = 0;
}
}
}
// Deal with unused outChar.
if ( count > 0 )
{
cout << "There are " << count << " bits that were not used.\n";
}
If you want to get eight characters (bits) at a time from the input you read, then you should use the std::string::substr function, and you can use the resulting string directly, either in std::stoi (or if you don't have it std::strtol).
Something like
while (file >> content)
{
do
{
std::string byte = content.substr(0, 8); // Get eight "bits"
fout << std::stoi(byte, nullptr, 2); // Convert and output to file
content = content.substr(8); // The remaining bits
} while (!content.empty());
}