With the following C-function, I want to retrieve the letter at index idx from some string:
char get_letter(char *str, int idx)
{
return *(str + idx);
}
For example, the following:
char s[] = "Barack";
get_letter(s,2);
should return the letter 'r'.
Here is the whole program (name of the executable file is "retrieve"):
int printf(const char * restrict, ...);
char get_letter(char *, int);
int main(int carg, const char **varg){
if (carg != 2) return -1;
printf("%s", get_letter(varg[1],1));
return 0;
}
char get_letter(char *str, int idx)
{
return *(str + idx);
}
when I run the program (e.g.: ./retrieve test), instead of getting the letter "e", I get an error message ("Segmentation fault: 11").
What is going wrong here?
The possible print a character in C language as follows:
char c = 'j';
printf("%c",j);
Working code:
#include <stdio.h>
#include <stdlib.h>
char get_letter(char *str, int idx)
{
return *(str + idx);
}
int main()
{
char s[] = "Barack";
printf("%c", get_letter(s,2));
return 0;
}
I got it ... it has to be %c instead of %s in the print function.
You are returning a char* but your return type is char.
Change your return statement to return str[idx];
Also why you need a function for that? you can just write s[idx]. I am curious about the reason.
Related
Write function that gets a string s and char c that checks whether the char shows in s, if yes return a pointer to the first place that c shows in s
Here is my code. I am not sure what I did about "return the pointer", is this correct?:
#include <stdio.h>
char *foo(char s[], char c)
{
int i;
char *ptr;
for(i=0;s[i];i++)
{
if(s[i]==c)
{
printf("result: %d",i);
*ptr=i;
return ptr;
}
}
}
void main()
{
char s[]="Error404";// some string
char c='r';// some char
foo(s,c);
}
First of all, your specification is unclear. Before you start coding, make sure that the specification makes sense. It doesn't say what to do if you don't find the character, so you can't write this function before you know that.
Your function must always return something, even if the character was not found. A common way to implement this would be to return a null pointer in that case.
Your pointer should point at the found character, not at i which is an integer, that doesn't make any sense.
Correct the code into something like this:
char* foo (char s[], char c)
{
char *ptr = NULL;
for(int i=0; s[i]!='\0'; i++)
{
if(s[i]==c)
{
ptr = &s[i]; // point at the address of item number i in s
break;
}
}
return ptr; // will return NULL if not found, otherwise a pointer to the found item
}
If s is a string, then s[i] represents the ith char in the string, while s + i represents a pointer to the ith char in the string. So you want to return s + i. You probably also want to return NULL if the char is not found.
#include <stdio.h>
char *foo(char s[], char c)
{
int i;
for(i = 0; s[i]; i++)
{
if(s[i] == c)
return (s + i);
}
return (NULL);
}
We're supposed to write a function that will return the address of the first occurrence of ch in string str. I wrote the below code, which runs and seems to return numbers that could be correct (I called the function 5 times for the 5 characters in a string and the return values were separated by 1 byte.) However, the ampersand in the return statement is underlined in red with the hover-over text, "Return value type does not match the function type." I don't understand how the code builds and runs if there is an error.
#include <stdio.h>
#include <string.h>
int mystrchr (char *str, char ch){
int i;
for(i=0;i<strlen(str);i++){
if(str[i]==ch)
{
//printf("%c\n",str[i]);
return &str[i];
}
}
}
Let me tell you the reason:
From you defined funtion int mystrchr (char *str, char ch){}, the return type is int, but the real value is &str[i];, the type is char * in your code.
so there is a warning..
char* mystrchr (char *str, char ch){
int i;
for(i=0;i<strlen(str);i++){
if(str[i]==ch)
{
break;
}
}
return &str[i];
}
I agree with others.
I have created a function for strend, which basically returns 1 if string t is present at the end of string s, however it never returns 1:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int strend(char *s, char *t) {
int p;
for (p = 0; p < strlen(s) - strlen(t); p++) {
*s++;
}
printf("%s\n%s\n", s, t);
if (s == t)
return 1;
return 0;
}
int main(void) {
int bool = strend("Hello", "ello");
printf("%i\n", bool);
return 0;
}
This gives me an output of:
ello
ello
0
So technically I should get 1. I assume the comparison using pointers is not used in this way?
You need to review your basic knowledge of C strings. There are lots of standard string functions in string.h that can help you with this test.
The basic problem is that the test s == t is valid, but you are comparing memory addresses here. You can see that is valid if you change the strings to test to
char test[] = "Hello";
int bool = strend_(test, test+1);
where test obviously is the same as your "Hello", and similarly, test+1 is the same as "ello" (try it by printing them). This correctly returns 1 with your routine.
In addition, I get two warnings:
on *s++; "warning: expression result unused [-Wunused-value]": you increment s but also ask what character is at that position through *s; and you don't use that information.
Fix by removing the * there.
on p < strlen(s) ..; "warning: comparison of integers of different signs: 'int' and 'unsigned long'", because strlen does not return a signed integer but an unsigned one (apparently, my header uses unsigned long).
Fix by declaring p as unsigned long, or even better, size_t.
Your entire routine can be condensed to a simple
int strend (char *s, char *t)
{
if (strlen(s) >= strlen(t) && !strcmp (s+strlen(s)-strlen(t),t))
return 1;
return 0;
}
It's not worth the trouble to cache the result of those four strlen calls into 2 temporary variables; a good compiler will work it out and do that for you. (A quick glance to the assembly output of the compiler I'm using – clang – shows it does, even with the default optimization settings.)
A slightly modified test, based on #M.M.'s comment:
int strend (char *s, char *t)
{
if (strlen(s) < strlen(t)) return 0;
return !strcmp (s+strlen(s)-strlen(t),t);
}
but attempting to optimize it this way is not as easy parsed as the routine above, and its assembly is ever so slightly "wordy" as well. Personally, I'd go for the more humanly readable version.
Use strcmp(3)
if (strcmp(s, t) == 0) return 1;
This actually compares the contents of the memory pointed to by s and t rather than their addresses.
Your code is broken in multiple ways:
The initial loop is a very cumbersome way to advance p by the difference of lengths if positive.
Once you have pointers at the same distance from the end of both strings, You should compare the characters with strcmp() (or memcmp() if you can first exclude the case of strlen(s) < strlen(t).
Comparing the pointers obtained after the loop will only work if t points inside the string pointed to by s, a special case that may or may not be produced by the compiler for the specific call in main: strend("Hello", "ello");.
Here is a modified version:
#include <string.h>
int strend(const char *str1, const char *str2) {
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
return len1 >= len2 && !memcmp(str1 + len1 - len2, str2, len2);
}
I corrected/modified your code, here is the code,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#pragma warning(disable:4996)
int strend(char *s, char *t)
{
int p,flag=0,count=0;//count will be the starting index for *t
p = strlen(s) - strlen(t);//this will be the starting index for *s
while(count<strlen(t))
{
if (*(s+p) == *(t+count))
{
flag = 1;
count++;
p++;
continue;
}
else
{
flag = 0;
break;
}
}
return flag;
}
int main(void)
{
int flag = strend("Hello", "ello");
printf("%i\n", flag);
return 0;
}
This code works too.
#include <stdio.h>
#include <string.h>
int strend (char *s1, char *s2);
void main ()
{
char str1[20] = "somethings";
char str2[20] = "things";
int f;
f = strend (str1,str2);
if (f==1)
printf ("1");
else
printf ("0");
}
int strend (char *str1, char *str2)
{
int l = strlen(str1) - strlen(str2);
str1 = str1 + l;
int d = strcmp(str1,str2);
if (d == 0)
return 1;
else
return 0;
}
this code works well.
int strend(char *s, char *t){
while(*t & *s){
if(*t == *s){
t++;
}
s++;
}
return *t==*s;
}
I had problem while using a function to do the task.Do I need to pass a pointer to character as well to do the task.I used the following code
#include <stdio.h>
char* change(char c)
{
char s[2];
s[0]=c;
s[1]='\0';
return s;
}
int main()
{
char t='o';
char* kk;
kk=change(t);
printf("\n%s",kk);
return 0;
}
Thanks
You cannot return a pointer to a local variable from a function without making a copy. Two ways of doing what you need in C are
Asking the caller to provide a buffer for writing the string, and returning the length, and
Allocating the return value dynamically with malloc or an equivalent, and requiring the caller to free the resultant string.
Here is the first approach:
int change(char c, char* res, int len) {
if (len < 2) return -1; // Invalid parameters
res[0]=c;
res[1]='\0';
return 1;
}
Here is the second approach:
char* change(char c) {
char *res = malloc(2);
res[0]=c;
res[1]='\0';
return res;
}
#include <stdio.h>
#include <stdlib.h>
char* change1(char c){
static char s[2];
s[0]=c;
return s;
}
char* change2(char c){
char *s = malloc(2);
s[0]=c;
s[1]='\0';
return s;
}
char* change3(char c, char *s){
s[0]=c;
s[1]='\0';
return s;
}
int main() {
char t='o';
char* kk;
kk=change1(t);
printf("%s\n", kk);
kk=change2(t);
printf("%s\n", kk);
free(kk);
char s[2];
kk = change3(t, s);
printf("%s\n", kk);
return 0;
}
You can just change
char s[2];
to
char *s; s = malloc(2);
and your program should work fine.
I'm trying very hard to figure out a way to parse a string and "highlight" the search term in the result by making it uppercase.
I've tried using strstr and moving a pointer along and "toupper"ing the characters, to no avail.
char * highlight( char *str, char *searchstr ) {
char *pnt=str;
int i;
pnt=strstr(str,searchstr);
while(pnt){
printf("ststr retured: %s\n", pnt);
for(i=0;i<strlen(searchstr);i++) {
printf("%c",toupper(pnt[i]));
}
printf("\n");
pnt=pnt+strlen(searchstr);
pnt=strstr(pnt,searchstr);
}
return str;
}
Any advice is greatly appreciated.
Since Schot mentioned every occurrence:
#include <string.h>
char *highlight(char *str, char *searchstr) {
char *pnt = str;
while (pnt = strstr(pnt, searchstr)) {
char *tmp = searchstr;
while(*(tmp++)) { *pnt = toupper(*pnt); pnt++; }
}
return str;
}
int main() {
char s[] = "hello world follow llollo";
char search[] = "llo";
puts(highlight(s, search));
return 0;
}
output is:
$ ./a.out
heLLO world foLLOw LLOLLO
You appreciate that the function takes the string as an argument and then returns that same string, while having -not- modified that string? all the function does is print to stdout the capital characters.
At some point, you would need to change the string itself, e.g.;
pnt[i] = toupper( pnt[i] );
Like Blank Xavier said, you probably want to modify the actual string. toupper does not change the value of the character you supply, but returns a new character that is its uppercase version. You have to explicitly assign it back to the original string.
Some additional tips:
Never do multiple strlen calls on a string that doesn't change, do it once and store the result.
You can express the promise of not changing searchstr by declaring it as const char *.
Below is an example with a (in my opinion) easy method of looping through all strstr matches:
#include <string.h>
#include <ctype.h>
char *highlight(char *s, const char *t)
{
char *p;
size_t i, len = strlen(t);
for (p = s; (p = strstr(p, t)); p += len)
for (i = 0; i < len; i++)
p[i] = toupper(p[i]);
return s;
}