Struggling to figure out how to write a certain function - c

I've been trying for quite a while now to write a function in my C program which will perform a task if a given array does not contain a certain letter, otherwise if the array does contain this letter, another function is called and the program continues on elsewhere.
Here is an example of one such function I attempted:
int Asterisk(){
int v;
for(v=0; v<sizeof Mask; v++){
if(Mask[v] != '*'){
return 1;
}
else{
return 0;
}
}
}
As you can see, this function returns 1 when
Mask[0] != '*'
I can't figure out how to check every element of the array before returning a value, rather than just checking the first element.
Any help/guidance would be much appreciated!

Try the following
int Asterisk()
{
int i = 0;
while ( i < sizeof Mask && Mask[i] != '*' ) ++i;
return i == sizeof Mask;
}
Though as for me I would write the function such a way that if an asterisk is present in the array then the function returns 1.
int Asterisk()
{
int i = 0;
while ( i < sizeof Mask && Mask[i] != '*' ) ++i;
return i != sizeof Mask;
}
and in the caller use it like
if ( !Asterisk() ) { /* do something */ }
That is if an asterisk is present in the array then the function returns 1 otherwise returns 0.
If the character array contains strings then you could simply use standard C function strchr declared in header <string.h>

By array, you mean a simple string ? If it that case, you just need to write a function taking a string and the letter to find and return 0 if the string doesn't contain this letter else 1 at the first occurrence of the letter.

int Asterisk()
{
int v;
bool exists = false;
for(v=0; v<sizeof Mask; v++){
if(Mask[v] != '*'){
exists = true;
break;
}
}
return exists;
}

Related

Knuth Morris Pratt Algorithm, keep getting error "control reaches end of non-void function"

