Trouble with a sequential search algorithm - c

Also why does this give me an error because I used bool?
I need to use this sequential search algorithm, but I am not really sure how. I need to use it with an array. Can someone point me in the correct direction or something on how to use this.
bool seqSearch (int list[], int last, int target, int* locn){
int looker;
looker = 0;
while(looker < last && target != list[looker]){
looker++;
}
*locn = looker;
return(target == list[looker]);
}

Looks like you'd use it like this...
// I assume you've set an int list[], an int listlen and an int intToFind
int where;
bool found = seqSearch(list, listlen - 1, intToFind, &where);
if (found)
{
// list[where] is the entry that was found; do something with it
}

It's pretty clear
list[] is the list you are searching
last is the last index in the list
target is what you are searching in list
locn will contain the index at which target was found
the return value is a boolean indicating if the target was found
for your question how to pass locn, do something like
int locn; /* the locn where the index of target will be stored if found */
bool target_found = seqSearch(blah blah blah, &locn);

The problem with your code is if you search for an element not present in the array, looker will be equal to last and you try to access an array element at location last which is invalid.
Instead you can do:
bool seqSearch (int list[], int last, int target, int* locn) {
int looker;
for(looker=0;looker<last;looker++) {
// target found.
if(list[looker] == target) {
*locn = looker; // copy location.
return true; // return true.
}
}
// target not found.
*locn = -1; // copy an invalid location.
return false; // return false.
}
You call the function as follows:
int list[] = {5,4,3,2,1}; // the array to search in.
int size = sizeof(list)/sizeof(list[0]); // number of elements in the array.
int target = 3; // the key to search for.
int locn; // to hold the location of the key found..and -1 if not found.
if( seqSearch(list,size,target,&locn) ) {
// target found in list at location locn.
} else {
// target not found in list.
}

There are a few issues.
I would change the name of last to size.
If you don't find the value, you will dereference an invalid memory location.
EDIT: I guess last is the length - 1. That's an unusual signature. So the call is something like:
int list[CONSTANT];
...
int foundIndex;
bool found = seqSearch(list, sizeof(list)/sizeof(int), target, &foundIndex);
There are many ways to enable bool. One is to use stdbool.h with C99.

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.

Function is returning 1 instead of a value?

I am writing a Queue data structure and I am not able to retain the value of the integer in the array once the value is returned in the stack. The pop function is doing exactly what it needs to do but why doesn't main get that information? What am I missing? malloc?
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
int QUE[20];
const int EMPTY = -1;
int position = -1;
int retrieve = 0;
//push, append to front of array
bool push(int num) {
if (position >= 20) return false;
position += 1;
QUE[position] = num;
return true;
}
//pop from top of array
bool pop() {
if(QUE[retrieve] == 0) return false;
int hold = QUE[retrieve];
printf("%d",hold);
retrieve ++;
return hold;
}
// PEEK
// First in first out
int main() {
push(12);
push(90);
push(22);
int t;
//why does pop equal 1
while ((t = pop()) != 0) {
printf("t = %d\n",t);
}
}
You're trying to pass two different kinds of information – a boolean state 'the pop succeeded' and an integer value popped from the queue – within the same value. That's bad; and the mismatch led you to declaring the return type as bool, which causes the resulting value of t being either zero or one (as a conversion of false or true, respectively, to the int type).
Try to split the action into testing and fetching phase, like:
bool anyItemInQueue()
{
return _add_appropriate_condition_here_;
}
int main()
{
....
while( anyItemInQueue() )
{
int t = pop();
.... // use t here
}
}
or pass another variable to receive another value:
bool pop(int *result)
{
if( anyItemInQueue() )
{
*result = QUE[retrieve];
.... // some housekeeping here
return true; // success status
}
return false; // failure status
}
int main()
{
....
int t;
while( pop( & t ) ) // point at t to receive the popped value
{
.... // use t here
}
}
It is because any non zero value is being converted to bool true and then to integer. The integer value of the bool true is 1
Your code has undefined behavior.
Let's consider for example the function push
//push, append to front of array
bool push(int num) {
if (position >= 20) return false;
position += 1;
QUE[position] = num;
return true;
}
and let's also assume for simplicity that the array QUE has only one element that is it is declared like
int QUE[1];
In this case the queue can only contain one pushed value due to the capacity of the array.
So after a first call of push like
push( 0 );
you will have that position is equal to 0 and the queue contains the value 0.
If to call the function a second time like for example
push( 1 );
the condition within the function
if (position >= 1) return false;
will not evaluate to true because the current value of position is 0. As a result the function will try to write the value 1 into the invalid location of the array QUE[1].
The array contains only one element but the function allows to write one more element.
Now let's consider the function pop
bool pop() {
if(QUE[retrieve] == 0) return false;
int hold = QUE[retrieve];
printf("%d",hold);
retrieve ++;
return hold;
}
and the same queue that already contains only one element equal to 0 (See the previous call push( 0 )).
As the condition of the if statement
if(QUE[retrieve] == 0) return false;
evaluates to true (the queue indeed contains the value 0 pushed on the queue early) then the function will return false as if the queue is empty though it is not empty.
So and this function is invalid.
Moreover in the loop in main
while ((t = pop()) != 0) {
printf("t = %d\n",t);
}
it seems you are trying to output values stored in the queue. However the function does not return such values. Due to the return type bool that is a typedef for the C standard type _Bool any returned value is converted either to 0 or 1.
So the program is in whole wrong.

