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.
Related
How do I take argv[1] from main so that I can use it in my function called only_digits? You don't have to show it to me on my code. I would just like to see, how argv[1] (that is stored in main) can be used in a function (outside of main).
It is also the first time I've used a bool function. I'm wondering if, in the <cs50.h> library, you can use strings and bools the way I used them here. Am I using them right?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
bool only_digits(string);
int x;
int main(int argc, string argv[])
{
string s = argv[1];
x = only_digits(s);
if (x == 1)
{
printf("True\n");
}
else if (x == 0)
{
printf("False\n");
}
}
bool only_digits(string s);
{
for (i= 0; i < strlen(s); i++)
{
if (isdigit(s [i]))
{
return 1;
}
else if (!isdigit(s [i]))
{
return 0;
}
}
}
Your code is really close to being correct. There are a couple of things:
remove the semicolon from the definition of only_digits.
bool only_digits(string s);
{
should be:
bool only_digits(string s)
{
make the i in the loop an int.
for( i =
should be:
for( int i =
fix the logic in the loop so it returns false (aka 0) if any character is not a digit, else if it gets all the way through the loop return true.
bool
only_digits (string s)
{
for (int i = 0; i < strlen (s); i++)
{
if (!isdigit (s[i]))
{
return 0;
}
}
return 1;
}
How do I take argv[1] from main so that I can use it in my function called only_digits?
In your main, the expression argv[1] designates an object of type string. You can do with it anything that you can do with any other string, including pass it as a function argument. Your only_digits() function expects an argument of type string, so you don't need to do anything special to pass argv[1] to it. This will work fine:
x = only_digits(argv[1]);
You can also assign argv[1] to a variable of type string, and then pass the value of that variable, as the code you present does. That's needlessly roundabout, but it will work fine, too.
However, if your function is intended to determine whether all the characters in the string that is passed to it are decimal digits, then it is buggy, as other answers describe in more detail. Loop notwithstanding, it decides what value to return based only on the first character in its input string, because either one or the other conditional inside the loop must evaluate to true no matter what that character is, and the function returns either way. It also fails to return anything at all in the event that an empty string is passed to it.
Note also that CS50 makes the unfortunate choice of using string as an alias for type char *. This is perhaps easier to read, and it defers the need to talk about pointers, but it sets students up for confusion later on when they discover that strings seem to behave differently than objects of most other data types.
It is also the first time I've used a bool function. I'm wondering if, in the <cs50.h> library, you can use strings and bools the way I used them here. Am I using them right?
There is nothing inherently wrong with the way you are using string and bool. Probably the compiler would warn you if there were, or even outright reject the code. Your program produces different results than you expect because it contains logic errors.
You ask two questions.
First, there's no need for string s. argv[] is an array of pointers to strings, so you could pass the string of interest like so:
x = only_digits( argv[1] );
BUT, before using it, you must test that the user has supplied a string:
if( argc == 2 )
x = only_digits( argv[1] );
Second, returning 1 for true or 0 for false, will work, but you should use the tokens that mean boolean results.
return true; // or return false;
Here's a version that moves the function ahead of its invocation. In this way, there's no need for a function prototype.
bool only_digits( string s )
{
while( isdigit( *s ) )
s++;
// TRUE if reached end of string
if( *s == '\0' )
return true;
return false;
}
void main( int argc, string argv[] )
{
if( argc == 2 && argv[1][0] != '\0' && only_digits( argv[1] ) )
printf( "True\n" );
else
printf( "False\n" );
}
The semicolon(;) needs to be removed:
bool only_digits(string s)
{
for (i= 0; i < strlen(s); i++)
{
if (isdigit(s[i]))
{
return 1;
}
else
{
return 0;
}
}
}
and you can simply use else in place of else if because if s[i] is not
A digit, then it doesn't matter what it is we just need to return false or 0 in that condition
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.
I need to use a binary search to recursively find a target string. The function should return a -1 if it is not found and a positive integer if found but it always returns -1. thanks for the help!
int start = 0;
int search;
search = binary_search(strings, target, start, size-1);
if(search == -1)
{
printf("Not in the dataset!");
}
if(search != -1)
{
printf("%s is in the dataset", target);
}
int binary_search(char **strings, char *target, int start_idx, int end_idx)
{
if(end_idx < start_idx)
{
return -1;
}
int middle = ((start_idx + end_idx)/2);
int i;
i = strcmp(target, strings[middle]);
if(i == 0)
{
return middle;
}
if(i < 0)
{
return binary_search(strings, target, start_idx, middle-1);
}
else
{
return binary_search(strings, target, middle+1, end_idx);
}
}
input data:
aden
caden
david
erik
john
mark
matt
mycah
phil
susan
Although binary search is notoriously hard to get right, I don't see any errors in your algorithm as shown. You can still fail (-1) due to various causes that can not be determined based on the information provided.
1) Your source strings list is not actually sorted correctly -- strcmp() uses ASCII comparison, not dictionary comparison, i.e., your source string must be ASCII sorted for bsearch to be valid.
2) Your source strings are not well-formed NUL terminated C strings.
3) The target string does not have an exact match in the source string list. i.e., searching for "bill" will not match "Bill" or "billiard"
Just a note, a recursive bsearch is slower than and uses more memory than a non-recursive solution
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);
}
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