How can i fix this (is_sorted) , recursive function? - c

How can i fix this (is_sorted) , recursive function?
Target: This function takes a string as a input parameter and returns TRUE if characters in the string are in alphabetical ascending order; returns FALSE otherwise. Characters can be lowercase or uppercase.
#include<stdio.h>
#define SIZE 50
typedef enum{FALSE,TRUE} Bool;
Bool is_sorted(const char *str);
int main(){
char arr1[SIZE]="aSTYoLPNDeSaFAE";
char arr2[SIZE]="aGjklOvz";
if(is_sorted(arr1)==TRUE){
printf("arr1 (is_sorted) Yes \n");
}
else
{
printf("arr1 (is_sorted) No \n");
}
if(is_sorted(arr2)==TRUE){
printf("arr2 (is_sorted) Yes \n");
}
else
{
printf("arr2 (is_sorted) No \n");
}
return 0;
}
Bool is_sorted(const char *str){
if(str[0]=='\0'){
return FALSE;
}
else if(strcmp(&str[0],&str[1])<0)
{
return TRUE;
}
else
{
return FALSE;
}
return is_sorted(&str[1]);
}

I see 3 problems within your code, let me first explain the problems in your code before showing a working solution.
First off:
if(str[0]=='\0'){
return FALSE;
}
Why would a empty string not be sorted? Which elements are out of order? After all it's empty.
Next you don't handle upper/lower case correctly:
if(strcmp(&str[0],&str[1])<0)
strcmp compares the ascii values. Upper case letters got lower values than lower case letters. That means strcmp("G", "a")<0 would return true. You really want to compare lowercase letters. You're also comparing strings not letters.
Lastly you never get to your recursive call.
if(str[0]=='\0'){
return FALSE;
}
else if(strcmp(&str[0],&str[1])<0)
{
return TRUE;
}
else
{
return FALSE; // return if you didn't return in any other condition
}
return is_sorted(&str[1]); // You never get here.
Now as for my solution:
Bool is_sorted(const char *str){
if(str[0]=='\0' || str[1] == '\0'){
return TRUE; // A single character as well as a empty string are
} // by definition sorted already.
else if(tolower(str[0]) < tolower(str[1))
{
return is_sorted(str + 1); //First two characters are sorted we got to check
} // if the rest are sorted too.
else
{
return FALSE; // If the first two characters aren't sorted the whole
} // string isn't sorted.
}

The correct is_sorted function in your program should look like this:
#include <ctype.h>
#include <stdio.h>
Bool is_sorted(const char *str){
if(str[0]=='\0'){
return TRUE; //the string is empty
}
else if(str[1]=='\0'){
return TRUE; //the string contains only one character or all letters before NULL are in correct order
}
else if(tolower(str[0])<tolower(str[1])))
{
return is_sorted(&str[1]); //current and next letter are in correct order
}
else
{
return FALSE; //current and next letter are in wrong order, thus whole string is not sorted
}
}

Related

Finding indexes where substring is present

So right now my code checks if the sub string is present in the code and returns true or false, I would like to find where these substrings are located in the total string. how can you implement that.
#include <stdio.h>
#include <stdbool.h>
bool checksub(const char *strng,const char *subs){
if (*strng=='\0' && *subs!='\0'){
return false;
}
if (*subs=='\0'){
return true;}
if (*strng==*subs){
return checksub(strng+1,subs+1);
}
return false;
}
bool lsub(char *strng,char *subs){
if (*strng=='\0'){
return false;
}
if (*strng==*subs){
if (checksub(strng,subs)){
return 1;
}
}
return lsub(strng+1,subs);
}
int main(){
printf("%d\n",checksub("ababuu","ab"));
printf("%d\n",checksub("the bed bug bites","bit"));
return 0;
}
First you should get rid of recursion since it's often slow and dangerous, for nothing gained.
A (naive) version of strstr that returns an index rather than a pointer might look like this:
int strstr_index (const char* original, const char* sub)
{
int index = -1;
for(const char* str=original; *str!='\0' && index==-1; str++)
{
for(size_t i=0; str[i]==sub[i] && str[i]!='\0'; i++)
{
if(sub[i+1] == '\0')
{
index = (int)(str - original);
break;
}
}
}
return index;
}
This returns -1 if not found, otherwise an index.
It iterates across the string one character at a time.
When a character match with the sub string is found, it starts executing the inner loop as well.
If the inner loop continues to find matches all the way to the end of the sub string, then we found a match.
The index can be obtained by pointer arithmetic: the start address of the found sub string minus the start of the string. The result of that subtraction is strictly speaking a special integer type called ptrdiff_t, but I used int to simplify the example.

Checking balanced parentheses in a string with stacks in c

