Searching a particular word in a matrix of characters - c

I was trying to search for a particular word in a matrix of characters through C but was unable to come to a fixed solution.
For ex:
Suppose I have to search for the word INTELLIGENT in a matrix of characters (3*9)
(Once you have picked a character from the matrix to form a sentence, you cannot pick it again to form the same sentence.There is a path from any cell to all its neighboring cells. A neighbor may share an edge or a corner.)
IIIINN.LI
....TTEGL
.....NELI
Output: YES (the word INTELLIGENT can be found)
Can anybody please give a solution to the above problem !!!!

Use a depth first search.
You can do this using a recursive algorthm. Find all the (unused) places containing the first letter then see if it is possible to find the rest of the word on the remaining board by starting from one of the adjacent squares.

#include <stdio.h>
char Matrix[3][9] = {
{ 'I','I','I','I','N','N','.','L','I'},
{ '.','.','.','.','T','T','E','G','L'},
{ '.','.','.','.',',','N','E','L','I'}
};
char Choice[3][9] = { { 0 }, { 0 }, { 0 } };
const char WORD[] = "INTELLIGENT";
const int Len = sizeof(WORD)-1;
int Path[sizeof(WORD)-1] = { 0 };
char get(int row, int col){
if(1 > col || col > 9) return '\0';
if(1 > row || row > 3) return '\0';
if(Choice[row-1][col-1] || Matrix[row-1][col-1] == '.')
return '\0';
else
return Matrix[row-1][col-1];
}
#define toLoc(r, c) (r)*10+(c)
#define getRow(L) L/10
#define getCol(L) L%10
int search(int loc, int level){
int r,c,x,y;
char ch;
if(level == Len) return 1;//find it
r = getRow(loc);
c = getCol(loc);
ch = get(r,c);
if(ch == 0 || ch != WORD[level]) return 0;
Path[level]=toLoc(r,c);
Choice[r-1][c-1] = 'v';//marking
for(x=-1;x<=1;++x){
for(y=-1;y<=1;++y){
if(search(toLoc(r+y,c+x), level + 1)) return 1;
}
}
Choice[r-1][c-1] = '\0';//reset
return 0;
}
int main(void){
int r,c,i;
for(r=1;r<=3;++r){
for(c=1;c<=9;++c){
if(search(toLoc(r,c), 0)){
printf("YES\nPath:");
for(i=0;i<Len;++i){
printf("(%d,%d)", getRow(Path[i]), getCol(Path[i]));
}
printf("\n");
return 0;
}
}
}
printf("NO\n");
return 0;
}

I think this is what you mean..... Though it seems simpler to what you currently have been offered, so I may have misunderstood the question.
I use Numpy to reshape an arbitrary array into a single
list of letters, then we create a mask of the search term and
a copy of the input list.
I tick off each letter to search for while updating the mask.
import numpy as np
import copy
def findInArray(I,Word):
M=[list(x) for x in I]
M=list(np.ravel(M))
print "Letters to start: %s"%"".join(M)
Mask=[False]*len(Word)
T = copy.copy(M)
for n,v in enumerate(Word):
try:
p=T.index(v)
except ValueError:
pass
else:
T[p]=''
Mask[n]=True
print "Letters left over: %s"%"".join(T)
if all(Mask):print "Found %s"%Word
else:print "%s not Found"%Word
print "\n"
return all(Mask)
I=["IIIINN.LI","....TTEGL",".....NELI"]
findInArray(I,"INTEL")
findInArray(I,"INTELLIGENT")
findInArray(I,"INTELLIGENCE")
Example output
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: IIIN.I....TGL.....NELI
Found INTEL
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: II.I.........NLI
Found INTELLIGENT
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: II.I....T.....NLI
INTELLIGENCE not Found

