The check must not user C++11 features or additional libraries e.g. Boost, Regex etc. I came up with the following solution. No pretty but working. Does it get more elegant and/or faster from here?
bool isJsonNumber(const std::string& text)
{
if(text.empty()) return false;
bool foundE = false;
bool foundESign = false;
bool leadingZero = false;
bool lastIsDigit = false;
bool foundDot = false;
for(uint32_t i=0; i < text.length(); ++i)
{
const unsigned char c = text[i];
lastIsDigit = false;
const bool currIsNoDigit = (c < '0' || c > '9');
if(i == 0)
{
if(currIsNoDigit && c != '-' ) return false;
if(c == '0') leadingZero = true;
if(c != '-') lastIsDigit = true;
}
else
{
if(leadingZero)
{
leadingZero = false;
if(c != '.') return false;
foundDot = true;
}
else if(c == '.')
{
if(foundDot) return false;
foundDot = true;
}
else if(c == 'e' || c == 'E')
{
if(foundE) return false;
foundE = true;
}
else if(foundE && !foundESign)
{
if(currIsNoDigit && c != '-' && c != '+') return false;
if(c == '+' || c == '-')
{
foundESign = true;
}
else
{
lastIsDigit = true;
}
}
else
{
foundESign = false;
if(currIsNoDigit) return false;
lastIsDigit = true;
}
}
}
if(lastIsDigit == false) return false;
return true;
}
The use case is a small embedded server that recieves huge CSV files and anwsers clients with portions in JSON.
It would probably be easier to use std::stod:
size_t endpos;
std::stod(text, &endpos);
if (endpos != text.length())
{
// Not a number
}
else
{
// A number
}
If you don't have std::stod, as it's a C++11 feature, you could do something similar with std::strtod.
If you want to disallow INFINITY or NAN or hexadecimal floating point values, it's as easy as checking that the second or third character in the string is not a letter:
if ((text.length() > 2 && std::isalpha(text[1])) ||
(text.length() > 3 && std::isalpha(text[2])))
{
// Not a number
}
For "larger" numnbers there always std::stold or std::strtold. However if you want arbitrarily sized numbers then either do as you do now or use a library such as GMP (mpf_set_str seems like a good function for this).
Related
I am getting a runtime error for this test case using stack
"bxj##tw", "bxj###tw"
Line 171: Char 16: runtime error: reference binding to misaligned address 0xbebebebebebec0ba for type 'int', which requires 4 byte alignment (stl_deque.h)
0xbebebebebebec0ba: note: pointer points here
<memory cannot be printed>
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_deque.h:180:16
class Solution {
public:
bool backspaceCompare(string s, string t) {
stack<int>st1;
stack<int>st2;
for(int i=0; i<s.size(); i++){
if(st1.empty() && s[i]!='#'){
st1.push(s[i]);
}
else{
if(!st1.empty() && s[i]=='#'){
st1.pop();
}
else if(s[i]=='#' && (st1.empty())){
continue;
}
else{
st1.push(s[i]);
}
}
}
for(int i=0; i < t.size(); i++){
if(st2.empty() && t[i]!='#'){
st2.push(t[i]);
}
else{
if(!st2.empty() && t[i]=='#'){
st2.pop();
}
else if(t[i]=='#' && st2.empty()){
continue;
}
else{
st2.push(t[i]);
}
}
}
if(st1.empty() && st2.empty()){
return "";
}
while(!st1.empty()){
if(st1.top()!= st2.top()){
return false;
}
else{
st1.pop();
st2.pop();
}
}
return true;
}
};
I wouldn't use a stack<char> since the natural representation is a string, and you're not using any functionality of the stack's ability to expand or shrink in the front (other than the end where you can just say return a == b). string has push_back and pop_back methods as well.
For small input (like the ones guaranteed for this challenge problem), I'd recommend constructing the two "editors" and comparing with ==:
class Solution {
public:
bool backspaceCompare(string s, string t) {
return backspace(s) == backspace(t);
}
private:
string backspace(const string &s) {
string editor = "";
string::const_iterator commandItr = s.cbegin();
while(commandItr != s.cend())
if(*commandItr == '#' && !editor.empty()) {
editor.pop_back();
++commandItr;
} else if(*commandItr != '#')
editor.push_back(*commandItr++);
else
++commandItr;
return editor;
}
};
However, they did challenge the coder to use O(1) memory. Here is an example of that:
class Solution {
public:
bool backspaceCompare(string s, string t) {
int left = s.size() - 1;
int right = t.size() - 1;
while(true) {
left = backspace(s, left);
right = backspace(t, right);
if (left == -1 && right == -1)
return true;
if (left == -1 && right != -1 || right == -1 && left != -1)
return false;
if(s[left--] != t[right--])
return false;
}
}
private:
// Returns first index from back that indexes to a non-deleted character
int backspace(string const &s, int startingIndex) {
if(startingIndex == -1)
return -1;
if(s[startingIndex] != '#')
return startingIndex;
unsigned backspaceCount = 0;
while(true) {
while(startingIndex != -1 && s[startingIndex] == '#') {
++backspaceCount;
--startingIndex;
}
while (startingIndex != -1 && backspaceCount && s[startingIndex] != '#') {
--startingIndex;
--backspaceCount;
}
if (startingIndex == -1)
return -1;
else if(s[startingIndex] != '#' && !backspaceCount)
return startingIndex;
}
}
};
I am trying to make a brainf*** interpreter in c++. when I test it with the Esolang hello world example:
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
is is here: https://esolangs.org/wiki/Brainfuck
it does not print anything for whatever reason. the period operator works, Ive tested it alone, but programs that work on proper brainf*** interpreters don't work on mine. Can anyone find the problem here?
PS:
file_str::read(file); is a custom method I implemented which works. just to let you know.
this is my code so far.
// Read File
std::string file_data;
file_data = file_str::read(file);
// Array
int array[30000];
bool running = true;
// pos
int pos = 0;
int pos_in_stack = 0;
// Handle brackets
std::vector<int> brackets;
// Main Loop
while(running)
{
if(pos > file_data.size()-1)
{
break;
}
// check what the curren command is and execute
if(file_data.at(pos) == '>')
{
pos_in_stack++;
pos++;
continue;
}
if(file_data.at(pos) == '<')
{
pos_in_stack--;
pos++;
continue;
}
if(file_data.at(pos) == '+')
{
array[pos_in_stack]++;
pos++;
continue;
}
if(file_data.at(pos) == '-')
{
array[pos_in_stack]--;
pos++;
continue;
}
if(file_data.at(pos) == '.')
{
char a = array[pos_in_stack];
std::cout << a;
pos++;
continue;
}
if(file_data.at(pos) == ',')
{
std::string a;
std::cin >> a;
char b = a.at(0);
array[pos_in_stack] = b;
pos++;
continue;
}
if(file_data.at(pos) == '[')
{
if(array[pos_in_stack] != 0)
{
brackets.push_back(pos);
pos++;
continue;
}
// find coresponding bracket
else{
int brackets_looking_for = 1;
while (brackets_looking_for != 0)
{
pos++;
if(file_data.at(pos) == '[')
{
brackets_looking_for++;
}
if(file_data.at(pos) == ']')
{
brackets_looking_for--;
}
}
continue;
}
}
if(file_data.at(pos) == ']')
{
if(array[pos_in_stack] != 0)
{
pos = brackets.at(brackets.size()-1);
continue;
}
brackets.pop_back();
pos++;
continue;
}
}
return 0;
}
Thanks for your help everyone, but I found the solution.
I need to change this:
pos = brackets.at(brackets.size()-1);
to this:
pos = brackets.at(brackets.size()-1)+1;
I am writing a C++ program that will show you how to pronounce a Hawaiian word.
Rules:
p, k, h, l, m, n (Pronounced like the english versions.)
w -start of word (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after the letter ‘a’ (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after ‘i’ or ‘e’ (Pronounced as a v sound.)
w -after ‘u’ or o (Pronounced as a w sound.)
My progress: My program works, but there's a couple of bugs.
When I type "iwa", the pronunciation must be "ee-vah" but I'm
getting "ee-wah".
My code is not ignoring whitespaces. So when I type "e komo mai", I want "eh koh-moh meye" but instead, I get "e komo mai is pronounced eh-eh-koh-moh-oh-meye".
Here is my code:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
string convertToHawaiian(string input);
bool vowelGroup(char first, char next, string& replacement);
bool consonantGroup(char prevchar, char currchar, string& replacement);
bool singleVowel(char current, string& replacement);
int main() {
// Declare my variables
string userInput;
string replacement;
//cout << "Enter a hawaiian word to pronounce ==>";
getline(cin,userInput);
// For loop that will call my Consonant function
// Call my Hawaiian function and put it
// into pronunciation
replacement = convertToHawaiian(userInput);
// if My initial input has a capital, the replacement
// will keep the capital letter at the beginning
if (isupper(userInput.at(0))) {
replacement.at(0) = toupper(replacement.at(0));
}
// Get rid of the '-' character at the end of the string
if (replacement.at(replacement.size() - 1) == '-') {
replacement.pop_back();
}
cout << userInput << " is pronounced " << replacement << endl;
return 0;
}
// My main function that will convert my input
// into the hawaiian pronunciation
string convertToHawaiian(string input) {
char nextChar;
string replacement = "";
string result = "";
// Iterate through my string to check for vowels,
// vowelgroups and consonants.
for (unsigned int i = 0; i < input.size(); i++) {
char character = input.at(i);
character = tolower(character);
if (i != input.size() - 1) {
nextChar = input.at(i + 1);
nextChar = tolower(nextChar);
}
if ((i != input.size() - 1) && (vowelGroup(character, nextChar, replacement))) {
i++;
result = result + replacement;
}
else if (singleVowel(character, replacement)) {
result = result + replacement;
}
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
}
return result;
}
bool vowelGroup (char first, char nextChar, string& result) {
bool isVowel = true;
if (first == 'a') {
nextChar = tolower(nextChar);
if ((nextChar == 'i') || (nextChar == 'e')) {
result = "eye-";
}
else if ((nextChar == 'o') || (nextChar == 'u')) {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'e') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ay-";
}
else if (nextChar == 'u') {
result = "eh-oo-";
}
else {
return false;
}
}
else if (first == 'i') {
nextChar = tolower(nextChar);
if (nextChar == 'u') {
result = "ew-";
}
else {
return false;
}
}
else if (first == 'o') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "oy-";
}
else if (nextChar == 'u') {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'u') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ooey-";
}
else {
return false;
}
}
else {
isVowel = false;
return isVowel;
}
return isVowel;
}
// Check to verify consonants
bool consonantGroup(char character, char nextChar, string& replacement) {
bool isConson = true;
if ((character == 'p') || (character == 'k') || (character == 'h') || (character == 'l') || (character == 'm') || (character == 'n')){
replacement = character;
return isConson;
}
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';
return isConson;
}
else if (((character == 'u') || (character == 'o')) && (nextChar == 'w')) {
replacement = 'w';
cout << "Not replacing w" << endl;
return isConson;
}
else if (((character == 'i') || (character == 'e')) && (nextChar == 'w')) {
replacement = 'v';
return isConson;
}
else {
isConson = false;
return isConson;
}
}
bool singleVowel(char current, string& result) {
bool isVowel = true;
if (current == 'a') {
result = "ah-";
return isVowel;
}
else if (current == 'e') {
result = "eh-";
return isVowel;
}
else if (current == 'i') {
result = "ee-";
return isVowel;
}
else if (current == 'o') {
result = "oh-";
return isVowel;
}
else if (current == 'u') {
result = "oo-";
return isVowel;
}
else {
isVowel = false;
return isVowel;
}
}
One of the more common sources of bugs is shared mutable state.
In your case, it is state shared between loop iterations.
The whitespace case is handled here:
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
and in that case, replacement will be string "spilled over" from the previous iteration.
The remedy is very simple: declare replacement inside the loop instead.
You can solve the "iwa" problem if you stare at these lines until you spot the bug:
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';
while( !q.is_empty() )
{
loc = q.remove_from_front();
//cout << loc.row << " " << loc.col << endl;
if( (loc.row-1) >= 0) //north
{
loc2.row = loc.row-1;
loc2.col = loc.col;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.col-1 >= 0) //West
{
loc2.row = loc.row;
loc2.col = loc.col-1;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.row+1 < rows) //South
{
loc2.row = loc.row+1;
loc2.col = loc.col;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
// loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc2.row][loc2.col] = '*';
break;
}
}
}
if(loc.col+1 < cols) //East
{
loc2.row = loc.row;
loc2.col = loc.col+1;
if(maze[loc2.row][loc2.col] != '#' && visited[loc2.row][loc2.col] == false)
{
visited[loc2.row][loc2.col] = true;
q.add_to_back(loc2);
//loc = predecessor[loc.row][loc.col];
predecessor[loc2.row][loc2.col] = loc;
if(maze[loc2.row][loc2.col] == 'F')
{
result = 1;
maze[loc.row][loc.col] = '*';
break;
}
}
}
}
if(result == 1)
{
while()
{
//not sure...
}
}
This is my BFS algorithm and the main reason I asked this question is because the other questions similar to my own question tends to be done with vectors. I haven't learn vectors yet. What I am trying to do is to print the shortest path using '' characters to display it on valid elements. It should be in bounds, no walls visited (walls are '#' characters), and no element should be visited twice. I know that if I set my predecessor 2D array correctly, the shortest path should be displayed correctly. However, I am not sure if I did set it up correctly and how to actually fill in that path with '' characters...
I am trying to create an input operator for a Polynomial class. However, my input operator is not reading my first coefficients and everything after the first exponent. It is basically reading the first term without coefficients. Here is my code:
std::istream & operator>> (std::istream & in,
Polynomial & aPoly)
{
double tempCoefficient; // temporary storage for coefficient
char ch; // variable that contains results from peek()
char dum; // removes useless symbols like '+' and 'x'
int tempExponent; // contains current exponent for coefficient
bool moreTerms = true; // variable that tells when the terms run out
bool negativeCoefficient = false; // tells when coefficient is negative
aPoly.coefficients.resize(0); // Clears aPoly before inserting user input
in >> ch ;
if (ch == '-')
{
negativeCoefficient = true;
ch = in.peek();
}
else
{
in.putback(ch);
}
if (ch >= '0' && ch <= '9')
{
in >> tempCoefficient;
if (negativeCoefficient)
{
tempCoefficient *= -1;
negativeCoefficient = false;
}
ch = in.peek();
}
if (ch == 'x')
{
tempCoefficient = 1.0;
in >> dum;
if (in.peek() == '^')
{
in >> dum;
in >> tempExponent;
}
else
{
tempExponent = 1;
}
}
else
{
tempExponent = 0;
moreTerms = false;
}
aPoly.coefficients.resize(tempExponent + 1);
aPoly.coefficients[tempExponent] = tempCoefficient;
if ((in.peek() != '+') || (in.peek() != '-'))
{
moreTerms = false;
}
while (moreTerms)
{
ch = in.peek();
if (ch == '+')
{
in >> dum; // '+'
}
else
{
negativeCoefficient = true;
in >> dum; // '-'
}
ch = in.peek();
if ( (ch >= '0') && (ch <= '9') )
{
in >> tempCoefficient;
if (negativeCoefficient)
{
tempCoefficient *= -1;
negativeCoefficient = false;
}
ch = in.peek();
}
else
{
if (negativeCoefficient)
{
tempCoefficient = -1.0;
negativeCoefficient = false;
}
else
{
tempCoefficient = 1.0;
}
}
if (ch == 'x')
{
in >> dum;
if (in.peek() == '^')
{
in >> dum;
in >> tempExponent;
}
else
{
tempExponent = 1;
}
}
else
{
tempExponent = 0;
moreTerms = false;
}
if ((in.peek() != '+') && (in.peek() != '-'))
{
moreTerms = false;
}
aPoly.coefficients[tempExponent] = tempCoefficient;
}
return in;
}
You have a problem here
if ((in.peek() != '+') || (in.peek() != '-'))
where the condition is always true.
Further down in the code you use && which works better.