I am trying to write a program where i implement stacks with arrays and use them to check if a given string has balanced parentheses.
For ex. if inputted '(()){}[()]' ,program would output 'Balanced', otherwise if inputted '({})[' the program would output 'Not balanced'.
This part is the array implementation of the stack.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int stack[MAX];
int top=-1;
void push(char val){
if(top==MAX-1){
printf("stack is already full,error\n");
}else{
top++;
stack[top]=val;
}
}
char pop(){
if(top==-1){
printf("not enough elements,error\n");
exit(1);
}else{
top--;
return stack[top];
}
}
This part is the implementation of a common method to solve the problem.
int isMatching(char c1, char c2){
if(c1=='{' && c2=='}')
return 1;
else if(c1 =='(' && c2==')')
return 1;
else if(c1=='[' && c2==']')
return 1;
return 0;
}
int isBalanced(char str[]){
int i=0;
while(str[i]!='\0'){
if(str[i]=='{' || str[i]=='[' || str[i]=='('){
push(str[i]);
}
if(str[i]==')' || str[i] == ']' || str[i]=='}'){
if(stack==NULL){
return 0;
}
if(!isMatching(pop(), str[i])){
return 0;
}
}
i++;
}
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
}
And this is the main function where the user inputs a string and it's tested if it's 'Balanced' or not.
int main(){
char str[MAX];
int flag;
printf("Enter the string with the brackets and etc.\n");
fgets(str, sizeof(str),stdin);
flag=isBalanced(str);
if(flag==1){
printf("Balanced\n");
}
else{
printf("Not balanced\n");
}
return 0;
}
When i input a very simple example, i get a wrong answer, for instance
Enter the string with the brackets and etc.
()
Not balanced
This is supposed to output 'Balanced' instead.I don't understand how this could have occured.
in pop(), you are decrementing before returning the top element. Change:
top--;
return stack[top];
to
return stack[top--];
Also, in isBalanced(), stack is NEVER null, so delete:
if(stack==NULL){
return 0;
}
and change the balanced check to look for the empty stack from:
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
To:
if(top==-1){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
After making these changes, your code appeared to work on my box. This isn't quite how I'd have coded it, but this is the minimal set of changes to make it work.
if (stack==NULL) is the problem here, stack will never be NULL.
You need to check if there are still elements in your stack, by verifying that top > 0
You implemented the push/pop combo wrong. If you push one character top becomes 0. If you popping it immediately it finally executes top--; return stack[top], which evaluates to stack[-1].
Try this push/pop:
int top=-1; //idx to be popped next; <0 -> invalid
void push(char val)
{
if(top==MAX-2)
printf("stack is already full,error\n");
else
stack[++top]=val;
}
char pop()
{
if(top<0) return '\0'; //no abort, just return invalid char
return stack[top--];
}
The answer to your question has already been satisfactorily answered, but as a suggestion for a different approach, consider the following.
Since there are only a very small number of common enclosures used within C source code you can easily track pairs of them using an increment-decrement counter. The following uses a struct, typedefed to balanced_s which is encapsulated into a function to simplify the evaluation. Following is a sample implementation:
typedef struct {
int paren;
int curly;
int square;
bool bBal
}balanced_s;
balanced_s * balanced_enclosures(const char *source);
int main(void)
{
char in[5000] = {0};//you could improve this by reading file size
//first then creating array sized accordingly
FILE *fp = fopen("C:\\play\\source.c", "r");//using copy of this source to test
if(fp)
{
size_t bytes = fread(in, 1, sizeof(in), fp);
}
balanced_s * b = balanced_enclosures(in);
bool balanced = b->bBal;//If not true, inspect the rest of the
//members to see where the imbalance has occurred.
free(b);
return 0;
}
balanced_s * balanced_enclosures(const char *source)
{
balanced_s *pBal = malloc(sizeof(*pBal));
memset(pBal, 0, sizeof(*pBal));
while(*source)
{
switch(*source) {
case '(':
pBal->paren++;
break;
case ')':
pBal->paren--;
break;
case '{':
pBal->curly++;
break;
case '}':
pBal->curly--;
break;
case '[':
pBal->square++;
break;
case ']':
pBal->square--;
break;
}
source++;
pBal->bBal = (!pBal->paren && !pBal->curly && !pBal->square);
}
return pBal;
}

Bool function to check if a word is in an array C++

I'm working on some code check if word is in ignoreWords array. The function keeps returning true for the first value and then false for the rest of the elements even if some of the words are in the ignoreWords array. I'm not sure what I'm doing wrong, I'd appreciate any help or advice.
bool isIgnoreWord(string word, string ignoreWords[])
{
int length;
string copy[length];
for(int i=0; i < length; i++){
copy[length] = ignoreWords[i]; //to find out length of ignoreWords
//cout << copy[length] << endl;
if(copy[length] == word)
return true;
else
return false;
}
//function returns whether word is in the ignoreWords array
}
edit: fixed it. I made it so much more complicated than it really is. This is the code that works:
bool isIgnoreWord(string word, string ignoreWords[])
{
for(int i=0; i < 50; i++){
if(ignoreWords[i] == word){
return true;
}
}
return false;
//function returns whether word is in the ignoreWords array
}
That would be because your if-else statement in the for loop returns in both conditions.
Imagine you're the computer, and you start the for loop:
if (copy[length] == word) {
return true;
}
else {
return false;
}
So you get to the first element in the array, and let's say it doesn't match the word you're checking against. This if-else statement says to return false if it's not, and immediately stops the function because a return statement was found.
What you probably want is for your program to only return false if it exits the for-loop without finding any matches, e.g.
for (...) {
if (matches) return true;
}
return false;
Another thing to note is that you're not initializing length before using it in a statement, and initializing a variable-length array like that isn't supported on all compilers.

checking an arrray and returning a bool

I'm in a CS class and I'm trying to create a tic tac toe program. This is my first time using functions and I need help checking a 2d array to see if it is full with 'x' or 'o' s. I initialized to start off with all the elements to '_' and I want a return value of true or false so I'm using #include <stdbool.h>. Here is the function:
bool check_table_full(char board[SIZE][SIZE]){
if(board[0][0] == '_'){
return false;
}else if(board[1][0] == '_'){
return false;
}else if(board[2][0] == '_'){
return false;
}else if(board[0][1] == '_'){
return false;
}else if(board[1][1] == '_'){
return false;
}else if(board[2][1] == '_'){
return false;
}else if(board[0][2] == '_'){
return false;
}else if(board[1][2] == '_'){
return false;
}else if(board[2][2] == '_'){
return false;
}else{
return true;
}
I know there is a better optimization then using if else statement but this is just is simple in my head. I use printf("%s", check_table_full?"true":"false"); to check if it returns false as it should since all elements in the array are '_'. No matter what I do it prints true, and if I change the "true" in the printf statement it prints whatever is inside the first quote.
Everything else works like SIZE is defined, the array is defined, I just can't get this function to return false.
Sorry if this is lengthy, this is my first time asking a question on here.
If you do printf("%s", check_table_full?"true":"false");, you are not calling the function.
check_table_full is the address of the function. You want check_table_full()
You may want to use nested for-loops. I have learned C++ syntax and not C syntax, so the syntax may be a little off.
Example Code...
#include <stdio.h>
int main() {
char board[2][2];
int outer_count, inner_count;
//It will use nested for loops
for (outer_count = 0; outer_count <= 2; count++) {
for (inner_count = 0; inner_count <= 2; count ++) {
if (board[outer_count][inner_count] == '_'){
return false;
}
}
}
return True
}
Your method of traversing the matrix is not scalable, you can easily introduce errors and is unnecessary complex. My 'check method' is 2 lines of code for any matrix size.
#include <stdio.h>
#include <stdbool.h>
#define MXSIZE 3
bool is_full(char *block) {
for (int l=0;l<MXSIZE*MXSIZE;l++)if(*(block+l)=='_')return false;
return true;
}
int main() {
char my2DArray[MXSIZE][MXSIZE]={{'O','O','O'},{'O','O','O'},{'O','O','_'}};
printf("%s",is_full(&my2DArray[0][0])?"The array is full\n":"The array is not full\n");
return 0;
}

C - scanf doesn't stop looping in string input

i'm making a small test to see if a word is inside another, and i want to return the index where that word begins.
Example: if i check "um" inside "amolum" the return value should be 4(position of the leter "u" where the word begins.
This is what my code looks like:
(...)
int cad_look_str (char s1[], char s2[]) {
int indS1 = 0, indS2 = 0;
while (s1[indS1]!='\0'|| s2[indS2]!='\0') {
if (s1[indS1]==s2[indS2]) {
indS1++;
indS2++;
}
else indS1=0;
}
if (s2[indS2]=='\0' && s1[indS1]!='\0') return -1;
else return indS2-strlen (s1);
}
void main () {
char s[100];
char s1[100];
scanf ("%s",s);
scanf ("%s",s1);
printf ("%d \n", cad_look_str(s1,s) );
}
The problem is that when i compile this, it doesn't stop looping on scanf... It just continues to ask for strings.
If i put cad_look_str(s1,s1) on the last line, it works fine... Why is this happening?
Regards
Your initial loop condition will never terminate if the first characters don't match your comparison test within your if statement.
The 'while' loop checks to ensure the current character positions (both 0 on first pass) are non-terminators. If they're not, and they're not equal, indS1 is reset to its starting position. indS2 never changes, thus the while condition is unchanged.
Might look at some other string functions to accomplish your task unless the scanning is a mandatory component for some reason.
Index of second string should be incremented in the else part also.
if (s1[indS1]==s2[indS2])
{
indS1++; indS2++;
}
else {
indS1=0;
indS2++;
}
changed cad_look_str() for situations like s1 : gdgddadada, s2 : dadada
int cad_look_str (char s1[], char s2[]) {
int indS1 = 0, indS2 = 0;
int flag = 0;
while (s1[indS1]!='\0'&& s2[indS2]!='\0') {
if (s1[indS1]==s2[indS2]) {
indS1++;
indS2++;
flag = 1;
}
else
{
indS1=0;
indS2++;
if(flag) indS2--; // to work with srtrings s1: gdgddadada s2: dadada
flag = 0;
}
}
if (s2[indS2]=='\0' && s1[indS1]!='\0') return -1;
else return indS2-strlen (s1);
}

Resources