Changing gets() to txt file input [closed] - c

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 7 years ago.
Improve this question
I need to covert this code from a user input using gets() to scanning in an input txt file.
It would also be helpful to find a way to count the number of letters in every word. Starting with 1 letter words and on.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
int acount, bcount, ccount, dcount, ecount, fcount, gcount, hcount, icount, jcount, kcount, lcount, mcount, ncount, ocount, pcount, qcount, rcount, scount, tcount, ucount, vcount, wcount, xcount, ycount, zcount = 0;
char *str;
printf("Enter any string : ");
gets(str);
while (*str != '\0')
{
if(isalpha(*str))
{
toupper(*str);
switch(*str)
{
case 'A':
++acount;
break;
case 'B':
++bcount;
break;
case 'C':
++ccount;
break;
case 'D':
++dcount;
break;
case 'E':
++ecount;
break;
case 'F':
++fcount;
break;
case 'G':
++gcount;
break;
case 'H':
++hcount;
break;
case 'I':
++icount;
break;
case 'J':
++jcount;
break;
case 'K':
++kcount;
break;
case 'L':
++lcount;
break;
case 'M':
++mcount;
break;
case 'N':
++ncount;
break;
case 'O':
++ocount;
break;
case 'P':
++pcount;
break;
case 'Q':
++qcount;
break;
case 'R':
++rcount;
break;
case 'S':
++scount;
break;
case 'T':
++tcount;
break;
case 'U':
++ucount;
break;
case 'V':
++vcount;
break;
case 'W':
++wcount;
break;
case 'X':
++xcount;
break;
case 'Y':
++ycount;
break;
case 'Z':
++zcount;
break;
}//Close case
}//Close if
}//Close while
printf("Number of A's: %d", acount);
}

Many errors in your code
You don't initialize all the (x)count variables to 0, read about the coma operator.
You used gets() which is a mean and deprecated function.
You passed an uninitialized pointer to gets() which is undefined behavior.
toupper(*str) does not modify *str.
Try this one
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
/* You need an array of int's with size equal to the number of letters
* int the alphabet
*/
int count['Z' - 'A' + 1];
/* You need some space to store the text, `str' will become a poitner
* when you pass it to `fgets()' pointing to an array of 1000 `chars'
*/
char str[1000];
/* Initialize all the counters to 0 */
for (int i = 0 ; i < sizeof(count) / sizeof(*count) ; ++i)
count[i] = 0;
printf("Enter any string : ");
/* Read the string, use `fgets()` and prevent a buffer overflow */
if (fgets(str, sizeof(str), stdin) == NULL)
return -1;
/* Now count the letters */
for (int i = 0 ; ((str[i] != '\0') && (str[i] != '\n')) ; ++i)
{
/* If it's not a letter, go to the next one */
if (isalpha((int) str[i]) == 0)
continue;
/* It's a letter, count it at the correct position */
count[toupper((int) str[i]) - 'A'] += 1;
}
/* Print the count of each letter, skipping those that did not appear */
for (int i = 0 ; i < sizeof(count) / sizeof(*count) ; ++i)
{
if (count[i] == 0)
continue;
fprintf(stderr, "Number of %c's : %d\n", i + 'A', count[i]);
}
return 0;
}