#include <stdio.h>
#define ROW 1
#define COL 11
char Matrix[ROW][COL] = { { 'I','N','T','E','L','L','I','G','E', 'N', 'T'} };
char Choice[ROW][COL] = { { 0 } };
const char WORD[] = "INTELLIGENT";
const int Len = sizeof(WORD)-1;
int Path[sizeof(WORD)-1] = { 0 };
char get(int row, int col){
if(1 > col || col > COL) return '\0';
if(1 > row || row > ROW) return '\0';
if(Choice[row-1][col-1] || Matrix[row-1][col-1] == '.')
return '\0';
else
return Matrix[row-1][col-1];
}
#define toLoc(r, c) (r)*16+(c)
#define getRow(L) L/16
#define getCol(L) L%16
int search(int loc, int level){
int r,c,x,y;
char ch;
if(level == Len) return 1;//find it
r = getRow(loc);
c = getCol(loc);
ch = get(r,c);
if(ch == 0 || ch != WORD[level]) return 0;
Path[level]=toLoc(r,c);
Choice[r-1][c-1] = 'v';//marking
for(x=-1;x<=1;++x){
for(y=-1;y<=1;++y){
if(search(toLoc(r+y,c+x), level + 1)) return 1;
}
}
Choice[r-1][c-1] = '\0';//reset
return 0;
}
int main(void){
int r,c,i;
for(r=1;r<=ROW;++r){
for(c=1;c<=COL;++c){
if(search(toLoc(r,c), 0)){
printf("YES\nPath:");
for(i=0;i<Len;++i){
printf("(%d,%d)", getRow(Path[i]), getCol(Path[i]));
}
printf("\n");
return 0;
}
}
}
printf("NO\n");
return 0;
}

Related

input files in C

