Hi i have the following code to convert string integer into integer, these are the code:
#include <stdio.h>
int str_to_int(char* str) {
int output = 0;
char* p = str;
for (int i=0;str[i]!='\0';i++) {
char c = *p++;
if (c < '0' || c > '9')
continue;
output *= 10;
output += c - '0';
}
return output;
}
int main(){
printf("%d\n", str_to_int("456xy"));
printf("%d\n", str_to_int("32"));
printf("%d\n", str_to_int("-5"));
return 0;
}
But some how printf("%d\n", str_to_int("-5")); some how returning 5 instead -5, where am i wrong here? Thanks
You don't really seem to account for "-" at all in your code.
You should insert some kind of hook to detect if it's a negative value:
#include <stdio.h>
int str_to_int(char* str) {
int output = 0;
char* p = str;
bool isNeg = false;
if (*p == '-')
{
isNeg = true;
p++;
}
for (int i=0;str[i]!='\0';i++) {
char c = *p++;
if (c < '0' || c > '9')
continue;
output *= 10;
output += c - '0';
}
if (isNeg)
{
output *= -1;
}
return output;
}
int main(){
printf("%d\n", str_to_int("456xy"));
printf("%d\n", str_to_int("32"));
printf("%d\n", str_to_int("-5"));
return 0;
}
it's the if (c < '0' || c > '9') continue; that causes this problem.
When variable c is '-', you just simply skip it. So there is no negative sign in your result.
Please just test if this number is negative (has '-') before your whole logic.
In your conversion function, you skip over the - character, because it is not in your tested range:
if (c < '0' || c > '9')
continue;
To fix it, you need to test for the - character, and negate the value after you are done converting the value.
if (c < '0' || c > '9') {
if (c == '-' && no_other_digits_processed_yet) is_neg = true;
continue;
}
//...
if (is_neg) output = -output;
return output;
Related
I am newbie and I have to check valid palindrome string.
Here is my code in c++
char to_lower(char ch){
char c = ch - 'A' + 'a';
return c;
}
bool isPalindrome(string s) {
int l = s.length();
string t = "";
for(int i=0;s[i]!='\0';i++){
if(((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z') || (s[i]>='0' && s[i]<='9')))
t.push_back(s[i]);
if(t[i]>='A' && t[i]<='Z')
t[i] = to_lower(t[i]);
}
int i=0;
int j=t.length()-1;
while(i<=j){
if(t[i]!=t[j])
return false;
else
i++;
j--;
}
return true;
}
It is showing stack buffer overflow. I am not understanding this error is showing. Please help me
Our teacher gave us this exercise:
"Given a string like '-5,14' write a function that returns the float value of -5,14
I used double here just to test the precision, but it also didn't work with floats.
[also i'm from Europe, we use the comma instead of the dot. Oh also we aren't allowed to use the type string and bool, we have to "make" them like in C]
This is what i came up with, and it seems to work a little bit. Positive numbers are similar, but wrong, and given a negative number, the result is similar to 10 times the positive of the given number.
It should work like this:
I read the string into an array of characters;
I check if the first character is a minus. if so, subtract 1 from the number of integer figures because i will count them later starting from index 0;
I count the number of integer figures with a loop from the start of the array to the ',' character;
I count the number of decimal figures with a loop from after the ',' to the end of the string;
[Keep in mind for the next step that, following the ASCII table, the code for the character of a number is that number + 48]
I add to the result variable every integer figure multiplied by ten to the power of whatever place in the number it has.
I do the same for the deicmal values but with the negative exponent.
if the number was negative, i multiply the result with -1.
But for some reason it's not working properly. The lower the number is, the less accurate it is (given 4,5 the result is 9, but given 345,543 the result is 350,43)
#include <iostream>
#define EOS '\0'
#define DIM 100
#define TRUE 1
#define FALSE 0
void leggiN(char* c)
{
std::cout << "Insert a number: ";
std::cin >> c;
}
double stof(char* str)
{
double Result = 0;
double ascii_to_int = 48;
int i = 0;
int j = 0;
int IntegerDigits = 0;
int DecimalDigits = 0;
int CommaIndex;
int isNegative = FALSE;
if (str[0] == '-')
{
IntegerDigits = -1;
isNegative = TRUE;
}
while (str[i] != ',')
{
++IntegerDigits;
++i;
}
CommaIndex = i;
++i;
while (str[i] != EOS)
{
++DecimalDigits;
++i;
}
for (i = (CommaIndex - 1); i >= 0; --i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, j));
++j;
}
j = 0;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
if (isNegative == 1)
Result = Result * -1;
return Result;
}
int main()
{
char str[DIM];
leggiN(str);
std::cout << stof(str);
}
use j = 1 to start your second for loop. You are trying to raise 10 to the power of -0
j = 1;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
If your code return 9.0 when you enter "4,5", your problem has nothing to do with imprecision.
There are other problems in your code, I've tried to un it and got a SEGFAULT...
#include <iostream>
#define EOS '\0' // 0 being such a special value, there is no need to
// define a named constant for it.
#define DIM 100
#define TRUE 1 // the language defines boolean values, avoid defining
#define FALSE 0 // unnecessary named constants for something that already
// exists.
void leggiN(char* c)
{
std::cout << "Insert a number: ";
std::cin >> c; // Inserting from cin to a char* is a BIG no-no.
// some compilers won't even allow it, for good reasons
// i.e.: what is the length of the array pointed to?
}
double stof(char* str) // you are indicating that you may modify str?
{
double Result = 0;
double ascii_to_int = 48; // this is a terrible name.
int i = 0;
int j = 0;
int IntegerDigits = 0;
int DecimalDigits = 0;
int CommaIndex;
int isNegative = FALSE;
if (str[0] == '-') // is str a valid pointer? what happens if NULL ??
{
IntegerDigits = -1;
isNegative = TRUE;
// you fail to skip the sing character, should have ++i here.
}
while (str[i] != ',') // what happens if there is no ',' in the string?
{ // you should check for str[i] == 0.
++IntegerDigits;
++i;
}
CommaIndex = i;
++i;
while (str[i] != EOS)
{
++DecimalDigits; // why do you count decimal digits?
++i; // you do not use this result anyway...
}
for (i = (CommaIndex - 1); i >= 0; --i)
{
// what happens if you have non-digit characters? they participate
// in the conversion??
// you call std::pow(), but do not include <cmath> at the top of the file.
// isn't str[i] - '0' clearer ?
Result += (str[i] - ascii_to_int) * (std::pow(10, j));
++j;
}
j = 0;
for (i = (CommaIndex + 1); str[i] != EOS; ++i)
{
Result += (str[i] - ascii_to_int) * (std::pow(10, -j));
++j;
}
if (isNegative == 1) // you had defined constants fot this, but don't use them.
Result = Result * -1;
return Result;
}
int main()
{
char str[DIM];
leggiN(str);
std::cout << stof(str);
}
Here is one way to achieve what you want.
#include <iostream>
#include <string>
const char DECIMAL_POINT = ','; // we'll use a named constant here....
// usually, we'd have to check the locale
// for regional specific information.
// works like atod(), conversion stops at end of string of first illegal character.
double stof(const char* str) {
// check input, must be not null, not empty
if (!str || str[0] == 0)
return 0;
int i = 0;
bool isNegative = false;
// take care of leading sign
if (str[0] == '-' || str[0] == '+') {
isNegative = (str[0] == '-');
++i;
}
// convert integer part.
double result = 0;
while ('0' <= str[i] && str[i] <= '9') {
result = (result * 10) + (str[i] - '0');
++i;
}
// only do decimals if they are there.
if (str[i] != DECIMAL_POINT)
return (isNegative) ? -result : result;
++i; // skip decimal point
double decimals = 0;
double multiplier = .1;
while ('0' <= str[i] && str[i] <= '9') {
decimals += (str[i] - '0') * multiplier;
++i;
multiplier *= .1;
}
result += decimals;
return (isNegative) ? -result : result;
}
int main() {
// always use std::string to read strings from cin.
std::string str;
std::cout << "Insert a number: ";
std::cin >> str;
std::cout << "in: " << str << " out: " << stof(str.c_str()) << '\n';
return 0;
}
int function2 (const char * string1) returning the number of unique digits appearing in the string, e.g. function2 ("ab512af6kc1") -> 3.
int function2(const char* string1) {
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0,
seven = 0, eight = 0, nine = 0, counter = 0;
for (int i = 0; i < strlen(string1); i++) {
if (string1[i] == '0') {
zero++;
}
if (string1[i] == '1') {
one++;
}
if (string1[i] == '2') {
two++;
}
if (string1[i] == '3') {
three++;
}
if (string1[i] == '4') {
four++;
}
if (string1[i] == '5') {
five++;
}
if (string1[i] == '6') {
six++;
}
if (string1[i] == '7') {
seven++;
}
if (string1[i] == '8') {
eight++;
}
if (string1[i] == '9') {
nine++;
}
}
if (zero == 1) {
counter++;
}
if (one == 1) {
counter++;
}
if (two == 1) {
counter++;
}
if (three == 1) {
counter++;
}
if (four == 1) {
counter++;
}
if (five == 1) {
counter++;
}
if (six == 1) {
counter++;
}
if (seven == 1) {
counter++;
}
if (eight == 1) {
counter++;
}
if (nine == 1) {
counter++;
}
return counter;
}
It's every correct in this code, but it's long a bit. Could someone help me and write SHORTER code? It's the only way that I can measure up to this exercise.
You can use an array instead of 10 variables. Calculate the index in the array by converting the character to an integer.
int function2(const char *in) {
// Array to hold digits occurence counts.
unsigned digits[10]{};
// Iterate over the characters in input.
// Better (auto i : std::string_view(in)) in C++17.
for (auto i = in; *i; ++i) {
if (isdigit(*i)) {
// Increment the proper digit index.
digits[*i - '0']++;
}
}
int count = 0;
// Go through digit occurences.
for (auto i : digits) {
// If the digit occurred only once.
if (i == 1) {
// Increment the count.
count++;
}
}
return count;
}
To shorten your code, use an array instead of 10 individual variables:
int digits[10] = {0}; // instead of int zero = 0, one = 0, ...
To check whether a char is a representation of a digit, use isdigit:
if (isdigit(string1[i])) // instead of if (string1[i] == '0'), if (string1[i] == '1'), ...
The only non-trivial part is to convert a char to the corresponding int:
string1[i] - '0'
This code subtracts the character code of 0 (usually 48) from the character code of a digit (usually 49 for 1, 50 for 2, ..., 57 for 9). The result is an index to your array of counters.
So, to increase the proper array element, use the following code:
digit = string1[i] - '0';
digits[digit]++; // instead of zero++, one++, ...
After the code goes over the input string, count the number of digits which appeared once:
int counter = 0;
for (digit = 0; digit < 10; ++digit)
{
if (digits[digit] == 1)
++counter;
}
Use a hash table collection class to keep track of unique digits. In this case, unordered_set will do just fine. Don't even bother converting the char to integer. You're just looking for unique chars between '0' and '9'.
#include <string>
#include <unordered_set>
size_t getUniqueDigits(const std::string& string1)
{
std::unordered_set<char> table;
for (char c : string1)
{
if ((c >= '0') && (c <= '9'))
{
table.insert(c);
}
}
return table.size();
}
A more traditional "C" based solution that doesn't use any std:: collections or objects is to use an array to be that "set"
int getUniqueDigits(const char* string1)
{
int table[10] = {0};
int count = 0;
const size_t len = (string1 != nullptr) ? strlen(string1) : 0;
for(size_t i = 0; i < len; i++)
{
char c = string1[i];
if ((c >= '0') && (c <= '9'))
{
table[c - '0'] = 1;
}
}
for (char j = '0'; j <= '9'; j++)
{
count += table[j];
}
return count;
}
Just use an ordinary array as for example in this demonstrative program
#include <iostream>
size_t unique_digits( const char *s )
{
unsigned char digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
if ( digits[*s - '0'] != 2 ) ++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
The program output is
3
Or you can declare the array of the element type size_t. In this case the function will look the following way
#include <iostream>
size_t unique_digits( const char *s )
{
size_t digits[10] = { 0 };
for ( ; *s; ++s )
{
if ( '0' <= *s && *s <= '9' )
{
++digits[*s - '0'];
}
}
size_t count = 0;
for ( unsigned char c : digits ) count += c == 1;
return count;
}
int main()
{
std::cout << unique_digits( "ab512af6kc1" ) << '\n';
return 0;
}
I think you already have many good solutions.
Here is mine version anyway
int function2(const char* string1) {
int count[10] = {0};
int counter = 0;
int i;
for(i = 0; i < strlen(string1); i++)
int a = (++count[string1[i]-'0']);
if(a == 1)counter++;
if(a == 2)counter--;
return counter;
}
I haven't tried it. Hope there is no error
Edit:
I tried it. It seems to work fine now.
Is it possible to reverse an array without affecting the special characters ? By special characters, I mean anything characters not included from 'a' to 'z' and 'A' to 'Z'. I am short of ideas to build the algorithm, I still haven't it figured out.
One simple solution would be to Simple Solution:
1) Create a temporary character array --> ex: myArr[].
2) Copy alphabetic characters from the given array to myArr[].
3) Reverse myArr[] using standard string reversal algorithm.
4) Now traverse input string and myArr in a single loop. Wherever there is alphabetic character is input string, replace it with current character of myArr[].
Little problem with above solution, it requires extra space and it does two traversals of input string.
You can reverse with one traversal and without extra space. Below is algorithm.
1) Let input string be 'str[]' and length of string be 'a'
2) l = 0, r = a-1
3) While l is smaller than r, do following
a) If str[l] is not an alphabetic character, do l++
b) Else If str[r] is not an alphabetic character, do r--
c) Else swap str[l] and str[r]
Here's a solution that will do it "in place" in one pass.
bool isspecial(char c)
{
if ((c >= 'a') && (c <= 'z')) return false;
if ((c >= 'A') && (c <= 'Z')) return false;
return true;
}
void rev(char* array, int N)
{
int i = 0; // i points to the first index of the array
int j = N - 1; // j points to the last index of the array
while (i < j)
{
if (isspecial(array[i]))
{
i++;
}
else if (isspecial(array[j]))
{
j--;
}
else
{
char tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
}
}
Console.WriteLine("enter any string");
string str = Console.ReadLine();
string[] revstr = new string[str.Length];
for (int i = 0; i < str.Length; i++)
{
int ch = Convert.ToInt16(str.ToLower()[i]);
if ((ch < 97 || ch > 122))
{
revstr[i] = str[i].ToString();
}
}
for (int k = str.Length - 1; k >= 0; k--)
{
int ch = Convert.ToInt16(str.ToLower()[k]);
if (!(ch < 97 || ch > 122))
{
for (int j = 0; j < str.Length; j++)
{
if (revstr[j] == null)
{
revstr[j] = str[k].ToString();
break;
}
}
}
}
for (int s = 0; s < revstr.Length; s++)
{
Console.Write(revstr[s]);
}
If you want the position of the special characters to remain the same and the rest of the string to be reversed then this should work -
#include <iostream>
using namespace std;
void swap(char& a, char& b)
{
char temp = a;
a = b;
b = temp;
}
int main()
{
string s = "Hell$o World";
for(int i = 0, j = s.length() -1;i < s.length()/2; i++, j--) {
while((s[i] <= 'a' && s[i] >= 'Z') || s[i] >= 'z' || s[i] <= 'A') {
i++;
}
while((s[j] <= 'a' && s[j] >= 'Z') || s[j] >= 'z' || s[j] <= 'A') {
j--;
}
swap(s[i], s[j]);
}
cout << s << endl; //dlro$W olleH
return 0;
}
I have this code:
Str UpperCase()
{
Str Result;
int i = 0;
for (; string[i]; i++)
{
if (string[i] <= 'z' && string[i] >= 'a')
{
string[i] -= 32;
}
Result.string[i] = string[i];
}
Result.string[i] = 0;
return Result;
}
It will make String Uppercase.
What should I do if I want it to be Decussate?
Example: hi my name is pooya ==> Hi My NaMe Is PoOyA
Sorry for my bad english
and Thanks ;)
Str UpperCase()
{
Str Result;
int i = 0;
int decussate = 0;
for (; string[i]; i++)
{
if (string[i] <= 'z' && string[i] >= 'a')
{
decussate++;
if( decussate%2 == 1 ){
string[i] -= 32;
}
}
Result.string[i] = string[i];
}
Result.string[i] = 0;
return Result;
}
Add int decussate, by changing it between an odd and an even number everytime a lowercase letter is found, it will create a pattern in which the 1,3,5,7,and so on letters will be capitalized, assuming the string is in lowercase.