I'm new to C and I'm trying to solve one of the exercise problem of K&R book. The problem is to detect the whether a given string ends with the same content of other string.
For example, if string one is ratandcat and string two is cat. Then it is true that string two ends in string one. To solve this, I came up with half a solution and I got struck with pointers.
My idea is to find the position where string one ends and also the position the string two starts, so that I can proceed further. I have this code:
int strEnd(char *s,char *t){
int ans,slength =0 ,tlength = 0;
while(*s++)
slength++;
while(*t++)
tlength++;
s += slength - tlength;
printf("%c\n",*t);
printf("%c\n",*s);
return ans;
}
void main() {
char *message = "ratandcat";
char *message2 = "at";
int a = strEnd(message,message2);
}
But strangely this outputs :
%
(and a blank space)
But I want my s pointer to point to a. But it doesn't. Whats going wrong here?
Thanks in advance.
One problem is that you have incremented the s pointer to the end of the string, and then you add more stuff to it. You could do that loop with something like:
while(s[slength])
++slength;
Another problem is that you are assuming that the s string is longer than the other. What if it's not? And fix the ; problem noted by Simon.
You have an extra semicolon at the end of
while(*t++);
This means that tlength is never incremented, as only the semicolon (empty statement) is executed in the loop.
Related
I want to loop through a text file and concatenate all the strings until a blank line is hit and then do the same for the next strings and so on. The result of each string concatenation should be added to an char* array:
char* element_arr[287];
void splitPassports(FILE* file_to_read){
char element[500];
char str[80];
int i = 0;
int j = 0;
while(j < FILELENGTH){
if (fgets(str,80, file_to_read) && !isBlank(str)){
strcat(element,str);
printf("The string is: %s\n",str);
}else if (isBlank(str)){
element_arr[i] = element;
memset(element, '\0', sizeof element);
printf("%s\n",element_arr[0]);
i++;
}
j++;
}
fclose(file_to_read);
}
However when I try to do this I get an illegal hardware instruction error (I'm on a Mac). How can I properly add the new strings to the existing one and then append that to my array and after that set it back to zero to do the same for the few lines until a blank line is hit?
I'm relatively new to C so thanks in advance :)
char element[] = ""; you declare the array which is 1 char long, so the strcat will always fail (unless the second string is also empty).
Even if you define it the correct way, the assignment element_arr[i] = element; you will assign the array element with the same reference every time, so the array will be simple filled with references to the same object.
while(!feof(file_to_read)) - read Why is “while ( !feof (file) )” always wrong?
I would recommend starting with the C book as you do not understand the basics of the language.
Dumb response to question 3, you could see if the problem is due to over-layering. I am also a Mac user, and my code will sometimes have errors occur due to having too many layers of functions etc. I don't know if anyone has already found the answer to question 3, however I genuinely hope this helps/helped.
I am completing my CISCO course on C and I got a doubt in the following function.
Can someone please explain me the logic of the function, especially the use of --destination here?
char *mystrcat(char *destination, char *source)
{
char *res;
for(res = destination; *destination++; ) ;
for(--destination; (*destination++ = *source++); ) ;
return res;
}
The first loop is looking for the string teminator. When it finds it, with *destination being false, the pointer is still post-incremented with *destination++.
So the next loop starts by decrementing the pointer back to pointing to the '\0' terminator, to start the concatentation.
In the second loop, each character is copied until the string terminator is found with (*destination++ = *source++); which is evaluated as the loop control. Again, this will include the required string terminator being copied.
This is a very complicated function for something that shouldn't be written so difficult.
--destination is a weird feature of C. I'm assuming you already know that variable++ increments the variable by one. Similarly variable-- decrements the variable by one. The thing is, when the ++ or -- comes after the variable name, that operation is done after the line is executed as a whole, when it is before the variable, C does the arithmetic first, then evaluates the full line.
For an example:
int c = 5
print(c++) -> outputs '5'
print(c) -> outputs '6'
but
int d = 5
print(++d) -> outputs '6'
print(d) -> outputs '6'
This is because in the second example, the increment is evaluated before the entire line is evaluate.
Hope that helps.
I'm really surprised I can't figure out a way to do this effectively. I've tried strstr, a combination of things with sscanf, and nothing seems to work the way I would expect it to based on my experience in other languages.
I have a char of "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS". I do not know where "BEGINTheMiddleEND" is in the string, and I would like to end with a char that equals "TheMiddle" by finding the occurrences of "BEGIN" and "END" and grabbing what is in between.
What is the most efficient way to accomplish this (find and sub-string)?
Thanks!
-- EDIT BASED ON ANSWERS --
I have tried this:
char *searchString = "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS"
char *t1, *t2;
t1 = strstr(searchString, "BEGIN");
t2 = strstr(t1, "END");
But something must be wrong from a pointer standpoint as it doesn't work for me. Strstr only takes two arguments, so I'm not sure what you mean by starting at the previous pointer. I'm also not sure how to then use those pointers to substring it, as they are not integer values like strpos returns, but character pointers.
Thanks again.
-- EDIT WITH FINAL CODE --
For anyone else who hits this, the final, working code:
char *searchString = "ABCDEFG HIJ K BEGINTheMiddleEND LMNO PQRS"
char *b = strstr(searchString , "BEGIN");
char *e = strstr(b, "END");
int offset = e - b;
b[offset] = 0;
Where "b" is now equal to "BEGINTheMiddle". (which as it turns out is what I needed in this case).
Thanks again everyone.
You need to realize what a string is. A 0 delimited sequence of chars.
strstr does what it says: it finds the beginning of the given substring.
So calling strstr with the needle "BEGIN" takes you to the position of this substring. The pointer pointing to "BEGIN", advanced by 5 characters is pointing to "TheMiddle" onward to the next 0 char. By searching for "END" you can find the end pointer, and then you need to copy the substring into a new string array (or cut it, by replacing the "E" with a 0; or implement your own string functions that do not use 0 terminated strings, so they can arbitrarily overlap).
That is probably the step that you are still missing: actually copy the string. E.g. using
t3 = strndup(t1, t2 - t1);
Take the string ABCDEF0, where 0 is an actual 0 character. A pointer to the beginning points to the full string, a pointer pointing to the E points to "EF" only. If you want to get a string "AB", you need to either copy that to "AB0", or replace C by 0.
strstr does not do the copying for you. It just finds the position. If you want an index, you can do int offset = newPosition - oldPosition;, but if you need to continue searching, it's easier to work with the newPosition pointer.
All this is less intuitive than e.g. String operations in Java. Except for truncating strings, it actually is more efficient as far as I know, and if you realize the 0-terminated memory layout, it makes a lot of sense. It's only when you think of strings as arrays that it may seem odd to have a pointer somewhere in the middle, and continue using it like a regular array. That makes "sub = string + offset" the C way of writing "sub = string.substring(offset)".
use strstr() twice, but the sencond time start from the position returned by the first call to strstr() + strlen(BEGIN).
This will be efficient because the first pointer returned from strstr() is going to be the beginning of BEGIN, therefore you won't be looking through the whole string again but start at the BEGIN-ing and look for the END from there; which means that at the most you run through the whole string once.
I hope this will help
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strpos(char *haystack, char *needle, int offset);
int main()
{
char *p = "Hello there all y'al, hope that you are all well";
int pos = strpos(p, "all", 0);
printf("First all at : %d\n", pos);
pos = strpos(p, "all", 10);
printf("Second all at : %d\n", pos);
}
int strpos(char *hay, char *needle, int offset)
{
char haystack[strlen(hay)];
strncpy(haystack, hay+offset, strlen(hay)-offset);
char *p = strstr(haystack, needle);
if (p)
return p - haystack+offset;
return -1;
}
I got this code from the internet but I couldnt get the whole code.
for example if(*str) . What does this code mean? and also can a string be returned? I thought that an array in main can be changed
directly in a function but here its been returned..
#include<stdio.h>
#define MAX 100
char* getReverse(char[]);
int main(){
char str[MAX],*rev;
printf("Enter any string: ");
scanf("%s",str);
rev = getReverse(str);
printf("Reversed string is: %s\n\n",rev);
return 0;
}
char* getReverse(char str[]){
static int i=0;
static char rev[MAX];
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
return rev;
}
This is not the clearest example of recursion due to the use of the static variables. Hopefully the code generally seems clear to you, I suspect the part that is confusing to you is the same that was confusing to me at first.
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
So line by line.
if(*str){
If we have not reached the null terminator.
getReverse(str+1);
Call the getReverse function on the next character of the string. It seems pretty straight forward up to here. But it also seems like it may not actually reverse anything because this is the next line
rev[i++] = *str;
We assign index i the character at the beginning of str and increment i but here is the tricky part. i may not be what you think. getReverse gets called before i is incremented. And i is static, so changes will persist between function calls. So, lets say we have a 5 letter word, let say "horse" we will end up with 6 calls on the stack to getReverse. The 6th will not do anything because that is where it finds the null terminator. The trick is that we will then go about resolving the calls in reverse order. First the call where str is pointing to 'e' will resolve and increment i because all the other ones are are still waiting for their calls to getReverse to return. So the last letters are actually the first ones to get added and increment i which is what can be confusing here.
I know it's a little unorthodox and will probably cost me some downvotes, but since it's due in 1 hour and I have no idea where to begin I thought I'd ask you guys.
Basically I'm presented with a string that contains placeholders in + form, for example:
1+2+5
I have to create a function to print out all the possibilities of placing different combinations of any given series of digits. I.e. for the series:
[9,8,6] // string array
The output will be
16265
16285
16295
18265
18285
18295
19265
19285
19295
So for each input I get (number of digits)^(number of placeholders) lines of output.
Digits are 0-9 and the maximum form of the digits string is [0,1,2,3,4,5,6,7,8,9].
The original string can have many placeholders (as you'd expect the output can get VERY lengthly).
I have to do it in C, preferably with no recursion. Again I really appreciate any help, couldn't be more thankful right now.
If you can offer an idea, a simplified way to look at solving this, even in a different language or recursively, it'd still be ok, I could use a general concept and move on from there.
It prints them in different order, but it does not matter. and it's not recursive.
#include <stdlib.h>
#include <stdio.h>
int // 0 if no more.
get_string(char* s, const char* spare_chr, int spare_cnt, int comb_num){
for (; *s; s++){
if (*s != '+') continue;
*s = spare_chr[comb_num % spare_cnt];
comb_num /= spare_cnt;
};
return !comb_num;
};
int main(){
const char* spare_str = "986";
int num = 0;
while (1){
char str[] = "1+2+5";
if (!get_string(str, spare_str, strlen(spare_str), num++))
break; // done
printf("str num %2d: %s\n", num, str);
};
return 0;
};
In order to do the actual replacement, you can use strchr to find the first occurrence of a character and return a char * pointer to it. You can then simply change that pointer's value and bam, you've done a character replacement.
Because strchr searches for the first occurrence (before a null terminator), you can use it repeatedly for every value you want to replace.
The loop's a little trickier, but let's see what you make of this.