Code implements the dynamic programming solution for global pairwise alignment of two sequences. Trying to perform a semi-global alignment between the SARS-CoV-2 reference genome and the first read in the Nanopore sample. The length of the reference genome is 29903 base pairs and the length of the first Nanopore read is 1246 base pairs. When I run the following code, I get this message in my terminal:
Usage: align < input file >
How do I add the necessary files to the code. The file names are SARS-CoV-2 reference genome.txt and Nanopore.txt, where A = SARS-CoV-2 reference genome.txt file and B = Nanopore.txt file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GAP -2
#define MATCH 5
#define MISMATCH -3
#define MAXLENGTH_A 29904
#define MAXLENGTH_B 1247
int max(int A, int B, int C)
{
if (A>=B && A>=C) return A;
else if (B>=A && B>=C) return B;
else return C;
}
char Tmax(int A, int B, int C)
{
if (A>B && A>C) return 'D';
else if (B>A && B>C) return 'L';
else return 'U';
}
int m(char p, char q)
{
if (p==q) return MATCH;
else return MISMATCH;
}
void append(char *st,int L,char c)
{
int i;
for (i=L;i>0;i--)
st[i]=st[i-1];
st[L+1] = '\0';
st[0] = c;
}
int main(int argc, char **argv)
{
FILE *fp;
char A[1000];
char B[1000];
char RA[1000];
char RM[1000];
char RB[1000];
int N,M,L;
int i,j;
//int S[MAXLENGTH_A][MAXLENGTH_B];
//char T[MAXLENGTH_A][MAXLENGTH_B];
int **S;
char **T;
S = (int**)malloc(sizeof(int*)*MAXLENGTH_A);
for (int i = 0; i<29904; i++)
S[i] = (int*)malloc(sizeof(int)*MAXLENGTH_B);
T = (char**)malloc(sizeof(char*)*MAXLENGTH_A);
for (int i = 0; i<29904; i++)
T[i] = (char*)malloc(sizeof(char)*MAXLENGTH_B);
if (argc!=2)
{
printf("Usage: align <input file>\n");
exit(1);
}
fp = fopen(argv[2],"r");
if (fp==NULL)
{
printf("input file not found.\n");
exit(1);
}
fscanf(fp,"%s",A);
fscanf(fp,"%s",B);
printf("Sequence A: %s\n",A);
printf("Sequence B: %s\n",B);
N = strlen(A);
M = strlen(B);
S[0][0] = 0;
T[0][0] = 'D';
// initialize first column
for (i=0;i<=N;i++)
{
S[i][0] = GAP*i;
T[i][0] = 'U';
}
//initialize the firt row
for (i=0;i<=M;i++)
{
S[0][i] = GAP*i;
T[0][i] = 'L';
}
for (i=1;i<=N;i++)
for (j=1;j<=M;j++)
{
S[i][j] = max(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP);
T[i][j] = Tmax(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP);
}
printf("The score of the alignment is : %d\n",S[N][M]);
i=N;
j=M;
L=0;
RA[0]='\0';
RB[0]='\0';
RM[0]='\0';
while (i!=0 || j!=0)
{
if (T[i][j]=='D')
{
append(RA,L,A[i-1]);
append(RB,L,B[j-1]);
if (A[i-1]==B[j-1]) append(RM,L,'|');
else append(RM,L,'*');
i--; j--;
}
else if (T[i][j]=='L')
{
append(RA,L,'-');
append(RB,L,B[j-1]);
append(RM,L,' ');
j--;
}
else if (T[i][j]=='U')
{
append(RA,L,A[i-1]);
append(RB,L,'-');
append(RM,L,' ');
i--;
}
L++;
}
printf("%s\n",RA);
printf("%s\n",RM);
printf("%s\n",RB);
}
These lines of the program
printf("Usage: align <input file>\n");
/* AND */
fp = fopen(argv[2],"r");
/* AND */
fscanf(fp,"%s",A);
fscanf(fp,"%s",B);
show the program expects to read from one file.
From your question, it seems you could make a third data file with one line containing the 29903 characters without spaces or breaks of the first sequence followed by a second line containing 1246 characters (again continuous characters) of the second sequence. But, don't do this...
When the program is run (eg: ./a.out filename) and one supplies the name of the 'combined' file, the first fscanf() will attempt to load the first block of characters into the array named 'A'. The second fscanf() would load the second block into the array named 'B'.
This is a problem because both 'A' and 'B' are dimensioned to hold only 1000 bytes each, maximum...
As this code is right now, you cannot use it to load the long sequences you want to. Sorry.

Format any number in Indian currency style using C language

