C program to convert string to integer and solve them algebraically [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to take a string consisting only of numbers and arithmetic operators. Then solve them algebraically. e.g. User input as string = "45 - 98 + 656" and get the output as "603" an integer.
Here's my code
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int main(void){
scanf(%s, &S);
int sum = 0;
int a;
for (int i = 0; i < strlen(S); i++) {
if (S[i] == ' ') {
continue;
} else
if (S[i] != ' ') {
if (isdigit(S[i])) {
a = atoi(&S[i]);
} else
if (!isdigit(S[i])) {
if (S[i] == '+') {
S[i] = S[i + 1];
sum = (sum + a);
} else
if (S[i] == '-') {
S[i] = S[i + 1];
sum = (sum - a);
} else {
sum = a;
}
}
}
}
printf("%d", sum);
}

Your code has syntax errors.
You forgot the " around %s
you did not declare S
Here is a simpler solution:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char buf[200];
if (fgets(buf, sizeof buf, stdin)) {
long sum = 0;
/* remove all white space */
for (int i = j = 0, len = strlen(buf); i <= len; i++) {
if (!isspace((unsigned char)buf[i]))
buf[j++] = buf[i];
}
/* parse the expression */
for (char *p = buf, *q;;) {
long a = strtol(p, &q, 10);
if (p == q) {
break;
} else {
sum += a;
p = q;
}
}
printf("sum = %ld\n", sum);
}
return 0;
}

This (unusual) solution should do the trick. It works strictly left-to-right:
sum= 0
number= 0
op= '+'
while get(character)
case character of
digit: case op of
'+': sum-= number; number= 10 * number + character; sum+= number
'-': sum+= number; number= 10 * number + character; sum-= number
'+', '-': number= 0; op= character
And now a slightly obfuscated, but very efficient C translation:
char* c= "45 - 98 + 656";
int s= 0, n= 0, d, p= 1;
for ( ; d= *c - '0', *c; c++)
if ((unsigned)d <= 9) { s-= n; n= 10 * n + p * d; s+= n; }
else if (*c != ' ') { n= 0; p= *c == '+' ? 1 : -1; }
printf("s = %d\n", s);
Prints out 603, as should.

Looking this code I see some error, after atoi() you have to increment the index according to number size (Eg "656" is 3 chars long).
Even after this fix this algorithm is wrong because you are executing the operation too early.
I mean, in your example, this algorithm compute -45+98 and do not compute 656.
Moreover S[i]=S[i+1]; is useless an so .. Wrong

Related

why can't my program recognize similar words in a string?