Code keeps returning the error "control reaches end of non-void function".
The source of the error is probably: int lps[M] but I can't figure out how to fix it. I tried to assign value to it but the error is still there.
EDIT: sorry about the return -1; thing. Fixed that but the error I'm trying to fix is still there.
int knuth(char *string, char * pattern){
int M = strlen(string);
int N = strlen(pattern);
int lps[M];
if (string == NULL)
{
return -1;
}
else {
int i = 0;
int j = 0;
while (i < N) {
if (string[j] == pattern[i]) {
j++;
i++;
}
if (j == M) {
//printf("Found stringtern at index %d ", i - j);
j = lps[j - 1];
return i - j;
} else if (i < N && string[j] != pattern[i]) {
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
return i - j;
}
}
}
Ignoring all other potential problems in this function, the compiler is rightfully complaining that not all code paths return a value. You have declared the knuth function to return an int, yet it's possible for logic in your function to reach the end without returning a value. If you go down one of those paths, the function will return an indeterminate value, and if the caller uses that value, it will invoke undefined behavior. See the condensed version of your function below:
int knuth(char *string, char * pattern){
if (string == NULL)
{
return -1; // ok, here's a return, but it's conditional on string == NULL
}
else {
while (...) {
if (...) {
return i - j; // here's another return, also conditional
} else if (...) {
}
return i - j; // here's the final return in your function, which is
// conditional on entering the while loop
}
// what if you get here (ie, the condition of the while loop was false)?
// The function returns nothing, this is what the compiler is warning
// you about.
}
// Here is logically the same as at the end of the else block .. also no return
}
As I mentioned in my comment, there's no point to the while loop, since you unconditionally return from it at the end of the first iteration. That means the loop is guaranteed to only execute once, eliminating the need for a loop all together. Your logic can be simplified, at least with a method as below:
int knuth(char *string, char * pattern){
int i=0, j=0;
if (string == NULL)
{
return -1; // ok, here's a return, but it's conditional on string == NULL
}
else if (i < N) {
// if i < N, do whatever manipulations you want as before
if (...) {
// return i - j; // really no need to return i-j here, we'll do that
// at the end now
} else if (...) {
}
}
// now at the very end of the function, this will unconditionally return
return i - j;
}
However, I suspect you actually want to loop, in which case your logic should be something like
int knuth(char *string, char * pattern){
int i=0, j=0;
if (string == NULL)
{
return -1;
}
else
{
while (i < N)
{
// ... do your operations. Be _very_ careful to increment
// i appropriately (probably each time thru the loop), otherwise
// you'll get an infinite loop here. I see a conditional
// mutation of i in your OP, which makes me nervous.
}
// since this is the end of an else block, we can return here
//return i - j;
}
// but IMO it's clearer to return here. It's up to you, depending on
// where you want to scope i and j
return i - j;
}
Your code falls off the end of the function when string == NULL.
This writing style is old; typically we would not write
if(string != NULL)
{
/* Entire body logic */
}
but rather we would now write
if(string == NULL)
{
/* handle input error and return; or do we do string = ""; */
}
You will find this mistake more easily avoided by using the modern style. It has been pointed out to me that string can't be NULL here because of the strlen(string) call above. While such a platform does exist where strlen() checks for NULL, depending on that behavior is unwise, and the check should be moved before the strlen(string) call.
Nobody believes in single return anymore, which was the only real reason for the old style.

Recursive function to calculate successor of a numeric string

I want to write a recursive function which calculates Succ(‘2468’) = '2469'. ‘2468’ is a numeric string.
The exercice give me some predefined function such as last(ch), which returns the last caracter of a string, start(ch), returns ch without the last caracter, addEnd(ch, c), adds c at the end of ch and ask me to return a string as final result (i.e., suc("123")="124")
I tried this code but it works only for a string with 2 characters. If the length of my string is > 2, it doesn't work:
int successor (char*ch)
{
if (strlen (ch)==1)
return (int(*ch))+1);
else
return ((int(*ch))*10+successor(ch+1));}
There seems to be no need for multiplication or use of powers. Given the extra predefined functions you indicated were provided, I think the intention here was for a recursive way to express long addition with carry. I don't know C but here's an illustration in JavaScript that has very close syntax. I hope this helps.
function successor(s){
if (s.length == 1){
if (s == '9'){
return '10';
} else {
// Return the successor character,
// not sure how this looks in C.
return String.fromCharCode(
s.charCodeAt(0) + 1);
}
}
let rightmost = successor(last(s));
// No carry so just return
// the string with the last
// character incremented
if (rightmost != '10'){
return addEnd(start(s), rightmost);
// We have a carry so
// continue the recursion
} else {
return addEnd(successor(start(s)), '0');
}
}
function last(s){
return s.substr(-1);
}
function start(s){
return s.substr(0, s.length - 1);
}
function addEnd(s, c){
return s + c;
}
console.log(successor('2999'));
A key problem is this logic:
(int(*ch))*10+successor(ch+1)
the multiplication by 10 is insufficient for larger numbers. We need to multiply by a power of 10 and we already calculated that power but didn't hang onto it:
strlen (ch)
or more specifically:
strlen(ch) - 1
A complete solution:
#include <math.h>
#include <stdio.h>
#include <string.h>
#define digit(c) (c - '0')
int successor(char *string)
{
size_t power = strlen(string) - 1;
if (power == 0)
{
return digit(*string) + 1;
}
return digit(*string) * pow(10, power) + successor(string + 1);
}
int main() {
printf("%d\n", successor("2999"));
return 0;
}
OUTPUT
> ./a.out
3000
>
TODO
What happens if successor() is passed an empty string:
printf("%d\n", successor(""));
How can you modify the code to fix this? First decide what the function should return in this situation. What happens if successor() is passed a string that represents a number too large to be contained in an int:
printf("%d\n", successor("8589934592"));
How can you modify the code to fix this? Again, first decide what the function should return in this situation.

Function that returns 1 if two arrays are completely different and 0 if there's a common element