Indian Currency format is 12345 → "12,345" (for odd length) and 123456 → "1,23,456" (for even length). I have included all possibilities such as
1. Minus sign: "-12,345".
2. Decimal Point: "-12,345.345" or "12,345.123".
3. Zero Condition 000000.123 → "0.123".
4.Minus and Zero Condition '-000000.123' -> "-0.123"
int currencyFormatter(char av_currency[], int av_strLen, char *ap_formattedNumber)
{
char flag = 'N'; //Taking a Flag to know whether thier is a decimal Point in Currency or not
int lengthOf = 0, index = 0, i = 0, j = 0;
char *decAr = NULL;
char *tmpCurrency = NULL;//Taking two Pointers one for Array with Commas(tmpCurrency) and decAr pointer for decimal Point array
char *s = NULL;
s = strstr(av_currency, ".");//Checking for decimal Point in array
if (s > 0)
{
flag = 'D'; // Changing Flag to show Decimal Point is Present in Array
s = strchr(av_currency, '.');
index = s - av_currency; //Index at which Decimal Point is present
av_strLen = strlen(av_currency) - index; // calculated formula to know length of an array needed to contain decimal point and Numbers after that
decAr = (char*)malloc(av_strLen*sizeof(char*));//allocated Memory using malloc
decAr[av_strLen] = '\0';
memmove(decAr, &av_currency[index], av_strLen); //memmove from decimal till end of array.
av_currency[index] = '\0';
if (!decAr)//Handled Null Condition for Pointer
{
return -1;//All errors for Negative Number
}
}
lengthOf = strlen(av_currency) + (strlen(av_currency) / 2); // Derived Formula(It Works for Indian Currency Format) to know the length of an array is needed to contain numbers and Commas Together.
tmpCurrency = (char*)malloc(lengthOf*sizeof(char*));
strrev(av_currency); //Reversed Array as commas comes at multiple of 3. eg=12345 reverse=54321 wdComma=543,21 index is 3 if number would had been bigger commas would had come at 3,6.
while (av_currency[i] != '\0')
{
if (j % 3 == 0 && j >= 3 && av_currency[i] != '-')//all Commas come at multiple of 3 when you reverse an amount
{
tmpCurrency[j] = ',';//If an , is found Increment only J as
is used as index number to store in tmpcurrency
j++;
continue;
}
tmpCurrency[j] = av_currency[i];//storing the Value in tmpCurrency
i++;//Incrementing
j++;//Incrementing
}
tmpCurrency[j] = '\0';//Null Condition
if (!tmpCurrency) // Checking for NULL Pointer
{
return -2; //all errors for Negative value
}
flag == 'D' ? strcpy(av_currency, (strcat(strrev(tmpCurrency), decAr))) : strcpy(av_currency, (strrev(tmpCurrency)));//Ternary Operator
strcpy(ap_formattedNumber,av_currency);//Copying formated number into original array
free(tmpCurrency);//Releasing the memory
free(decAr);//Releasing the Memory
return 0;
}
I have solution for above question.
Please try this code.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
char *printComma(double input_number,char *demo,char ap_it[],char ap_type[])
{
char *result = NULL;
char *lp_decimal_number = NULL;
char *main_number = NULL;
char *decimal_pos = NULL;
char zero[1] = {0};
int i = 0;
int j = 0;
int z = 0;
int cnt = 0;
int decimal_index = 0;
int lp_decimal_numberLen = 0 ;
int flag_dec = 0;
int flag_minus = 0 ;
int length_main;
int k = 0;
int length_demo=0;
sprintf(demo,"%lf",input_number);
if(strcmp(ap_type,"P") == 0)
{
if(strcmp(ap_it,"A") == 0 || strcmp(ap_it,"B") == 0)
{
sprintf_s(demo,40,"%0.4lf",input_number);
}
else
{
sprintf_s(demo,40,"%0.2lf",input_number);
}
}
else
{
sprintf_s(demo,40,"%.0lf",input_number);
}
length_demo = strlen(demo); // finds the length of original string
result = (char *)malloc((length_demo+10)*sizeof(char));
main_number = (char *)malloc((length_demo+50)*sizeof(char));
z = strspn(demo[0] == '-' ? (demo + 1) : demo , "0");
if(z != 0)
{
if(demo[0] != '-')
{
memcpy(main_number,&demo[z],length_demo);
main_number[length_demo]='\0';
}
else
{
puts(main_number);
main_number[length_demo]='\0';
flag_minus=1;
}
}
else
{
memcpy(main_number,&demo[0],length_demo);
main_number[length_demo]='\0';
}
length_main=strlen(main_number);
decimal_pos = strstr(main_number,".");
if(decimal_pos > 0)
{
decimal_index = decimal_pos - main_number ; // Getting postion of decimal
lp_decimal_numberLen = length_main - decimal_index; // Calculating the endpoint for decimal number
if(length_main > 3) //Copying the decimal part to a separate array
{
lp_decimal_number = (char *) malloc(lp_decimal_numberLen+1);
memcpy( lp_decimal_number, &main_number[decimal_index], lp_decimal_numberLen );
lp_decimal_number[lp_decimal_numberLen] = '\0';
flag_dec=1;
main_number[decimal_index]='\0';
}
}
//logic for comma starts here
strrev(main_number);
i = 0;
while(main_number[i] != '\0')
{
if (j%3 == 0 && j>=3 && main_number[i]!='-' && main_number[i]!='$')
{
result[j] = ',';
cnt++;
j++;
continue;
}
else if(cnt==1 || cnt==2)
{
result[j] = main_number[i];
}
else
{
result[j] = main_number[i];
}
i++;
j++;
}
result[j] = '\0';
if(flag_dec==0)
{
if(flag_minus==0)
return(strrev(result));
else
{
strcat(result,"-");
return(strrev(result));
}
}
else
{
if(flag_minus==0)
return(strcat(strrev(result),lp_decimal_number));
else
{
strcat(result,"-");
return(strcat(strrev(result),lp_decimal_number));
}
}
}
int main()
{
double number;
char num[25] = {0};
char it_type[] = "A";
char ap_type[] = "P";
char *formattedNumber = NULL;
printf("\n Enter the number n: ");
scanf("%lf",&number);
formattedNumber=printComma(number,num,it_type,ap_type);
printf("\n Final Result = %s ",formattedNumber);
getch();
return 0;
}
Do only positive values with your function!
Check if the value is negative before calling the function; call the function with the positive value; if it was negative to start with, add the minus sign afterwards.
int needssign = 0;
if (val < 0) needssign = 1;
indianformat(res, abs(val));
if (needssign) sprintf(res, "-%s", res);
Or make your current function a helper function and use the code above for the new improved function for formatting in Indian format.

