I am trying to write a function(findString) to find out if character strings are present inside another string. For my function, the first argument is the searched character string and the second is the one trying to be found.
If the string is found, then the location of the source string is returned.
My written code is below:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int findstring(char source[], char lookup[]){
int lensource, lenlookup;
lensource= strlen(source);
lenlookup = strlen(lookup);
int i;int j;
for(i=0; i>=lensource; ++i)
for (j=0; j>=lenlookup; ++j)
if (source[i]==lookup[j])
return i;
}
int main(){
findstring("Heyman","ey");
}
If the function worked properly, then the index 2 should be returned.
However, when I run it, nothing is returned. I suppose the problem it that there is something wrong with my approach with the for loop or if statement.
I'm doing this without using strstr
First, there is a function that does this already, called strstr.
Second, your loop is written incorrectly. It should be:
for(i=0; i < lensource - lenlookup + 1; ++i) {
for (j=0; j<lenlookup; ++j)
if (source[i + j]!=lookup[j])
break;
if (j == lenlookup) return i + 1; // edit: had error
// note that return i feels more right, but
// op's spec seems to want i + 1
}
return -1; // no spec on return value for failure, but -1 seems reasonable
Edit: had typo.
Assuming both source and lookup are non-empty strings, then both lenlookup and lensource are strictly positive.
And your for loops are never executed, because
for(i=0; i>=lensource; ++i) {
// do something
}
is understood as (and translated by the compiler to):
i=0;
while(i>=lensource) {
// do something;
// at last
++i;
}
so you understand the initial test i>=lensource is false (at start i==0 but lensource>0) so the loop is never executed
BTW I strongly suggest to compile your code with all warnings and debugging info (e.g. gcc -Wall -g) and to use a debugger (e.g. gdb) to run it step by step and understanding what is happening.
You missed basic input check (what if either source or lookup is NULL, what if lookup is an empty string, what if lookup is longer than source, etc)
The comparison is not performed correctly
Your function doesn't always return a value (what does it return if lookup is not found in source?).
int findstring(char source[], char lookup[]){
// when either input is NULL
if(source==NULL||lookup==NULL)return -1;
int lensource, lenlookup;
lensource= strlen(source);
lenlookup = strlen(lookup);
// when lookup is an empty string
if(lenlookup==0)return 0;
// when lookup is longer than source
if(lenlookup>lensource)return -1;
int i;int j;
for(i=0; i<=lensource-lenlookup; ++i){
bool success = true;
for (j=0; j<=lenlookup; ++j){
if(lenlookup[j]!=lenlookup[i+j]){
success = false;
break;
}
}
if(success)return i;
}
return -1;
}
You may also want to check out other more efficient algorithms like KMP, boyer-moore and rabin-karp.
Related
I am quite new to C so my apologies if this is a straight forward problem but I cannot seem to find my error. My code is as follows
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* makeString(char character,int count)
{
int i;
char* finalString=malloc(count+1);
for(i=1;i<=count;i++)
{
finalString[i]=character;
}
finalString[count]=0;
return finalString;
}
int main()
{
char* string=makeString('*',5);
printf("%s\n",string);
}
I am trying to get an output of the finalString which would be 'character', 'count' number of times. I am not getting any errors or warnings but It is not generating any output. When debugging it runs the loop successfully but does not ever store any character into finalString. Any help appreciated.
As with many programming languages, C uses 0-based indices for arrays. The first element of the character array at finalString is finalString[0], not finalString[1].
Your for loop should go from 0 to count - 1, instead of from 1 to count. The line:
for(i = 1; i <= count; i++)
should instead be:
for(i = 0; i < count; i++)
As your code is now, you have undefined behaviour, because you try to print finalString[0], which is uninitialized. In this case, it seems to be 0 ('\0').
I've ignored the fact that makeString is missing its closing }, since you say this compiles correctly, I assume that's a pasting error.
Arrays in C begin at 0, i.e. the 1st element is finalString[0].
Since you do not set it, it contains garbage, and most probably a NUL which ends the string immediately.
Your loop should look like
for(i=0;i<count;i++)
...
and so on.
Just wondering if these variations of for loops are more efficient and practical.
By messing with the c for loop syntax i can embedd statements that would go in the loop-body into the loop-head like so:
Example 1:
#include <stdio.h>
int main(int argc, char ** argv)
{
// Simple program that prints out the command line arguments passed in
if (argc > 1)
{
for(int i = 1; puts(argv[i++]), i < argc;);
// This does the same as this:
// for(int i = 1; i < argc; i++)
// {
// puts(argv[i]);
// }
}
return 0;
}
I understand how the commas work in the for loop it goes through each statement in order, evaluates them then disregards all but the last one which is why it is able to iterate using the "i < argc"condition. There is no need for the final segment to increment the i variable as i did that in the middle segment of the loop head (in the puts(argv[i++]) bit).
Is this more efficient or is just just cleaner to seperate it into the loop body rather than combine it all into one line?
Example 2:
int stringLength(const char * string)
{
// Function that counts characters up until null terminator character and returns the total
int counter = 0;
for(counter; string[counter] != '\0'; counter++);
return counter;
// Same as:
//int counter = 0;
// for(int i = 0; string[i] != '\0'; i++)
//{
// counter++;
//}
//return counter;
}
This one seems more efficient than the version with the loop body as no local variable for the for-loop is initialised. Is it conventional to do these sorts of loops with no bodies?
Step 1: Correctness
Make sure code is correct.
Consider OP's code below. Does it attempt to print argv[argc] which would be bad?
if (argc > 1) {
for(int i = 1; puts(argv[i++]), i < argc;);
I initially thought it did. So did another user. Yet it OK.
… and this is exactly why code is weak.
Code not only should be correct, better code looks correct too. Using an anti-pattern as suggested by OP is rarely1 as good thing.
Step 2: Since code variations have the same big O, focus on understandably.
Sculpt your code – remove what is not needed.
for (int i = 1; i < argc; i++) {
puts(argv[i]);
}
What OP is doing is a trivial optimization concern.
Is premature optimization really the root of all evil?
Is it conventional to do these sorts of loops with no bodies?
Not really.
The key to the style of coding is to follow your group's style guide. Great software is often a team effort. If your group's likes to minimize bodies, go ahead. I have seen the opposite more common, explicit { some_code } bodies.
Note: int stringLength(const char * string) fails for strings longer than INT_MAX. Better to use size_t as the return type – thus an example of step 1 faltering.
1 All coding style rules, except this rule, have exceptions.
Are there any significant differences between the following two methods of printing text using subscripts? Are there any pros/cons of using one method over the other?
#include <stdio.h>
int main(void)
{
int i;
char *text;
/* method 1 */
text = "abc";
for (i = 0; i < 3; ++i) {
printf("%c\n", text[i]);
}
printf("\n");
/* method 2 */
for (i = 0; i < 3; ++i) {
printf("%c\n", "abc"[i]);
}
return 0;
}
Both methods are basically the same. The 2nd method could be slightly faster since your print function calls a static value ("abc") instead of a reference to "abc".
I wouldn't be surprised if the compiler would make those 2 methods similar in the end.
This being said, the first method should be better in most situations since you'll probably want to reuse the 'text' variable or load it from elsewhere.
I'm writing a function for my homework which is supposed to tell if a given string is a palindrome or not.
Although I even tried it on paper with the word "otto", my program always returns 1.
Although this is a quite common question, I'd really like to know what I'm doing wrong instead of just copying a solution from here.
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
Your code is correct, however please note that you may have an inverted logical expression. You are returning 1 in case of not equal, and 0 when it is. This means your function is working the opposite of "standard" C functions, where 1 evaluates to true.
Obviously, you are free to use whichever value you like to represent whatever you want. However, this can easily lead to confusion if someone else is reading your code. If bool is available, you should be using that; otherwise, you should always assume 1 is true and 0 is false.
Also, make sure to note is_palindrome takes a string and not an integer.
i.e. you must call it as is_palindrome("767") and not is_palindrome(767)
Your code does return 0 when it should. I am guessing when you read the string you pass as argument to your function, there are extra characters appended to the string, most probably a new line character. Try debugging the application or adding debug output in the function. For instance print the length of the string and the ascii codes of the characters in it.
Here is the code I used to verify it:
#include <stdio.h>
#include <string.h>
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
int main(void) {
printf("%d", is_palindrom("otto"));
return 0;
}
Make sure your (const char *) has a "\0" at the end when you call this function.
#include<stdio.h>
#include<conio.h>
int is_palindrom(const char* jj);
int main(char *args){
int rr = is_palindrom("otto");
printf("rsult is %d", rr);
getch();
}
int is_palindrom(const char* palin)
{
int size = strlen(palin), i=0;
for (i=0;i<=(size/2); ++i)
{
if(palin[i] != palin[(size - i -1)])
{
return 1;
}
}
return 0;
}
I ran you code using above code snippet and it work fine for me.it returns 0 if palindrome is entered and 1 if entered value is not palindrome. the main part of the function is the loop
for (i=0;i<=(size/2); ++i) and the comparison if(palin[i] != palin[(size - i -1)]) the loop starts from 0 and then in condition palin[0] element and palin[4-0-1] i.e palin[3] element first o and last o in this case are mapped then the increement ++i takes place and then nest mapping of palin[second] and palin[second-last] elements happen so you can you either `++i' or 'i++'
So, I have a task to find number of substrings in given string. I can't use any C libraries for doing this task. stringExist can only have 2 strings as a parameters.
My solution is working, but I have a feeling that there should be a more elegant way to do this task.
Solution 1: as it turns out, it doesn't work correctly
#include <stdio.h>
int stringExist(char string[], char s2[]);
int main(void){
char string[] = "strstrASDstrSTRst";
char s2[] = "str";
printf("Final result: %i\n",stringExist(string,s2));
return 0;
}
int stringExist(char string[], char s2[]){
/* I am aware that I can init all this values in one row */
int count = 0;
int size = 0;
int i = 0;
int temp = 0;
int result = 0;
while(s2[size]!='\0'){
size++;
}
while(string[i]!='\0')
{
if(string[i]==s2[0])
{
printf("Found first occurrence\n");
count=0;
while((temp=(string[i]==s2[count]))!=0)
{
count++;
if(size==count){
printf("Match\n");
result++;
break;
}
i++;
}
}
i++;
}
return result;
}
Solution number 2:
So far no errors found.
Did a little bit different string traversal, now I don't increment i in the compare chars loop.
#include <stdio.h>
int stringExist(char string[], char s2[]);
int main(void){
char string[] = "bobobobojkhhkjjkhbo;klkl;bobo";
char s2[] = "bobo";
printf("Final result: %i\n",stringExist(string,s2));
return 0;
}
int stringExist(char string[], char s2[]){
int count = 0;
int size = 0;
int i = 0;
int c = 0;
int temp = 0;
int result = 0;
while(s2[size]!='\0'){
size++;
}
for(i=0;string[i]!='\0';i++){
if(string[i]==s2[0])
{
printf("Found first occurence at %i\n",i);
count = 0;
c = i;
while((temp=(string[c]==s2[count]))!=0)
{
printf("Count %i, I %i, current char: %c\n",count, c,string[c]);
count++;
if(size==count){
printf("Match\n");
result++;
break;
}
c++;
}
}
}
return result;
}
Thanks for you suggestions,
Vitaly
beat it: (also works for the extra condition)
int stringExist( char *string, char *sub )
{
int count = 0;
while( *string )
{
char *a = string, *b = sub;
while( *a && *a == *b ) {a++;b++;}
count += !*b;
++string;
}
return count;
}
I suggest writing it the way you would if you were allowed to use library functions. Then go back and write your own versions of those library functions that you used. While writing highly optimized versions of the string.h functions may be difficult, writing decent versions of most of them them in C is pretty easy..
Using subroutines (functions) to preform sub-tasks of this problem will help you to keep your code clear and also avoid certain types of problems, such as if you called:
x = stringExist("aaaaa", "aa");
There are 4 occurances of the string "aa" within "aaaaa", but I don't think that your function will find all of them. The reason for this is that as you search through the larger string for occurances of the second you are using the same index for both the beginning of the string and within the string. In fact, it looks like you would get the wrong results for:
x = stringExist("tBatBath", "tBath");
Unless of course, I've misunderstood what the function was supposed to do.
If you were to write your own version of a string prefix comparing function (essentially memcmp or strncmp) then you would have separated the job of matching the length of the string from looking deeper into the string and probably would not have made such a mistake.
If you are worried about squeezing efficiency out of your functions and the overhead of calling functions, don't. First, it's not that bad. Second, just declare them inline or static inline and if you compile with optimization turned on the compiler will most likely generate code as good as it would have without the use of multiple functions.
This feels like a homework question - in which case you should definitely just do it yourself. But, something that you'll probably want to check for that I don't think your code is handling correctly now is this:
How many times does "bobo" appear in the string "bobobo". It should probably be twice and I think your code as is will only count one.
Good luck,
Mark.
Well, from an algorithmic point of view, it's not bad. You can make optimizations, but I don't think that's the point (looks like homework!).
You may have a slight issue: in a string like "hahahaha", how many times should "haha" be detected? Twice? Thrice? Your code would see it twice.
From a stylistic point of view, there's certainly room for improvement, but you'll learn that over time, from coding and reading other's code =). Keep at it!