How do I use the value of a variable in a function else where?

I have a certain program that lets you register members and save their name and birthdate into arrays. The particular function that does this registration uses the following code;
char regmember (struct member a[])
{
int i = 0;
char wow;
do
{
//registration
printf("\n Do you want to add someone else (y/n):");
scanf(" %c",&wow);
i++
}while(wow != 'n');
int nrofmembers = i;
return nrofmembers;
}
-> I save the user input by using
scanf("%s",a[i].name) and scanf("%d",&a[i].ID);
which is why I am using i++. As you realize, the int variable i, will hold the number of members who have been registered. I want to utilize this info in order to use it in loops in other functions, so I went on to save the value of i in another int variable...
int nrofmembers = i;
My problem is, I can't use that variable (nrofmembers) else where, even though I tried returning it, any advice?
you need both to get i in parameter and to return the new value, you can do
int regmember (struct member a[], int i)
{
... use and modify i
return i;
}
or using it as an input-output variable
void regmember (struct member a[], int * i)
{
... use and modify *i
}
In the first case the caller do for instance :
int i = 0;
for (...) {
...
i = regmember(..., i);
...
}
and in the second case :
int i = 0;
for (...) {
...
regmember(..., &i);
...
}
Suppose you keep the members in a global array, then you can manage how many members are in your array also as a global variable, for example
struct member gMembers[MAX_MEMBERS];
int gnMembers;
Your function can now operate on this array directly:
int regmember (void)
{
if (gnMembers < MAX_MEMBERS)
{
// add member
if (scanf("%s",gMembers[gnMembers].name)==1
&& scanf("%d",&gMembers[gnMembers].ID)==1) {
gnMembers++;
return 1; // success
}
}
return 0; // array full or scanf error
}

Initialize int array in struct in C