Find all vowels which never used in all words in the text

I wrote code that find all vowels which used in all words in the text. And I do not know how to transfer it. Do I need to rewrite all code?
So, I need to have such results:
Text:
wwe w fa
Result:
o u i
#include <stdio.h>
#include <ctype.h>
#define vowel (1u<<('a'-'a') | 1u<<('e'-'a') | 1u<<('i'-'a') | 1u<<('o'-'a') | 1u<<('u'-'a'))
unsigned int char_to_set(char c)
{
c = tolower(c);
if (c < 'a' || c > 'z')
return 0; else return 1u<<(c-'a');
}
int letter(int c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
int sign(int c)
{
return c == ' ' || c == ',' || c == '\n' || c == '\t';
}
int main ()
{
int c, flag=0;
char alpha;
unsigned int sl = 0, mn = vowel;
FILE *pf;
pf=fopen("l13.txt","r");
printf ("Ishodnyi text:\n\n");
while (!feof(pf))
{
c=getc(pf);
printf("%c",c);
switch (flag)
{
case (0):
{
if (letter(c))
{
sl = sl | char_to_set(c);
flag = 1;
}
if (sign(c)) flag = 0;
break;
}
case (1):
{
if (letter(c))
{
sl = sl | char_to_set(c);
flag = 1;
}
if (sign(c))
{
mn = mn & sl;
sl = 0;
flag = 0;
}
break;
}
}
}
if (mn == 0) { printf ("\n\n no vowels are included in all word"); } else { printf ("\n\n vowels are included in all word:\n"); for(alpha='a'; alpha <= 'z'; alpha++){ if((mn & char_to_set(alpha)) != 0){ printf("%c ", alpha);
}
}
}
fclose(pf);
getchar();
return 0;
}
There are many ways to do what you want. Below is one way. There may be better ways but hopefully it will give you some ideas to improve it.
If I understand your code correctly, mn contains the bit mask of vowels present in the text. So you can write a function to check all the vowel bits that are not set. The following code checks for a and e only but I think it should be clear how to extend it for the other other vowels.
#define A_MASK (1u<<('a'-'a'))
#define E_MASK (1u<<('e'-'a'))
/*
* Convenience struct for associating masks with characters.
* Could be done without this by deriving the character from the mask
* but this (IMHO) makes the code simpler to understand.
*/
struct {
unsigned int mask
char c;
} masks[] = { { A_MASK, 'a'} , { E_MASK, 'e'} };
void vowels_not_present (unsigned int vowels_mask)
{
int ix;
for (ix = 0; ix < sizeof(masks) / sizeof(masks[0]); ix++) {
if (!(vowels_mask & masks[ix].mask)) {
printf("vowel %c is not present\n", masks[ix].c);
}
}
}
Then in your main invoke the above function:
vowels_not_present(mn);

Calculator in C using stack

I'm trying to create a calculator in c, which can calculate with priority and get right results for examples like these:
((5+5)/3)*3) -- > 9
((1+2) * 3) -- > 9
These examples my code below can calculate. But for something like this
(2+5) * (2+5), my program gives wrong answer.
I'm using 2 stacks. One for operators and one for numbers. It works on this principle:
follows:
((4 - 2) * 5) + 3 --> normal infix expression:
+ * - 4 2 5 3
Pseudo code:
Read + (an operation), push it onto the stack,
Read * (an operation), push it onto the stack,
Read - (an operation), push it onto the stack,
Read 4 (a number), the top of the stack is not a number, so push it onto the stack.
Read 2 (a number), the top of the stack is a number, so pop from the stack twice, you get 4 - 2, calculate it (2), and push the result (2) onto the stack.
Read 5 (a number), the top of the stack is a number, so pop from the stack twice, you get 2 * 5, push the result (10) onto the stack.
Read 3 (a number), the top of the stack is a number, so pop from the stack twice, you get 3 + 10, push the result (13) onto the stack.
Nothing left to read, pop from the stack and return the result (13).
Actual code:
#include <stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 102
typedef struct
{
char stk[MAXSIZE];
int top;
}STACK;
typedef struct stack
{
int stk[MAXSIZE];
int itop;
}INT_STACK;
STACK s;
INT_STACK a;
void push(char);
char pop(void);
void display(void);
int main()
{
a.itop = 0;
char string[MAXSIZE],vyb,vyb2;
int cislo1,cislo2,vysledok;
while (gets(string) != NULL){
for(int j = strlen(string); j > 0; j--){
if(string[j] == '*' || string[j] == '/' || string[j] == '+' || string[j] == '-')
push(string[j]);
}
//display();
for(int j = 0; j < strlen(string); j++){
if(isdigit(string[j])&&!(a.itop)){
//display();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
int_push(atoi(pomoc));
}
else if(isdigit(string[j])&&(a.itop)){
cislo1 = int_pop();
vyb2 = pop();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
cislo2 = atoi(pomoc);
if(vyb2 == '+')
vysledok = cislo1+cislo2;
else if(vyb2 == '-')
vysledok = cislo1-cislo2;
else if(vyb2 == '*')
vysledok = cislo1*cislo2;
else if(vyb2 == '/')
vysledok = cislo1 / cislo2;
//printf(" v %d",vysledok);
int_push(vysledok);
}
}
printf("%d\n",int_pop());
}
}
/* Function to add an element to the stack */
void push (char c)
{
s.top++;
s.stk[s.top] = c;
//printf ("pushed element is = %c \n", s.stk[s.top]);
}
/* Function to delete an element from the stack */
char pop ()
{
char num = s.stk[s.top];
// printf ("poped element is = %c\n", s.stk[s.top]);
s.top--;
return(num);
}
int empty()
{
if (s.top == - 1)
{
printf ("Stack is Empty\n");
return (s.top);
}
return 1;
}
void display ()
{
int i;
if (!empty)
{
printf ("Stack is empty\n");
return;
}
else
{
printf ("\n The status of the stack is \n");
for (i = s.top; i >= 0; i--)
{
printf ("%c\n", s.stk[i]);
}
}
printf ("\n");
}
void int_push (int c)
{
a.itop++;
a.stk[a.itop] = c;
//printf ("pushed element is = %d \n", a.stk[a.itop]);
}
/* Function to delete an element from the stack */
int int_pop ()
{
int num = a.stk[a.itop];
// printf ("poped element is = %d\n", a.stk[a.itop]);
a.itop--;
return(num);
}
Is there any other way to create a calculator with priority, which can give good answers?
Thanks for your respond
Put breakpoints - you'll get the following expression:
+ + * 2 5 2 5. The problem with that, is your interpreter is interpeting this as (2+5+2)*5 instead of (2+5) * (2+5).
Well then, you might be wondering how to solve this. There's no simple single solution - you could either fix your own interpreter or build a whole new mechanic, because the way you build expressions just can't handle more then one pair of parthesises.
For example, you may want to calculate all the values in parnthesises before even building the expression seperatley, possibly using recursion in the case of parenthesiseception - however if you actually choose to use that method, you might want to change the way you work with the expressions entirely, because that's a different approach.
If you need me to show actual code examples to explain this further using parts of the code you made, just ask for it and i'll edit and provide what you need.
Either way, I really advise you to look up working with interpreters in general - you could really learn a lot about analysing strings and working with different inputs, and people even did similar stuff to yours with calculators before
EDIT: you asked for examples, so here you go - this is an example of a completely different method using recursion. This way, you handle a single pair of parenthesises at a time, and thus you won't have the problem you currently do. Note - the source i'm basing this on ( pretty much copy-pasted with edits from the thread and some personal comments ) is from codereview on stack exchange, you can see it here
if you're intrested.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getInput(char * in) {
printf("> ");
fgets(in, 256, stdin);
}
int isLeftParantheses(char p) {
if (p == '(') return 1;
else return 0;
}
int isRightParantheses(char p) {
if (p == ')') return 1;
else return 0;
}
int isOperator(char p) {
if (p == '+' || p == '-' || p == '*' || p == '/') return p;
else return 0;
}
int performOperator(int a, int b, char p) {
switch(p) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/':
if (b == 0) { printf("Can't divide by 0, aborting...\n"); exit(1); } // now we dont want the world to expload here do we.
return a/b;
default:
puts("Bad value in switch.\n"); // A replacement which was mentioned in the thread- better have a default response just in case something goes wrong.
break;
}
return 0;
}
char isDigit(char p) {
if (p >= '0' && p <= '9') return 1;
else return 0;
}
int charToDigit(char p) {
if (p >= '0' && p <= '9') return p - '0';
else return 0;
}
int isNumber(char * p) {
while(*p) {
if (!isDigit(*p)) return 0;
p++;
}
return 1;
}
int len(char * p)
{
return (int) strlen(p); // This was bugged in the source, so I fixed it like the thread advised.
}
int numOfOperands(char * p) {
int total = 0;
while(*p) {
if (isOperator(*p)) total++;
p++;
}
return total+1;
}
int isMDGRoup(char *p)
{
for(; *p; p++) // used to be a while loop in the source, but this is better imho. more readable, also mentioned on the thread itself.
{
if (!isDigit(*p) && *p != '/' && *p != '*') return 0;
}
return 1;
}
int getLeftOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
int i = 0;
// Operand is part of multi-*/ group
if (isMDGRoup(p)) {
while(1) {
if (*p == '*' || *p == '/') break;
l[i++] = *p++;
}
return i;
}
// Operand is in parantheses (so that's how you write it! sorry for my bad english :)
if(isLeftParantheses(*p)) {
int LeftParantheses = 1;
int RightParantheses= 0;
p++;
while(1) {
if (isLeftParantheses(*p)) LeftParantheses++;
if (isRightParantheses(*p)) RightParantheses++;
if (isRightParantheses(*p) && LeftParantheses == RightParantheses)
break;
l[i++] = *p++;
}
// while (!isRightParantheses(*p)) {
// l[i++] = *p++;
// }
l[i] = '\0';
return i+2;
}
// Operand is a number
while (1) {
if (!isDigit(*p)) break;
l[i++] = *p++;
}
l[i] = '\0';
return i;
}
int getOperator(char * p, int index, char * op) {
*op = p[index];
return index + 1;
}
int getRightOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
while(*p && (isDigit(*p) || isOperator(*p) ||
isLeftParantheses(*p) || isRightParantheses(*p))) {
*l++ = *p++;
}
*l = '\0';
return 0;
}
int isEmpty(char * p) {
// Check if string/char is empty
if (len(p) == 0) return 1;
else return 0;
}
int calcExpression(char * p) {
// if p = #: return atoi(p)
//
// else:
// L = P.LeftSide
// O = P.Op
// R = P.RightSide
// return PerformOp(calcExpression(L), calcExpression(R), O)
// ACTUAL FUNCTION
// if p is a number, return it
if (isNumber(p)) return atoi(p);
// Get Left, Right and Op from p.
char leftOperand[256] = ""; char rightOperand[256]= "";
char op;
int leftOpIndex = getLeftOperand(p, leftOperand);
int operatorIndex = getOperator(p, leftOpIndex, &op);
int rightOpIndex = getRightOperand(p+operatorIndex, rightOperand);
printf("%s, %c, %s", leftOperand, op, rightOperand);
getchar();
if (isEmpty(rightOperand)) return calcExpression(leftOperand);
return performOperator(
calcExpression(leftOperand),
calcExpression(rightOperand),
op
);
}
int main()
{
char in[256];
while(1) {
// Read input from user
getInput(in);
if (strncmp(in, "quit", 4) == 0) break;
// Perform calculations
int result = calcExpression(in);
printf("%d\n", result);
}
}

