I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings.
try to put a repeated character when next is not numeric or end of string.
For prepare this, it needs to make number by parsing string.
about this, I recommend you to find how to convert string to integer in real time at C++.
bool isNumeric(char ch) {
return '0' <= ch && ch <= '9';
}
string decode(const string& s) {
int counter = 0;
string result;
char prevCh;
for (int i = 0; i < s.length(); i++) {
if (isNumeric(s[i])) { // update counter
counter = counter * 10 + (s[i] - '0');
if (isNumeric(s[i + 1]) == false || i + 1 == s.length()) {
// now, put previous character stacked
while (counter-- > 1) {
result.push_back(prevCh);
}
counter = 0;
}
}
else {
result.push_back(s[i]);
prevCh = s[i];
}
}
return result;
}
now, decode("a12bhr3") returns aaaaaaaaaaaabhrrr. it works well.
Related
I am having trouble making this function evaluate if a a six digit integer has either a set of two repeated consecutive digits or four. All other sets of repeated consecutive digits should evaluate to false.
Examples of good input: 122345, 133335
Bad input: 123335, 666478
Here is my code:
bool hasDuplicate(int number){
int rem, num, dig;
do {
rem = number % 10;
num = number / 10;
dig = num % 10;
if (rem == dig) {
return true;
}
else {
return hasDuplicate(num);
}
} while (number > 0);
return false;
}
Consider converting the number to string and then just scanning the characters in the string from left to right.
bool hasDuplicate(int number) {
std::string s = std::to_string(number);
bool good = false;
bool bad = false;
int consecutive = 1;
// deliberately starting at s[1]
for (size_t i = 1; i < s.size(); i++) {
bool dupe = (s[i - 1] == s[i]);
if (dupe) {
consecutive++;
}
// last iteration or this char is not a duplicate of the previous one
if ((i + 1 == s.size()) || (!dupe)) {
bool good_sequence = (consecutive == 2) || (consecutive == 4);
good = good || good_sequence;
bool bad_sequence = (consecutive == 3) || (consecutive > 4);
bad = bad || bad_sequence;
}
if (!dupe) {
consecutive = 1;
}
}
return good && !bad;
}
I want to obtain integers from file that has strings too, and store them into array to do some operation on them. the integers can be 1 or 12 or 234, so 3 digits. I am trying to do that but the output stops when I run the code
void GetNumFromFile (ifstream &file1, char & contents)
{
int digits[20];
file1.get(contents);
while(!file1.eof())
{
for (int n = 0; n < 10; n++)
{
if(('0' <= contents && contents <= '9') && ('0' >= contents+1 && contents+1 > '9'));
digits[n]=contents;
if(('0' <= contents && contents <= '9') && ('0' <= contents+1 && contents+1 < '9'));
digits[n]=contents;
if(('0' <= contents && contents <= '9') && ('0' <= contents+1 && contents+1 <= '9') && ('0' <= contents+2 && contents+2 < '9'));
digits[n]=contents;
}
continue;
}
for (int i = 0; i <= 20; i++)
{
cout << *(digits + i) << endl;
}
}
You have to deal with the number of digits of the number found:
int digits[20];
int i = 0;
short int aux[3]; // to format each digit of the numbers
ifstream file1("filepath");
char contents;
file1.get(contents); //first char
if (!file1.eof()) //test if you have only one char in the file
{
while (!file1.eof() && i < 20) // limit added to read only 20 numbers
{
if (contents <= '9' && contents >= '0') // if character is in number range
{
aux[0] = contents - '0'; // converting the char to the right integer
file1.get(contents);
if (contents <= '9' && contents >= '0') // if contents is number, continue on
{
aux[1] = contents - '0';
if (!file1.eof()) // if has mor char to read, continue on
{
file1.get(contents);
if (contents <= '9' && contents >= '0') // if is integer, continue on
{
aux[2] = contents - '0';
file1.get(contents); // will read same of last char if eof, but will have no effect at all
//aux[0] *= 100; // define houndred
//aux[1] *= 10; // define ten
digits[i++] = (aux[0] * 100) + (aux[1] * 10) + aux[2];
}
else
{
//aux[0] *= 10; // define ten
digits[i++] = (aux[0] * 10) + aux[1];
}
}
else
{
digits[i++] = (aux[0] * 10) + aux[1];
}
}
else
{
digits[i++] = aux[0];
}
}
}
}
else if (contents <= '9' && contents >= '0' && i < 20) // check if the only one char is number
{
digits[i++} = contents - '0';
}
If you want read an undefined size number, then you will have to allocate memory to format each digit of the numers with new (c++) or malloc(c/c++).
First observation: you iterate out of bounds of the array:
int digits[20];
for (int i = 0; i <= 20; i++)
20 elements and 21 iteration. That is an undefined behavior, so everything is possible here (if your program eventually gets here).
Next, you read from file once and then you have an infinite loop because the expression !file1.eof() is either true or false for the rest of the program run. Isn't that the reason of "output stops"?
The third finding: your if statements are useless because of the semicolon after the statement:
if(('0' <= contents && contents <= '9') && ('0' >= contents+1 && contents+1 > '9'));
digits[n]=contents;
You just assign digits[n]=contents; without any check.
I neither see any reason of providing a reference to char in the function. Why not to make it a local variable?
You will need first to add get() functionality inside the loop as well in order to reach end of file.
Forthmore try to add a while loop once a char was found to be an integer to continue in asking for the next character.
e.g.
int digits[20];
int i = 0;
ifstream file1("filepath");
char contents;
while (!file1.eof())
{
file1.get(contents); // get the next character
if (contents <= '9' && contents >= '0' && i < 20) // if character is in number range
{
digits[i++] = contents - '0'; // converting the chat to the right integer
file1.get(contents);
while (contents <= '9' && contents >= '0' && i < 20) // while is integer continue on
{
digits[i++] = contents - '0';
file1.get(contents);
}
}
}
// do other stuff here
I was benchmarking some I/O code with large input( 1Mb text file of integer, separated by tab, spaces or endline) then the normal cin method
int temp;
cin >> temp;
while(temp!=0){ cin >> temp;}
Got into an infinite loop with temp value at 15
, there is no such long sequences in the input file however
The cooked up integer parsing method, with fread however did just fine
with a clock time of around 0.02ms
void readAhead(size_t amount){
size_t remaining = stdinDataEnd - stdinPos;
if (remaining < amount){
memmove(stdinBuffer, stdinPos, remaining);
size_t sz = fread(stdinBuffer + remaining, 1, sizeof(stdinBuffer) - remaining, stdin);
stdinPos = stdinBuffer;
stdinDataEnd = stdinBuffer + remaining + sz;
if (stdinDataEnd != stdinBuffer + sizeof(stdinBuffer)){
*stdinDataEnd = 0;
}
}
}
int readInt(){
readAhead(16);
int x = 0;
bool neg = false;
// Skipp whitespace manually
while(*stdinPos == ' ' || *stdinPos == '\n' || *stdinPos == '\t'){
++stdinPos;
}
if (*stdinPos == '-') {
++stdinPos;
neg = true;
}
while (*stdinPos >= '0' && *stdinPos <= '9') {
x *= 10;
x += *stdinPos - '0';
++stdinPos;
}
return neg ? -x : x;
}
Any direction on how might cin get stuck ?
So I want to take a string in such as 8302 and convert this into an integer by creating my own function and not using the stoi/atoi functions.
I tried so far by doing:
int stringToInt(string input)
{
int i = 0;
while(input[i] >= '0' && input[i] <= '9')
{
input[i] = input[i] * 10 + ......
i++;
}
return i;
}
I know i need to keep multiplying by 10 everytime i find an integer so i can increase it e.g 123 = 1*10*10+2*10+3. but i dont know how to code this. could anyone suggest a method?
It might be easiest to do it in a recursive manner. Use the following idea:
8302 = 830 * 10 + 2
That is:
If there is only one char in the string - return it; otherwise continue
Separate the last char in the string
Convert the string (without the last char) to integer - using recursion
Multiply by 10 and add the last char
There are a lot of details here:
how to convert 1 char to an integer? - subtract '0' from it
how to separate a char from the rest of the string? - use substr
when you have a working recursive solution, you might want to convert it to an iterative solution - this will make it faster, but maybe less readable
what to do with invalid strings like "aaa" or "123haha" - my algorithm doesn't handle that
Before you could define a char2int conversion:
inline int ctoi(char c) {
switch (c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
throw std::runtime_error("Invalid char conversion");
}
}
And use it:
int my_stoi_dec(const std::string& str) {
int rtn = 0;
int exp = 1;
for (auto cp = str.crbegin(); cp != str.crend(); ++cp) {
char c = *cp;
if (isdigit(c)) {
rtn += ctoi(c) * exp;
exp *= 10;
} else if (c == '+') {
return rtn;
} else if (c == '-') {
return rtn * -1;
} else {
throw std::runtime_error("Integer error conversion");
}
}
}
This one is very close to your attempt:
int toInt(const std::string& input)
{
int i = 0;
for (const auto c : input)
{
if (c < '0' || c > '9')
break;
i = i*10 + c-'0';
}
return i;
}
The only assumption is that the characters '0' to '9' lie directly next to each other in the character set. The if statement makes sure that we stop at non-digit characters. The digit-characters are converted to their integer value using c-'0'.
Please keep in mind that this only parses the first digits of a string. Strings that start with a sign + or - are not considered.
A good way is to find your first digit and go from there make a multiplayer variable and multiply it by ten every digit. for every char you add you have to subtract '0' from it as '0' is not equal to int 0.
example:
string s = "12346";
int multiplayer = 1;
int i = 0;
int result = 0;
while (s[i] >= '0' && s[i] <= '9')
++i;
--i;
for(i ; i >= 0 ; --i){
result += (s[i] - '0') * multiplayer;
multiplayer *= 10;
}
It is much better that you start your conversion from right to left.
So you will iterate your string starting from its end, and ending on its beginning. On each iteration, we will take the character, convert it to int and multiply it with its multiplier (its position in the result integer) and then add it to the final result.
This should work:
#include <iostream>
#include <string>
int stringToInt(std::string input)
{
int result = 0;
int multiplier = 1;
for (int i = input.length() - 1; i >= 0; i--) // start from right
{
if (input[i] - '0' < 0 || input[i] - '0' > 9) // if any character is not an integer, return maximum negative
{
result = INT16_MIN;
break;
}
result += (input[i] - '0') * multiplier; // convert to int, get its position and then add it to result.
multiplier *= 10; // get next position
}
return result;
}
int main()
{
std::string MyEx = "123456";
int MyInt = stringToInt(MyEx);
std::cout << MyInt;
return 0;
}
void enforce( bool b ) {
if ( !b ) {
throw std::range_error("Not a valid string to convert to integer");
}
}
int stringToInt(std::string) {
for ( std::size_t i( 0 ); i != ( last - first ); ++i ) {
enforce( ( '0' <= first[ i ] ) && ( first[ i ] <= '9' ) );
result += pow(10,i) * ( first[ i ] - '0' );
}
}
Source
I am looking for better ways to optimize this function for better performance, speed its targeted towards embedded device. i welcome any pointers, suggestion thanks
function converts string BCD to Decimal
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int NumSubstrings = str.length() / splitLength;
std::vector<std::string> ret;
int newvalue;
for (auto i = 0; i < NumSubstrings; i++)
{
ret.push_back(str.substr(i * splitLength, splitLength));
}
// If there are leftover characters, create a shorter item at the end.
if (str.length() % splitLength != 0)
{
ret.push_back(str.substr(splitLength * NumSubstrings));
}
string temp;
for (int i=0; i<(int)ret.size(); i++)
{
temp +=ReverseBCDFormat(ret[i]);
}
return newvalue =std::stoi(temp);
}
string ReverseBCDFormat(string num)
{
if( num == "0000")
{
return "0";
}
else if( num == "0001")
{
return "1";
}
else if( num == "0010")
{
return "2";
}
else if( num == "0011")
{
return "3";
}
else if( num == "0100")
{
return "4";
}
else if( num == "0101")
{
return "5";
}
else if( num == "0110")
{
return "6";
}
else if( num == "0111")
{
return "7";
}
else if( num == "1000")
{
return "8";
}
else if( num == "1001")
{
return "9";
}
else
{
return "0";
}
}
Update
this is what i plan to get, for a BCD Value::0010000000000000 Decimal Result 2000
BCD is a method of encoding decimal numbers, two to a byte.
For instance 0x12345678 is the BCD representation of the decimal number 12345678. But, that doesn't seem to be what you're processing. So, I'm not sure you mean BCD when you say BCD.
As for the code, you could speed it up quite a bit by iterating over each substring and directly calculating the value. At a minimum, change ReverseBCDFormat to return an integer instead of a string and calculate the string on the fly:
temp = temp * 10 + ReverseBCDFormat(...)
Something like that.
What you call BCD is not actually BCD.
With that out of the way, you can do this:
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int ret = 0;
for (unsigned i = 0, n = unsigned(str.size()); i < n; )
{
int v = 0;
for (unsigned j = 0; j < splitLength && i < n; ++j, ++i)
v = 2*v + ('1' == str[i] ? 1 : 0); // or 2*v + (str[i]-'0')
ret = 10*ret + v;
}
return ret;
}
Get rid of all the useless vector making and string copying. You don't need any of those.
Also, I think your code has a bug when processing strings with lengths that aren't a multiple of splitLength. I think your code always considers them to be zero. In fact, now that I think about it, your code won't work with any splitLength other than 4.
BTW, if you provide some sample inputs along with their expected outputs, I would be able to actually verify my code against yours (given that your definition of BCD differs from that of most people, what your code does is not exactly clear.)
as soon as you're optimizing function, here is different variant:
int ConvertBCDToDecimal(const std::string& str) {
unsigned int result = 0;
const std::string::size_type l = str.length();
for (std::string::size_type i = 0; i < l; i += 4)
result = result * 10 + ((str[i] - '0') << 3) + ((str[i + 1] - '0') << 2) + ((str[i + 2] - '0') << 1) + (str[i + 3] - '0');
return result;
}
note: you don't need splitLength argument, as you know that every digit is 4 symbols