I have written a type:
typedef struct
{
int Tape[TAPE_SIZE];
int *Head;
int Tape_Count;
int Loop_Start_Count;
} Tarpit;
I try to initialize this type with the following function:
void Tarpit_Initialize(Tarpit Tarpit)
{
Tarpit.Tape_Count = 0;
Tarpit.Loop_Start_Count = 0;
int Index;
for(Index = 0; Index < TAPE_SIZE; Index++)
{
Tarpit.Tape[Index] = INITIAL_SIZE;
}
}
However, it does not seem to work. If I run this:
Tarpit Foo;
Tarpit_Initialize(Foo);
printf("Tarpit Initialization Test: \n");
int index;
for(index = 0; index < TAPE_SIZE ; index++)
{
if(Foo.Tape[index] == INITIAL_SIZE)
{
printf("%d: %d \n", index, Foo.Tape[index]);
}
else
{
printf("%d: %d !ERROR \n", index, Foo.Tape[index]);
}
}
I get several non-zero values (I have set #define TAPE_SIZE 10000 and #define INITIAL_SIZE 0)
Moreover, if I run the test without running Tarpit_Initialize(Foo), I get exactly the same results. The initializer does not seem to work. Why/how could I implement it in an other way? I would like to set every element of Foo.Tape to zero.
Problem solved!
You are passing Tarpit by value:
void Tape_Initialize(Tarpit Tarpit)
That means it is only a copy of Tarpit. You have to pass a pointer to it to be able to modify it.
void Tape_Initialize(Tarpit* Tarpit)
and pass it as pointer (note the name of the function called!):
Tape_Initialize(&Foo);
and the use the -> operator to modify it. For instance:
Tarpit->Tape_Count = 0;
Moreover, as "Elias Van Ootegem" pointed out, you should not use sizeof(Tarpit.Tape) to get the size of the array but TAPE_LENGTH that you defined. Because sizeof() will give you a size in bytes not in elements.
Have you checked the function u are calling ??
Its "Tarpit_Initialize(Foo);"
But the Function u are using it to initialize "void Tape_Initialize(Tarpit Tarpit)".
I think even what u have implemented should work fine .

Function that searches for difference between members of an array

I need to write a function that will return true if it has found a difference between members of an array.
My code is:
int func1(int *str)
{
int i;
for(i=0;i<*(str+i);i++) {
if(*(str+i) == *(str+i+1))
{
return 1;
}
}
return 0;
}
I have to implement it with pointers.
The code above does not work(logically).
Can anybody help?
UPDATE:
I have changed my code to the following:
int func1(int *str)
{
int i,temp=0;
for(i=0;i<10-1;i++) {
if(*(str+i) == *(str+i+1))
{
temp++;
if( temp == 10 )
{
return 1;
}
}
}
return 0;
}
What is the problem with the new code?
This looks like homework to me, so I don't want to spoil the fun but one thing about C I'd like to mention: having a pointer to some array doesn't tell you anything about the size of the array. So your function will need to take a pointer and a second size_t argument (or maybe a pointer to the last element of the array).
Your function only takes in a single array pointer, that seems like one too few for a comparison.
You must add an argument that specifies the lengths of the arrays, or implement some kind of "policy" that e.g. terminates the arrays using a specific value.
You should also look into using the standard memcmp() function.
I don't understand the question (It's unclear what you're trying to achieve)...
As others have already said, there's no boundary checking on your array, which is wrong...
Here's some other feedback on your code:
// func1 - consider giving functions a meaningful name, it helps people to
// understand what the function is supposed to be doing....
// In this instance, it might have been helpful to identify what the expected
// return values / inputs of the function are...
int func1(int *str)
{
int i;
// Start a counter at 0, loop (adding 1) while
// the current value of the counter is less than, the value held in the
// array so, {1,2,3,4,0,7} Would terminate on the 0
// This: {1,20,7,14,0,7} Would also terminate on the 0
// This seems wrong, but again, it's unclear what you're trying to do here.
for(i=0;i<*(str+i);i++) {
// If the current element of the array
// is the same as the next element of the array
if(*(str+i) == *(str+i+1))
{
// return 1 - two numbers next to each other in the
// array are the same?
return 1;
}
}
// Either: The array contained a digit less than the counter,
// Or: It didn't contain two numbers that were the same next to each other.
// This seems a bit wrong?!?
return 0;
}
Your question could be improved (to get a more useful answer), if you showed what inputs you were expecting to return what return values.
Based on this 'I will need to write a function that will return true if its found diffrence between members of array.'
In pseudo code, it seems like you would want:
// Loop, checking we don't overflow. No point checking the last element as
// there's nothing after it to check...
for (count = 0 to arraysize -1) {
// If the current element != the next element, we've found a difference?!?
if(arrayElement[count] != arrayElement[count+1) {
return true
}
}
return false
UPDATE:
In your new code...
// You're still assuming the size of 'str'
int func1(int *str)
{
int i,temp=0;
// Loop while i < 9, i.e. 9 times.
for(i=0;i<10-1;i++) {
if(*(str+i) == *(str+i+1))
{
temp++;
// Temp can never == 10, you're only going round the loop 9 times...
// Maybe it should be (temp == 10-1), but I don't know where the
// 10 comes from...
if( temp == 10 )
{
return 1;
}
}
}
return 0;
}
This:
if(*(str+i) == *(str+i+1))
{
temp++;
// Temp can never == 10, you're only going round the loop 9 times...
if( temp == 10 )
{
return 1;
}
}
Could be:
// return 0 (FALSE) on first difference
if(*(str+i) != *(str+i+1))
{
return 0;
}
If you changed the return 0 at the end of your function to return 1

Resources