how to modify detab to accept list of arguments

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define TAB_STOP 8
/* replaces tabs from input with the proper amount of blank spots */
int Detab()
{
int c, x;
int column;
x = column = 0;
while((c=getchar())!=EOF)
{
if(c == '\n') /* reseting counter if newline */
{
putchar(c);
return 1;
}
else if(c!='\t') /* column counts places to tab spot */
{
putchar(c);
column++;
if(column == TAB_STOP)
column = 0;
}
else /* tab */
{
for(x=0; x<TAB_STOP - column; x++)
putchar('_');
column = 0;
}
}
return 0;
}
#define MAX_ARGUMENTS 100
int main(int argc, char *argv[])
{
int i, val = 0;
int nums[MAX_ARGUMENTS];
int x = 0;
for(i = 1; i < argc; i++) {
while(isdigit(*argv[i])) {
val = val * 10 + *argv[i] - '0';
*++argv[i];
}
if(x > MAX_ARGUMENTS - 1)
return 0;
nums[x++] = val;
nums[x] = '\0';
val = 0;
}
while(Detab(nums));
printf("Press any key to continue.\n");
getchar();
return 0;
}
In main i put all the arguments(numbers) inside nums array and then pass it to detab. So now im interested what would be the smart way to edit detab so it works. I'm still trying to figure out for a working pseudocode but i dont really know.
The way i tought it should work is:
if arguments are 5, 8, 10 then a tab inside first 4 characters leads to position 5, in 5 - 7th char leads to pos 8 etc.
In case of a newline, the arguments start all over again from the begining.
The most common way is to have Detab accept a pointer (which points to an element in an array) and the length of that array:
int Detab(int* data, int len); // access data[0] through data[len - 1]
Call it like so:
void example() {
int array[] = {5, 8, 10};
Detab(array, 3);
// or:
Detab(array, sizeof array / sizeof *array); // second parameter evaluates to 3
// without using a magic constant
}
Here's some pseudocode for expanding tabs:
def expandtabs_in_line(line, tabstops, default, space):
result = ""
for c in line:
if c != "\t":
result += c
else:
for stop in tabstops:
if stop > len(result):
result += space * (stop - len(result))
break
else:
result += space * (default - (len(result) % default))
return result
def expandtabs(lines, tabstops=[], default=8):
for line in lines:
yield expandtabs_in_line(line, tabstops, default, " ")
Try it out at codepad.

Resources