I've tried this code but it doesn't seem to be working, how to break out of the nested loop ?
#include <stdio.h>
#include <string.h>
int meme(char s1[], char s2[])
{
int i = 0, j = 0;
int different;
while (i <= strlen(s1) && different == 1) {
while (j <= strlen(s2)) {
if (s1[i] != s2[j]) {
different = 1;
} else {
different = 0;
}
j = j + 1;
}
i = i + 1;
}
return different;
}
You have to initialize different as it is undefined if not - this probably breaks your first while loop as different probably is a random number > 1.
strlen gives you the number of characters in the string excluding the null-character which terminates the string (see here). However, you do not only compare the characters of the two strings, but also the null-character, probably to implicitely check if the length of the strings is the same. While this should work, it is better to do this check explicitely by comparing the length of the strings first as it is less error-prone.
It isn't necessary to do a nested loop here if you compare the length of the strings first. Also, you now know the length of both strings, so this function can be change to use a for loop, which makes it even simpler.
A possible solution based on the points above:
#include <stdio.h>
#include <string.h>
int meme(char s1[], char s2[]){
int i = 0;
int len_s1 = 0;
int len_s2 = 0;
int different = 0;
len_s1 = strlen(s1);
len_s2 = strlen(s2);
if (len_s1 == len_s2) {
for (i = 0 ; i < len_s1 ; i++) {
if (s1[i] != s2[i]) {
different = 1;
break;
}
}
else {
different = 1;
}
return different;
}
One more thing - do yourself and everyone else a favor and intend your code as it is extremely hard to read otherwise!
Your code is not optimized and you are not using a good approach for doing the task. I have modified the code and it will do the job with minimized complexity.
Here I assume that both the arrays are of same size as your problem shows
bool meme(char s1[], char s2[])
{
int i=0;
while(s1[i] != NULL && s2[i] != NULL)
{
if(s1[i] == s2[i])
return false;
i += 1;
}
return true;
}
When you call this function then declare a variable of type bool and store the returned value of this function in that variable.
For example :
bool check;
bool = meme(array 1 , array 2);
and then check if returned value is true, then both the arrays are totally different else not. You can do that by the below code :
if(check)
printf("Arrays are different");
else
printf("Arrays are not different");
You can also use int in place of bool if it suits you better but remember, whatever code you write, must be least complex. And think that if you are using int then also you are returning only 0 or 1; but int takes 2 bytes in 32-bit compiler and 4 bytes in 64-bit compiler, but bool takes only 1 byte and even 1 bit in some languages like pascal (if I am not wrong).
And don't get confused with return true; and return false;. True simply means 1 and false means 0. And a boolean type variable can store only binary number (1 or 0).
There is so much wrong with your code.
Why are you calling strlen() in while()? It will get executed every time till the loop doesn't exit and will cost on performance.
Also the variable different is not initialized with value 1, so how can you be so sure about the initial value of that variable?
I have tried to simplify your function still, there is scope for optimization:
int meme(char s1[], char s2[])
{
int i = 0;
int different;
int str1_len = strlen(s1);
int str2_len = strlen(s2);
if(str1_len > str2_len)
str1_len = str2_len;
do{
if(s1[i] == s2[i])
{
printf("Common\n");
different = 0;
}
else
{
different = 1;
}
i++;
}while(str1_len--);
return different;
}

Compare two arrays and return the index of the first appearence

I have a task to do, and I was thinking about it, but I dont come up with the right answer.
In a language of your choosing, write a function that gets a string named str and a string named set.
The function will return the index of the first appearance of any char from set in str.
For example:
str = "hellohellohellohelloistom!"
set = "t98765!"
The function will return 22 (index of '5' in str).
Make sure that time complexity is not larger than the length of both strings - O(m+n)
Assume that the string only contains ASCII characters.
I was thinking about it and I thought about doing it with divide and conquer. I have a base case that is always O(1) and the I divide the problem in smaller problems until I get the answer. The problem is that with that solution the complexity will be O(log n).
The other approax I thought was to make a Set. But I still don't really know how to approach this problem. Any ideas??
This program is written in Swift
let str = "hellohellohellohelloistom!"
let set = "t98765!"
func findFirstAppearance(str : String , set : String) -> Int? {
var index : Int?
mainLoop: for setCharacter in set.characters{
for (indexOfChar,strCharacter) in str.characters.enumerate(){
if strCharacter == setCharacter{
index = indexOfChar
break mainLoop
}
}
}
return index
}
print(findFirstAppearance(str, set: set))
print(findFirstAppearance("helloWorld", set: "546Wo"))
Or another solution with less time consuming
let str = "hellohellohellohelloistom!"
let set = "t98765!"
func findFirstAppearance(str : String , set : String) -> Int? {
var index : Int?
mainLoop: for setCharacter in set.characters{
if let range = str.rangeOfString(String(setCharacter)){
index = str.startIndex.distanceTo(range.startIndex)
break
}
}
return index
}
print(findFirstAppearance(str, set: set))
print(findFirstAppearance("helloWorld", set: "546Wo"))
Note :
if any character is not found then it will return nil
it's case sensitive comparison
Hope this will solve your problem.
Since all the strings involved contain only ASCII characters then using constant memory this can be solved in O(LengthOf(str) + LengthOf(set)).
Here is the code in "C" Language:
//ReturnValues:
//-1 : if no occurrence of any character of set is found in str
//value >=0 : index of character in str.
int FindFirstOccurenceOfAnyCharacterInSet(const char *str, const char *set, int *index_of_set)
{
char hash[256];
int i = 0;
while(i < 256)
{
hash[i] = -1;
++i;
}
i = 0;
while(set[i] != '\0')
{
hash[set[i]] = i;
++i;
}
i = 0;
while(str[i] != '\0')
{
if(hash[str[i]] != -1)
{
*index_of_set = hash[str[i]];
return i;
}
++i;
}
*index_of_set = -1;
return -1;
}
Logic works by recording the position/indexes (which are >=0) of all the characters of set in hash table and then parsing str and checking whether the current character of str is present in hash table.
index_of_set will also report the index of character in set which is found in str. If index_of_set = -1 then no occurrence was found.
Thanks for the help!!
Here is also the code in C#.
Cheers,
public static int FindFirstOccurenceOfAnyCharacterInSet(string str, string set)
{
var hash = new int[256];
int i = 0;
while (i < 256)
{
hash[i] = -1;
++i;
}
i = 0;
do
{
hash[set[i]] = i;
++i;
} while (set[i] != '\0' && i < set.Length - 1);
i = 0;
while (str[i] != '\0')
{
if (hash[str[i]] != -1)
{
return i;
}
++i;
}
return -1;
}

strlen function using recursion in c

I'm kida new to the recursion subject and i've been trying to write the "strlen" function using recurion, thats what i tried:
int strlen ( char str[], int i)
{
if ( str[i] == 0) return i+1;
return strlen(str,i++);
}
and i tried something very similiar
int strlen( char str[], int i)
{
if ( str[i] == 0) return 1;
return strlen(str,i++) + 1;
}
and in my main function
int main()
{
char word[MAX_DIGITS];
scanf("%s",word);
printf("%d", strlen(word,0));
return 0;
}
but my program would crash whenever i run it, what am I missing? (I'm using C90 btw)
Your problem starts here:
i++
This is called a postfix.
Just use ++i or i + 1
Postfix sends the value and just then increments the variable. It's like writing this:
return strlen(str,i);
i = i + 1;
You have to use Prefix, which increments the variable and then sends the value. A prefix (++i) will act like that:
i = i + 1;
return strlen(str,i);
Or just send the value without changing the variable:
return strlen(str, i + 1);
Which, in my opinion, is the simplest way to do that.
size_t strlen (char* str) {
if (*str == 0) {
return 0;
}
return strlen (str+1) +1;
}
So :
strlen ("") == 0
strlen ("a") -> strln("") + 1 == 1
strlen ("he") -> strln("e") + 1) = (strln("") + 1) + 1 == 2
etc
return strlen(str,i++);
You are using the wrong increment operator. i++ means the original value of i is passed as argument, and then it's incremented. That means infinite recursion.
You should try ++i instead, or better, i + 1.
If you want to keep the same prototype as strlen does.
This is how i see a strlen with recursion.
size_t strlen(char *str)
{
static int i = 0;
if (*str != '\0')
{
i++;
return ft_strlen(++str);
}
return i;
}
I know it's not the best way to do it. Just my implementation.

Resources