All remarks in iharob response are correct. Read my comment on his response for extra problems. Here is a simple solution:
#include <stdio.h>
int main(void) {
int counts[256] = { 0 };
int c;
printf("Enter any string: ");
while ((c = getchar()) != EOF && c != '\n') {
counts[c & 255]++;
}
printf("Number of A's: %d", counts['a'] + counts['A']);
return 0;
}
EDIT: here is a solution to handle a file instead of a line of input:
#include <stdio.h>
int main(int argc, char **argv) {
long long int counts[256] = { 0 };
int c;
FILE *f;
if (argc < 2) {
fprintf(stderr, "usage: %s FILE\n", argv[0]);
exit(2);
}
if ((f = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
exit(1);
}
while ((c = getc(f)) != EOF) {
counts[c & 255]++;
}
fclose(f);
printf("Number of A's: %lld", counts['a'] + counts['A']);
return 0;
}

Related

seeking combinations (strstr) of letters in external file

I have a task to make smth like t9 like it was in old phones (number can also mean some combination of letters). For example, if user run it this way ./t9search 23 < list.txt, program should return numbers which has this combination of digits or letters that corresponds to them (in this case a,b,c and d,e,f). It's also forbidden to work with dynamic memory(malloc, free) and functions with algorithms (qsort, lsearch etc). Format of information in file is "name\n number\n name\n number\n...".
The loop doesn't work correctly but I can't find a mistake. The program should return {Name}, {number}but it return only numbers.
The code is:
`
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define FULFILLED 1
#define NOT_FULFILLED 0
int main(int argc, char **argv)
{
char line[99];
int line_no = -1;
int size = strlen(argv[1]);
char letters[size][5];
int total_combinations = 1;
char combinations[total_combinations][size + 1];
int current_combination[size];
int check_name = NOT_FULFILLED;
char name[99];
for(int i = 0; argv[1][i]; i++)
{
switch(argv[1][i]) //cases according to input
{
case '0':
strcpy(letters[i], "+");
break;
case '2':
strcpy(letters[i], "abc");
break;
case '3':
strcpy(letters[i], "def");
break;
case '4':
strcpy(letters[i], "ghi");
break;
case '5':
strcpy(letters[i], "jkl");
break;
case '6':
strcpy(letters[i], "mno");
break;
case '7':
strcpy(letters[i], "pqrs");
break;
case '8':
strcpy(letters[i], "tuv");
break;
case '9':
strcpy(letters[i], "wxyz");
break;
}
total_combinations *= strlen(letters[i]); //number of combinations of letters from array elements
}
for (int i = 0; i < size; i++)
{
current_combination[i] = 0;
}
int k = 0;
while (k < total_combinations)
{
for (int set_idx = 0; set_idx < size; set_idx++)
{
int letter_idx = current_combination[set_idx];
combinations[k][set_idx] = letters[set_idx][letter_idx];
}
combinations[k][size] = '\0';
for(int i = size - 1; i >= 0; i--)
{
current_combination[i]++;
if (current_combination[i] == strlen(letters[i]))
{
current_combination[i] = 0;
}
else
{
break;
}
}
k++;
}
printf("%c\n", sizeof(combinations)/sizeof(combinations[0]));
while(fgets(line, sizeof(line), stdin))
{
line_no++;
if (line_no % 2 == 0) //even lines (names)
{
name[99] = line; //variable to use name with number
for (int i = 0; i < total_combinations; i++) //for each combination from array with combinations
{
if (strstr(line, combinations[i])) //if combination is a substring of a string
{
check_name = FULFILLED;
}
}
}
else if (line_no % 2 == 1) //odd lines (numbers)
{
if (check_name == FULFILLED || strstr(line, argv[1])) // if there's name that corresponds with input OR input is a substring of a string
{
printf("%s, %s", name, line);
check_name = NOT_FULFILLED;
}
}
}
}
`
I've tried to change the way of checking names:
if (line_no % 2 == 0)
{
for (int j = 0; j <= strlen(letters); j++)
{
char let = getchar();
for (int i = 0; i < strlen(line); i++)
{
if (letters[j] == line[i])
{
check_name = FULFILLED;
continue;
}
else if (letters[j] != line [i])
{
break;
}
}
}
}
Sure I didn't reach success. So I'd be extremely grateful for any help.
Arrays do not resize reflectively when the variables used to create them change. They are sized permanently at the time of their initialization. The following
int total_combinations = 1;
char combinations[total_combinations][size + 1];
/* ... */
total_combinations *= strlen(letters[i]);
does not cause combinations to grow as total_combinations does. Move the definition of combinations to after total_combinations has been fully computed.
The following attempts to assign a char * to a char, and also indexes name out of bounds.
name[99] = line;
As done previously, use strcpy to copy strings.
Note that, if found and if there is room in the buffer, fgets stores the newline character in the buffer, so
printf("%s, %s", name, line);
will very likely print staggered output, like
Alice
, 5551234567
A cursory refactoring:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *remove_newline(char *string)
{
if (string)
string[strcspn(string, "\n")] = '\0';
return string;
}
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "usage: %s t9_sequence\n", argv[0]);
return EXIT_FAILURE;
}
int size = strlen(argv[1]);
char letters[size][5];
int total_combinations = 1;
int current_combination[size];
for (int i = 0; argv[1][i]; i++) {
switch (argv[1][i]) {
default:
fprintf(stderr, "Invalid input: \"%c\"\n", argv[1][i]);
return EXIT_FAILURE;
case '0':
strcpy(letters[i], "+");
break;
case '2':
strcpy(letters[i], "abc");
break;
case '3':
strcpy(letters[i], "def");
break;
case '4':
strcpy(letters[i], "ghi");
break;
case '5':
strcpy(letters[i], "jkl");
break;
case '6':
strcpy(letters[i], "mno");
break;
case '7':
strcpy(letters[i], "pqrs");
break;
case '8':
strcpy(letters[i], "tuv");
break;
case '9':
strcpy(letters[i], "wxyz");
break;
}
total_combinations *= strlen(letters[i]);
}
memset(current_combination, 0, sizeof current_combination);
char combinations[total_combinations][size + 1];
for (int k = 0; k < total_combinations; k++) {
for (int set_idx = 0; set_idx < size; set_idx++) {
int letter_idx = current_combination[set_idx];
combinations[k][set_idx] = letters[set_idx][letter_idx];
}
combinations[k][size] = '\0';
for (int i = size - 1; i >= 0; i--) {
current_combination[i]++;
if (current_combination[i] != strlen(letters[i]))
break;
current_combination[i] = 0;
}
}
char name[128];
char number[128];
while (1) {
if (!fgets(name, sizeof name, stdin))
break;
if (!fgets(number, sizeof number, stdin))
break;
int found = 0;
for (int i = 0; i < total_combinations; i++) {
if (strstr(name, combinations[i])) {
found = 1;
break;
}
}
if (found || strstr(number, argv[1]))
printf("%s, %s\n", remove_newline(name), remove_newline(number));
}
}