I want to write a program that will take an input T. In the next T lines, each line will take a string as an input. The output would be how many ways the string can be reordered.
#include <stdio.h>
#include <stdlib.h>
int main() {
int T, i, l, count = 1, test = 0, word = 0, ans;
char line[200];
scanf("%d", &T);
for (i = 0; i < T; i++) {
scanf(" %[^\n]", line);
l = strlen(line);
for (int q = 0; q < l; q++) {
if (line[q] == ' ') {
word++;
}
}
ans = fact(word + 1);
word = 0;
for (int j = 0; j < l; j++) {
for (int k = j + 1; k < l; k++) {
if (line[k] == ' ' && line[k + 1] == line[j]) {
int m = j;
int n = k + 1;
for (;;) {
if (line[m] != line[n]) {
break;
} else
if (line[m] == ' ' && line[n] == ' ') {
test = 1;
break;
} else {
m++;
n++;
}
}
if (test == 1) {
count++;
ans = ans / fact(count);
count = 0;
test = 0;
}
}
}
}
printf("%d\n", ans);
}
}
int fact(int n) {
if (n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
Now, in my program,
my output is like this:
2
no way no good
12
yes no yes yes no
120
if T = 2 and the 1st string is no way no good, it gives the right output that is 12 (4!/2!). That means, it has identified that there are two similar words.
But in the 2nd input, the string is yes no yes yes no. that means 3 yes and 2 nos. So the and should be 5!/(3!2!) = 10. But why is the answer 120? and why can't it recognize the similar words?
The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ') but this test fails to identify a duplicate that occurs with the last word because line[n] is '\0', not ' '.
Note these further problems:
you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count); only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans to be divided by 23 = 8, instead of 3! = 6.
you should protect against buffer overflow and detect invalid input with:
if (scanf(" %199[^\n]", line) != 1)
break;
the range of type int for ans is too small for a moderately large number of words: 13! is 6227020800, larger than INT_MAX on most systems.
The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.
Here is a modified version using this approach:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmpstr(const void *p1, const void *p2) {
char * const *pp1 = p1;
char * const *pp2 = p2;
return strcmp(*pp1, *pp2);
}
unsigned long long factorial(int n) {
unsigned long long res = 1;
while (n > 1)
res *= n--;
return res;
}
int main() {
int T, i, n, begin, count;
unsigned long long ans;
char line[200];
char *words[100];
if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
return 1;
while (T --> 0) {
if (!fgets(line, sizeof line, stdin))
break;
n = 0;
begin = 1;
for (char *p = line; *p; p++) {
if (isspace((unsigned char)*p)) {
*p = '\0';
begin = 1;
} else {
if (begin) {
words[n++] = p;
begin = 0;
}
}
}
qsort(words, n, sizeof(*words), cmpstr);
ans = factorial(n);
for (i = 0; i < n; i += count) {
for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
continue;
ans /= factorial(count);
}
printf("%llu\n", ans);
}
return 0;
}

K&R C Programming Language Exercise 2-3 code returns rubbish

I tried to write a solution from exercise 2-3. After compilation, it returns random numbers on output. I don't really understand where this issue is coming from.
Any help appreciated.
StackOverflow keeps asking for more details. The purpose of the program is listed in the code bellow.
More delails.
Purpose of the code:
Write the function htoi(s), which converts a string of hexa-
decimal digits (including an optional 0x or 0X) into its
equivalent integer value. The allowable digits are 0 through 9,
a through f, and A through F.
/*
* Write the function htoi(s), which converts a string of hexa-
* decimal digits (including an optional 0x or 0X) into its
* equivalent integer value. The allowable digits are 0 through 9,
* a through f, and A through F.
*/
#include <stdio.h>
#include <math.h>
int hti(char s)
{
const char hexlist[] = "aAbBcCdDeEfF";
int answ = 0;
int i;
for (i=0; s != hexlist[i] && hexlist[i] != '\0'; i++)
;
if (hexlist[i] == '\0')
answ = 0;
else
answ = 10 + (i/2);
return answ;
}
unsigned int htoi(const char s[])
{
int answ;
int power = 0;
signed int i = 0;
int viable = 0;
int hexit;
if (s[i] == '0')
{
i++;
if (s[i] == 'x' || s[i] == 'X')
i++;
}
const int stop = i;
for (i; s[i] != '\0'; i++)
;
i--;
while (viable == 0 && i >= stop)
{
if (s[i] >= '0' && s[i] <= '9')
{
answ = answ + ((s[i] - '0') * pow(16, power));
}
else
{
hexit = hti(s[i]);
if (hexit == 0)
viable = 1;
else
{
hexit = hexit * (pow(16, power));
answ += hexit;
}
}
i--;
power++;
}
if (viable == 1)
return 0;
else
return answ;
}
int main()
{
char test[] = "AC";
int i = htoi(test);
printf("%d\n", i);
return 0;
}
answ is not initialized in htoi. Initialize it to zero.

Count frequency of digits in string

I need to implement a function that can count the number of digits in a string. So for numbers but also for somehting like: aD23b. If I could make it work...it should look like:
Input: 0912302
Output:
0: 2
1: 1
2: 2
3: 1
4: 0
5: 0
6: 0
7: 0
8: 0
9: 1
At this point I can't code anything that works unfortunately...My basic idea is: Use a loop to check every character from Input, if it's a digit, store it in a second array (let's say frequency). The problems I have are that I need to somehow convert every character into a integer or somehow be able to count how
often each digits appears... I was hoping this might work but it doesn't at all:
I forgot to mention I'm a beginner in programming so I would really appreciate if you could give me tips and explanations.
void calc_occurrences(int s[], int occurrences[])
{
int i = 0;
int j;
int count = 0;
while (s[i] != '\0') {
if (isdigit(s[i])) {
for (j = 0; occurrences[j] != '\0'; j++) {
occurrences[j] = s[i];
}
}
i++;
for (j = i + 1; s[j] != '\0'; j++) {
if (isdigit(s[i]) == isdigit(s[j])) {
count++;
occurrences[j] = 0;
}
}
if(occurrences[i] != 0) {
occurrences[i] = count;
}
}
}
Make an array to count the frequency of each relevant character.
Something like this:
#include <stdio.h>
void count_freq(char* str, int freq[10])
{
int i = 0;
while(str[i]) // Loop to end of string
{
if (str[i] >= '0' && str[i] <= '9') // Check that the character is in range
{
++freq[str[i]-'0']; // notice the -'0' to get in range 0..9
}
++i;
}
}
int main(void) {
int freq[10] = {0}; // Array to count occurence
char str[] = "0034364hh324h34"; // Input string
count_freq(str, freq); // Calculate frequency
for (int i=0; i < 10; ++i) // Print result
{
printf("%d: %d\n", i, freq[i]);
}
return 0;
}
Output:
0: 2
1: 0
2: 1
3: 4
4: 4
5: 0
6: 1
7: 0
8: 0
9: 0
You can have an integer array with size 10 with 0 stored in all indices. Then, when you spot a digit, you can increment the number in the respective index.
In example, when you see a "0", you can do arr[0]++;.
Also, you may check if a character is a digit with the isdigit() function.
PS : I know, I'm answering an old post, but I was doing some challenges on HackerRank, and I managed to solve this nearly exact problem, in case it might help someone since I've used dynamic allocation on my code.
/* Problem: hackkerrank.com/challenges/frequency-of-digits-1/problem */
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main(void)
{
char *s;
int *arr;
int i;
i = 0;
s = (char*)malloc(sizeof(char));
scanf("%s", s);
arr = (int*)malloc(10 * sizeof(int));
while(i < 10)
{
*(arr + i) = 0;
i++;
}
i = 0;
while (i < strlen(s))
{
if (*(s + i) >= '0' && *(s + i) <= '9')
{
(*(arr + (*(s + i) - '0'))) += 1;
}
i++;
}
i = 0;
while (i < 10)
{
printf("%d ", *(arr + i)); // As HackerRank problem wanted the output format.
// printf("%d: %d\n", i, *(arr + i)); As you wanted it
i++;
}
return (0);
}

How to handle negative integer when converting them to strings? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I need to convert integer to a string, be it negative or positive.
So far i able to convert positive integers to strings using the following code.
But not the negative ones. How can i handle them properly to convert them to strings.
Here is the code that i was using.
Thanks
Rajat!
/*
* C Program which Converts an Integer to String & vice-versa
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
tostring(str, num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
if(num<0)
{
n=(-1)*(num);
}
else
{
n=num;
}
while (n != 0)
{
len++;
n /= 10;
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
str[len - (i + 1)] = rem + '0';
}
str[len] = '\0';
}
Before doing anything else, see if n is negative. If it is, start the output with the sign - (make sure len is also one more than it would be otherwise, and that your stringification starts one character later), make n positive, and continue as you were doing it before.
You have to be really wary of "corner-case" like many other have said :
You can't have the positive value of a negative int in an int
The range value of an int is [MIN; +MIN -1], like –2,147,483,648 to 2,147,483,647 for a 4 byte int.
So, if you have –2,147,483,648 and you *-1, you will not have 2,147,483,648 since it will overflow the int capacity
Your loop for finding the len of int is "bad", because you don't take negative number in count (but I suppose this is the purpose of this post) and you don't take car of the corner case 0 ("len" value is 0 but must be 1).
So, how can you make this function ?
1 : Fix the int len calculation
size_t len = 1;
for (int n = number; n <= -10 || 10 <= n; n /= 10) {
++len;
}
2 : Fix the "digit to char" loop
for (size_t i = 0; i < len; ++i) {
str[len - i - 1] = abs(number % 10) + '0';
number /= 10;
}
str[len] = '\0';
There. The only thing that left is to put "-" in the beginning and have an offset for negative case number.
You can have an offset variable (fix the "digit to char loop" if you use it) or you can simply do "++str".
There, you can do the function on your own now, I pratically gived you the answer.
On a funny note, you can skip the "abs" function if you simply do the following :
void tostring(char *str, int number)
{
char *digit = "9876543210123456789" + 9;
size_t len = 1;
if (number < 0) {
// TODO : Put '-' in the first case
// TODO : Make str to be *str[1]
}
for (int n = number; n <= -10 || 10 <= n; n /= 10) {
++len;
}
for (size_t i = 0; i < len; ++i) {
str[len - i - 1] = digit[number % 10];
number /= 10;
}
str[len] = '\0';
}
If you don't understand how this work, take your time and read how pointer work (especially pointer arithmetic).
I have solved the issue by the help from #Amadan .
Here is the code that i am using. Please feel free to tell me a more better way to solve this issue.
Thanks
Rajat
/*
* C Program which Converts an Integer to String & vice-versa
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
tostring(str, num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
bool flag=0;
if(num<0)
{
n=-num;
flag=1;
}
else
{
n=num;
flag=0;
}
while (n != 0)
{
len++;
n /= 10;
}
if(flag==1)
{
num=-1*num;
str[0]='-';
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
if(flag==1)
{
str[len - (i)] = rem + '0';
}
else
{
str[len - (i + 1)] = rem + '0';
}
}
if(flag==1)
{
str[len+1] = '\0';
}
else
{
str[len] = '\0';
}
}
Just use sprintf function as below,
sprintf(str,"%i",num);
So the modified code will be,
#include <stdio.h>
#include <string.h>
#include <math.h>
void tostring(char [], int);
int main()
{
char str[10];
int num, result;
printf("Enter a number: ");
scanf("%d", &num);
//tostring(str, num);
sprintf(str,"%i",num);
printf("Number converted to string: %s\n", str);
return 0;
}
void tostring(char str[], int num)
{
int i, rem, len = 0, n;
n =num;
while (n != 0)
{
len++;
n /= 10;
}
for (i = 0; i < len; i++)
{
rem = num % 10;
num = num / 10;
str[len - (i + 1)] = rem + '0';
}
str[len] = '\0';
}
Hope this helps.
Here you have the function which works with any base (you need just to find enough chars to represent digits) but it will not work in one corner case (can you find the case?)
static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUWXYZ";
static char *reverse(char *s, size_t len)
{
size_t pos;
for(pos = 0; pos < len / 2; pos++)
{
char tmp = s[pos];
s[pos] = s[len - pos - 1];
s[len - pos - 1] = tmp;
}
return s;
}
char *toString(char *buff, int n, unsigned base)
{
int saved = n;
char *savedbuff = buff;
n = n < 0 ? -n : n; // <= there is one number which will cause problems. Which one?
do
{
*buff++ = Digits[n % base];
n /= base;
}while(n);
if(saved < 0) *buff++ = '-';
*buff = 0;
return reverse(savedbuff, buff - savedbuff);
}
int main()
{
char buff[50];
printf("%s\n", toString(buff, -255,12)); // 12 base :)
printf("%s\n", toString(buff, -976,10)); // 10 base
printf("%s\n", toString(buff, -976,8)); // or maybe octal ?
return 0;
}

Hex/Dec Program in C getting the wrong output and cant use Scanf

Whenever I run my program, I think that I am getting the wrong output using the included test strings, though I think my first function is working. Tthe files I have are xbits.c xbits.h and two versions of showxbits.c, one that is instructor provided and the other is the one I am trying to use scanf with. The program is supposed to convert an integer to a hex string and then a hex string to an integer. My main problem is, while I think that my code works with the instructor test input, I know it doesn't work with the scanf showxbits because it gives answers such as 0xS when 127 is inputed.
Here is the xbits.c
#include <stdio.h>
#include <math.h>
int hex_To_dec(int c) {
char hex_values[] = "aAbBcCdDeEfF";
int i;
int answer = 0;
for (i=0; answer == 0 && hex_values[i] != '\0'; i++) {
if (hex_values[i] == c) {
answer = 10 + (i/2);
}
}
return answer;
}
/* function represents the int n as a hexstring which it places in the
hexstring array */
void itox(char* s, int n)
{
char *digits = "0123456789ABCDEF";
int i=0,j;
char temp;
while(n > 0)
{
s[i] = digits[n % 16];
n /= 16;
i++;
}
s[i] = '\0'; // Add null terminator
i--;
// Now reverse it in place
for(j=0; j < i / 2; j++)
{
temp = s[j];
s[j] = s[i - j];
s[i - j] = temp;
}
}
/* function converts hexstring array to equivalent integer value */
int xtoi(char hexstring[]) {
//printf("in xtoi, processing %s\n", hexstring);
int answer = 0;
int i = 0;
int valid = 1;
int hexit;
if (hexstring[i] == '0') {
++i;
if (hexstring[i] == 'x' || hexstring[i] == 'X') {
++i;
}
}
while(valid && hexstring[i] != '\0') {
answer = answer * 16;
if(hexstring[i] >='0' && hexstring[i] <= '9') {
answer = answer + (hexstring[i] - '0');
}
else {
hexit = hex_To_dec(hexstring[i]);
if (hexit == 0) {
valid = 0;
}
else {
answer = answer + hexit;
}
}
++i;
}
if(!valid) {
answer = 0;
}
return answer;
}
Here is the showxbits.c provided by the instructor:
/*
* stub driver for functions to study integer-hex conversions
*
*/
#include <stdio.h>
#include <string.h>
#include "xbits.h"
#define ENOUGH_SPACE 1000 /* not really enough space */
int main() {
char hexstring[ENOUGH_SPACE];
int m=0, n = 0x79FEB220;
itox(hexstring, n);
/* for stub testing: create a fake input string */
strcpy(hexstring, "6BCD7890");
m = xtoi(hexstring);
printf("\t%12d %s %12d\n", n, hexstring, m);
return 0; /* everything is just fine */
}
And here is the showxbits that has scanf in it:
/*
* stub driver for functions to study integer-hex conversions
*
*/
#include <stdio.h>
#include <string.h>
#include "xbits.h"
#define ENOUGH_SPACE 100 /* not really enough space */
int main() {
char hexstring[ENOUGH_SPACE];
//int m=0, n = 0x79FEB220;
int n, m;
while ((scanf("%d", &n)) == 1) {
itox(hexstring, n);
m = xtoi( hexstring);
printf("%12d %s %12d\n", n, hexstring, m);
}
return 0; /* everything is just fine */
}
Like I said, I am getting weird outputs when using the scanf function. I am a complete beginner programmer and would really appreciate any help that can be offered. Thanks!
Because there is a mistake in the function itox , which would cause the wrong result when reverse string. Then, the wrong hexstring from itox will result in the abnormal output finally.
The quick fix is to replace j < i / 2 with j < i / 2 + 1
void itox(char* s, int n)
{
//......
// Now reverse it in place
for(j=0; j < i / 2 + 1 ; j++)
{
temp = s[j];
s[j] = s[i - j];
s[i - j] = temp;
}
}
You don't need to reverse the string to convert to hex ascii:
#include <stdio.h>
const char* hexlat="0123456789ABCDEF";
char *binaryToHex(unsigned int answer, char *result){
if(answer==0) return result;
else{
result=binaryToHex(answer>>4,result);
*result=hexlat[answer & 0x0F];
return result+1;
}
};
int main(void) {
unsigned int answer=0x12340ADF;
char hexAnswer[32];
*binaryToHex(answer,hexAnswer)='\0';
printf("%s",hexAnswer);
return 0;
}

Resources