C language: Given a string, delete/remove the words that contain the n number of vowels

Given an integer n, the program has to delete each word, that contains the n number of vowels.
The string is read from a test.txt file, which contains the following:
Astazi nu este maine.
Currently my program contains a count1 function, that counts the number of characters and vowels for each word in the string.
How can I use the data from count1 function as a refference when typing in the n vowels to delete the needed words then print the updated string?
I have an idea, which I'm unsure how to implement. In count1 we already count the number of vowels per each word, so, given n by the user we check if this number is equal to v in the count1 function and so we do int num_of_words++, then we do a loop, which prints out the needed words, until num_of_words=0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void count1 (char* str)
{
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
len = i - 1 - w;
printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
if (c)
break;
else
return;
}
break;
}
}
void count2 (char* str, int n)
{
char line2[128];
int ls=strlen(str);
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
for(int k = 0; str[k] != '\0'; k++)
{
if (k == 0 || isspace(str[k]))
{
if(v==n)
{
strcat(line2, str+1);
}
}
}
printf("%s ", line2);
if (c)
break;
else
return;
}
break;
}
}
int main()
{
FILE *fp;
char line[128];
int c=0, count[26]= {0}, x;
int n;
fp = fopen("test.txt", "r");
fscanf(fp, "%[^\n]", line);
fclose(fp);
printf("%s\n\n", line);
while (line[c] != '\0')
{
if (line[c] >= 'a' && line[c] <= 'z')
{
x = line[c] - 'a';
count[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
printf("\n");
count1(line);
printf("\nInsert n: ");
scanf("%d", &n);
count2(line, n);
return 0;
}
If you have a string str that consists of separate words, separated one from another by ' ' or '\n' or '\t', and you want to have a string that contains all the words in str that satisfy some condition, it will be a bit difficult to program it such that it will be "in-place", i.e. to change str to the desired string, without using a "helper array" of some sort.
Instead, I would recommend to create a new char array with the same size (say str2), and every time you find a word that satisfies the condition (the condition can be for example: doesn't have 1 vowel), you copy the word that you found from str to str2.
Something like this:
char str[128];
// read from file to str using fscanf
char str2[128];
for (int c = 0; str[c] != '\0'; ++c)
{
if (c == 0 || isspace(str[c]))
{
if (! is_1_vowel[str+1]) // if it doesn't have exacly one vowel
{
// copy the word from str to str2
strcat_word(str2, str+1); // a user-defined adapted version of strcat that will copy from src to dest only till src reaches a space character or '\0'
}
}
}
I'm assuming here that is_1_vowel will be a function that goes over a single word (and not the whole line or file), and returns 1 if it satisfies the condition (has 1 vowel), and returns 0 otherwise.
Here's my final solution
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void count1 (char* str)// count numbers of vowels for each word
{
for (int i = 0;;)
for (int v = 0, w = i;;)
{
int len;
char c = str[i++];
switch (c)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
v++;
default:
continue;
case ' ':
case '\t':
case '\n':
case '\0':
len = i - 1 - w;
printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
if (c)
break;
else
return;
}
break;
}
}
void print_x(char* str, int n)
{
char* tmp;
unsigned int cnt = 0, stat = 0;
const char aeiou[] = "AEIOUaeiou";
while(*str)
{
switch(stat)
{
case 0://the word did not start
if (!isalpha(*str))
{
putchar(*str);
break;
}
stat = 1;
tmp = str;
cnt = 0;
case 1://the word started
if (strchr(aeiou, *str))
{
cnt++;
break;
}
if (! isalpha(*str))
{
if (cnt != n)
while(tmp <= str) putchar(*(tmp++));
else putchar(*str);
stat = 0;
}
} // end switch
++str;
}
if (stat)
{
--str;
if (cnt != n) while(tmp <= str) putchar(*(tmp++));
}
}
int main()
{
FILE *fp;
char line[128], line2[128];
int c=0, count[26]= {0}, x;
int n,a;
int i,j;
fp = fopen("test.txt", "r");
fscanf(fp, "%[^\n]", line);
fclose(fp);
printf("%s\n\n", line);
while (line[c] != '\0')
{
if (line[c] >= 'a' && line[c] <= 'z')
{
x = line[c] - 'a';
count[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
for (i = 0; i < 26; ++i)
{
for (j = i + 1; j < 26; ++j)
{
if (count[i] < count[j])
{
a = count[i];
count[i] = count[j];
count[j] = a;
}
}
}
printf("\n\n");
for (c = 0; c < 26; c++)
{
printf("%c occurs %d times.\n", c + 'a', count[c]);
}
printf("\n");
count1(line);
printf("\nInsert n: ");
scanf("%d", &n);
if (!(fp = fopen("./test.txt", "r")))
{
printf("unable open file\n");
return 1;
}
while (fgets(line, 128, fp))
print_x(line, n);
fclose(fp);
return 0;
}

Program not receiving required input

I have a problem with my homework. I have some code written by teacher and I suppose to edit it in order to make a calculator. So I added couple of lines i thought it will work, but sadly it's not the case. Program returns always that operands or operator is wrong. Can you have a look?
main.c
#include "stdio.h"
#include "evalexpression.h"
int main() {
char string[100];
int result;
result = InterCalc(string);
CalcFilter(result, string);
return 0;
}
evalexpression.c
#include "stdio.h"
#include "string.h"
#include "evalexpression.h"
#include "math.h"
#include "float.h"
static float f1, f2;
static char op;
int isValidExpression(const char *str) {
int res;
char ops[10];
res = sscanf(str, "%f %s %f", &f1, ops, &f2);
if (res == 3) {
if (ops[0] == '+' || ops[0] == '-' || ops[0] == '^' || ops[0] == '*' || ops[0] == '/') {
op = ops[0];
return 1;
} else
return 0;
} else
return 0;
}
int getOperator() {
return (op);
}
float getFstOperand() {
return (f1);
}
float getSecOperand() {
return (f2);
}
float getExprValue() {
int operation;
operation = getOperator();
switch (operation) {
case 1:
return (getFstOperand() + getSecOperand());
break;
case 2:
return (getFstOperand() - getSecOperand());
break;
case 3:
return (getFstOperand() / getSecOperand());
break;
case 4:
return (getFstOperand() * getSecOperand());
break;
case 5:
return (pow(getFstOperand(), getSecOperand()));
break;
default:
return 0;
}
}
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
if (strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else
return 1;
}
void CalcFilter(int a, char *str) {
float calculation_value;
printf("Press 'E' to display the invalid line or press 'V' to display the valid line\n");
int choice;
choice = getchar();
switch (choice) {
case 'E':
case 'e':
if (a == 0) printf("The line %s is invalid.\n", str);
else if (a == 1) printf("There's nothing wrong with the line %s\n", str);
break;
case 'V':
case 'v':
if (a == 1) {
calculation_value = getExprValue();
printf("The result of %s is %f.\n", str, calculation_value);
}
if (a == 0) printf("The line %s is invalid\n", str);
break;
default:
printf("You haven't chosen the valid option of the switch\n");
break;
}
}
You should pass the size of the destination buffer to function InterCalc(). As written, it can only read sizeof(char*) - 1 bytes at a time. You should also check for end of file.
int InterCalc(char *my_string, size_t size) {
if (fgets(my_string, size, stdin) == NULL
|| strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else {
return 1;
}
}
Invoke from main():
#include <stdio.h>
#include "evalexpression.h"
int main(void) {
char string[100];
int result;
result = InterCalc(string, sizeof(string));
CalcFilter(result, string);
return 0;
}
Notes:
you should use the <stdio.h> syntax for standard headers.
you should prevent buffer overflow by passing the maximum number of characters for %s formats in sscanf(): sscanf(str, "%f %9s %f", &f1, ops, &f2);
EDIT: There is another problem in GetExrValue(): you switch on values from 0 to 5 for op instead of the operation character. Here is a way to correct this:
float getExprValue(void) {
switch (getOperator()) {
case '+':
return getFstOperand() + getSecOperand();
case '-':
return getFstOperand() - getSecOperand();
case '/':
return getFstOperand() / getSecOperand();
case '*':
return getFstOperand() * getSecOperand();
case '^':
return pow(getFstOperand(), getSecOperand());
default:
return 0;
}
}

Using for loops to print specific "non-vowel, vowel, non-vowel" words

I have a task to print a list of words made up of "non-vowel, vowel, non-vowel", i.e bab, bac, bad, bad ... through to zuz.
I have managed to create a code which does the first two letters but gets lost on the last loop and prints only '}' - which seems strange to me. The code is below:
#include <stdio.h>
#include <string.h>
int check_vowel(char c);
int check_consonant(char c);
int main ()
{
char c, c2, c3;
int cnt;
for (cnt = 0; cnt <= c; cnt++)
{
for (c = 'a'; c <= 'z'; c++)
{
if (check_vowel(c) == 0)
{
for (c2 = 'a'; c2 <= 'z'; c2++)
{
if (check_consonant(c2) == 0)
{
for (c3 = 'a'; c3 <= 'z'; c3++);
{
if (check_vowel(c3) == 0)
{
cnt++;
printf("%d || %c%c%c\n", cnt, c, c2, c3);
}
}
}
}
}
}
}
printf("Total names = %d", cnt);
return 0;
}
int check_vowel(char c)
{
switch(c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return 1;
default:
return 0;
}
}
int check_consonant(char c)
{
switch(c)
{
case 'b':
case 'c':
case 'd':
case 'f':
case 'g':
case 'h':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
return 1;
default:
return 0;
}
}
The outputs are along the lines of:
1 || ba}
2 || be}
etc
The first bug is in this line:
for (c3 = 'a'; c3 <= 'z'; c3++);
Because of the semicolon at the end of that line, the iteration body is "do nothing". The block of code after it (from { to }) is just treated as something to do after this loop. When you enter this block of code, c3 will always be {, because it's the first character after z (in most character encodings). The fix: remove the semicolon.
The second bug is in the choice of conditions. The condition check_vowel(c3) == 0 (what you wrote) is not equal to check_consonant(c3) == 1 (what you want). For instance, { is not a vowel, but that doesn't make it a consonant. The fix: make your conditions positive.
Why don't try to iterate only over the proper sets:
static const char cons[] = "bcdfghjklmnpqrstvwxyz";
static const size_t cons_sz = sizeof cons - 1;
static const char vowels[] = "aeiou";
static const size_t vowels_sz = sizeof vowels - 1;
for (i = 0; i < cons_sz; i++)
for (j = 0; j < vowels_sz; j++)
for (k = 0; k < cons_sz; k++)
printf("%c%c%c\n", cons[i], vowels[j], cons[k]);

How do I detect an operator vs. int in C using scanf?

How do I read in the following input in my RPN calculator so that it will find the operator no matter what order?
2
2+
4
As of now my scanf only sees the first char in the string and I can only do this:
2
2
+
4
I'm also trying to add an option for integer vs floating point mode. (ex. when 'i' is entered, operate in floating point and vice versa.)
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int *p;
int *tos;
int *bos;
void push(int i);
int pop(void);
int main (void)
{
int a, b;
//float c, d;
char s[80];
//char op; //declare string of 80 chars
p = (int *) malloc(MAX*sizeof(int)); //get stack memory
if (!p){
printf("Allocation Failure\n");
exit(1);
}
tos = p;
bos = p + MAX-1;
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
do {
printf("> ");
// gets(s);
// scanf("%s", s); //read integer
scanf("%s", s);
// switch (*s) {
switch(*s) {
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
push(atoi(s));
}
} while (*s != 'q');
return 0;
}
// Put an element on the stack
void push (int i)
{
if (p > bos){
printf("Stack Full\n");
return;
}
*p = i;
p++;
}
// Get the element from the top of the stack
int pop (void)
{
p--;
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
return *p;
}
Your scanf reads the whole string. It's the following switch that judges by the first character and misses that + in 2+.
To improve it you can use the strtol function. It will parse an integer out of the string and return to you the location where the integer ended - if that's still not the end of the string, there may be an operator there.
A similar function for floating point numbers is strtod.
Here's some sample code of strtol applicable to your example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* input = "25+";
char* endptr;
int val = strtol(input, &endptr, 10);
if (*endptr == '\0')
{
printf("Got only the integer: %d\n", val);
}
else
{
printf("Got an integer %d\n", val);
printf("Leftover: %s\n", endptr);
}
return 0;
}
I'm not sure if I fully understood your question, but you could iterate through the string like this:
for(i = 0; i < strlen(s); i++)
{
// Here comes your switch section like this
switch(s[i]) {
.....
}
}
Remember also to include string.h.
I really didn't understand your code.
If expect the user to enter one character each time, I mean one character + enter, you should use a simple char instead of char[]. And if you pretend to use a string you should receive it and parse it pzico said.
You could do something like that. The problem would be in the treatment of numbers with multiple digits, but thinking a little bit you can fix this problem. I wrote an attempt, but I'm pretty sure it's not going to work.
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
scanf("%c", s);
switch(*s){
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case 'q':
printf("Bye Bye\n");
return;
break;
}
printf("Enter the expression one character each time\n");
do {
scanf("%c", s);
switch(s) {
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
a = pop()*10+atoi(s);
push(a);
}
} while (s != 'q');
Another problem in your code is in your pop function. What do you want to do with this test:
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
You are expecting your pointer to reach the address 0?
Anyway I hope this is not your homework.

Resources