This should be very trivial. I was running through a very basic C program for comparing strings:
#include <stdio.h>
int strcmp(char *s, char *t);
int main()
{
printf("Returned: %d\n", strcmp("abc", "adf"));
return 0;
}
int strcmp(char *s, char *t)
{
printf("Blah\n");
while (*s++ == *t++)
{
if (*s == '\0')
return 0;
}
return *s - *t;
}
So I've basically implemented my own version of the strcmp function already present in string.h. When I run the above code, I only see return values of 0, 1, or -1 (at least for my small set of test cases) instead of the actual expected results. Now I do realize that this is because the code doesn't go to my implemented version of strcmp, but instead uses the string.h version of the function, but I'm confused as to why this is the case even when I haven't included the appropriate header file.
Also, seeing how it does use the header file version, shouldn't I be getting a 'multiple implementations' error (or something along those lines) when compiling the code?
You're using gcc, right? gcc implements some functions as built-ins in the compiler and it seems that strcmp is one of those. Try compiling your file with the -fno-builtin switch.
Header files just tell the compiler that certain symbols, macros, and types exist. Including or not including a header file won't have any effect on where functions come from, that's the linker's job. If gcc was pulling strcmp out of libc then you probably would see a warning.
Not as elegant as the earlier answers, another way to get this done
#include <stdio.h>
static int strcmp(char *s, char *t); /* static makes it bind to file local sym */
int main()
{
printf("Returned: %d\n", strcmp("abc", "adf"));
return 0;
}
int strcmp(char *s, char *t)
{
printf("Blah\n");
while (*s++ == *t++)
{
if (*s == '\0')
return 0;
}
return *s - *t;
}
Without knowing what compiler and lib. version you use, all conclusion are only 'possibility'. So the most reasonable thing that stdio.h already includes stdlib.h or string.h
strcmp is the name of a standard library function. As such you are only permitted to declare the function (although you must use a correct declaration); you are not permitted to provide another definition for it. The implementation can assume that whenever you use strcmp you are referring to the standard library function even if you haven't used the correct #include for it.
If you want to provide an alternative strcmp then you should give it an alternative name.
Related
Is this method of copying a string faster than copying each char individually? The idea of this code is that it could (but I am not sure if it is so) be faster to copy 8 bytes at once instead of a single byte. It is very un-safe but it seems to work somehow. Or it's just a bad idea?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* copy_string(char s[])
{
int len=strlen(s);
int i=0;
double *p=(double*)s;
double *copy=(double*)malloc(len+1);
while(i-len>8)
{
*copy=*(p++);
copy++;
i+=8;
}
char *p2=(char*)p;
char *c=(char*)copy;
while(i<len)
{
*c=*(p2++);
c++;
i++;
}
*c='\0';
return copy;
}
int main()
{
char s[]="GOODBYE SAFE WORLD!";
char *c=copy_string(s);
printf("%s",c);
return 0;
}
Tricks like that may be faster under some circumstances on some architectures. Trust your provider of your C library to know about these tricks if they apply.
In your case, your code is simply wrong. Assuming that the condition of the first while loop is fixed, the rules for pointer conversions are violated:
A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined.
On many architectures this will simply result in a "bus error".
To see how these kind of tricks work, check out the sources of your favorite C library and look for their implementation of memcpy and memmove.
I tried to write my own implementation of the strchr() method.
It now looks like this:
char *mystrchr(const char *s, int c) {
while (*s != (char) c) {
if (!*s++) {
return NULL;
}
}
return (char *)s;
}
The last line originally was
return s;
But this didn't work because s is const. I found out that there needs to be this cast (char *), but I honestly don't know what I am doing there :( Can someone explain?
I believe this is actually a flaw in the C Standard's definition of the strchr() function. (I'll be happy to be proven wrong.) (Replying to the comments, it's arguable whether it's really a flaw; IMHO it's still poor design. It can be used safely, but it's too easy to use it unsafely.)
Here's what the C standard says:
char *strchr(const char *s, int c);
The strchr function locates the first occurrence of c
(converted to a char) in the string pointed to by s. The
terminating null character is considered to be part of the string.
Which means that this program:
#include <stdio.h>
#include <string.h>
int main(void) {
const char *s = "hello";
char *p = strchr(s, 'l');
*p = 'L';
return 0;
}
even though it carefully defines the pointer to the string literal as a pointer to const char, has undefined behavior, since it modifies the string literal. gcc, at least, doesn't warn about this, and the program dies with a segmentation fault.
The problem is that strchr() takes a const char* argument, which means it promises not to modify the data that s points to -- but it returns a plain char*, which permits the caller to modify the same data.
Here's another example; it doesn't have undefined behavior, but it quietly modifies a const qualified object without any casts (which, on further thought, I believe has undefined behavior):
#include <stdio.h>
#include <string.h>
int main(void) {
const char s[] = "hello";
char *p = strchr(s, 'l');
*p = 'L';
printf("s = \"%s\"\n", s);
return 0;
}
Which means, I think, (to answer your question) that a C implementation of strchr() has to cast its result to convert it from const char* to char*, or do something equivalent.
This is why C++, in one of the few changes it makes to the C standard library, replaces strchr() with two overloaded functions of the same name:
const char * strchr ( const char * str, int character );
char * strchr ( char * str, int character );
Of course C can't do this.
An alternative would have been to replace strchr by two functions, one taking a const char* and returning a const char*, and another taking a char* and returning a char*. Unlike in C++, the two functions would have to have different names, perhaps strchr and strcchr.
(Historically, const was added to C after strchr() had already been defined. This was probably the only way to keep strchr() without breaking existing code.)
strchr() is not the only C standard library function that has this problem. The list of affected function (I think this list is complete but I don't guarantee it) is:
void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
char *strpbrk(const char *s1, const char *s2);
char *strrchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
(all declared in <string.h>) and:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
(declared in <stdlib.h>). All these functions take a pointer to const data that points to the initial element of an array, and return a non-const pointer to an element of that array.
The practice of returning non-const pointers to const data from non-modifying functions is actually an idiom rather widely used in C language. It is not always pretty, but it is rather well established.
The reationale here is simple: strchr by itself is a non-modifying operation. Yet we need strchr functionality for both constant strings and non-constant strings, which would also propagate the constness of the input to the constness of the output. Neither C not C++ provide any elegant support for this concept, meaning that in both languages you will have to write two virtually identical functions in order to avoid taking any risks with const-correctness.
In C++ you wild be able to use function overloading by declaring two functions with the same name
const char *strchr(const char *s, int c);
char *strchr(char *s, int c);
In C you have no function overloading, so in order to fully enforce const-correctness in this case you would have to provide two functions with different names, something like
const char *strchr_c(const char *s, int c);
char *strchr(char *s, int c);
Although in some cases this might be the right thing to do, it is typically (and rightfully) considered too cumbersome and involving by C standards. You can resolve this situation in a more compact (albeit more risky) way by implementing only one function
char *strchr(const char *s, int c);
which returns non-const pointer into the input string (by using a cast at the exit, exactly as you did it). Note, that this approach does not violate any rules of the language, although it provides the caller with the means to violate them. By casting away the constness of the data this approach simply delegates the responsibility to observe const-correctness from the function itself to the caller. As long as the caller is aware of what's going on and remembers to "play nice", i.e. uses a const-qualified pointer to point to const data, any temporary breaches in the wall of const-correctness created by such function are repaired instantly.
I see this trick as a perfectly acceptable approach to reducing unnecessary code duplication (especially in absence of function overloading). The standard library uses it. You have no reason to avoid it either, assuming you understand what you are doing.
Now, as for your implementation of strchr, it looks weird to me from the stylistic point of view. I would use the cycle header to iterate over the full range we are operating on (the full string), and use the inner if to catch the early termination condition
for (; *s != '\0'; ++s)
if (*s == c)
return (char *) s;
return NULL;
But things like that are always a matter of personal preference. Someone might prefer to just
for (; *s != '\0' && *s != c; ++s)
;
return *s == c ? (char *) s : NULL;
Some might say that modifying function parameter (s) inside the function is a bad practice.
The const keyword means that the parameter cannot be modified.
You couldn't return s directly because s is declared as const char *s and the return type of the function is char *. If the compiler allowed you to do that, it would be possible to override the const restriction.
Adding a explicit cast to char* tells the compiler that you know what you're doing (though as Eric explained, it would be better if you didn't do it).
UPDATE: For the sake of context I'm quoting Eric's answer, since he seems to have deleted it:
You should not be modifying s since it is a const char *.
Instead, define a local variable that represents the result of type char * and use that in place of s in the method body.
The Function Return Value should be a Constant Pointer to a Character:
strchr accepts a const char* and should return const char* also. You are returning a non constant which is potentially dangerous since the return value points into the input character array (the caller might be expecting the constant argument to remain constant, but it is modifiable if any part of it is returned as as a char * pointer).
The Function return Value should be NULL if No matching Character is Found:
Also strchr is supposed to return NULL if the sought character is not found. If it returns non-NULL when the character is not found, or s in this case, the caller (if he thinks the behavior is the same as strchr)
might assume that the first character in the result actually matches (without the NULL return value
there is no way to tell whether there was a match or not).
(I'm not sure if that is what you intended to do.)
Here is an Example of a Function that Does This:
I wrote and ran several tests on this function; I added a few really obvious sanity checks to avoid potential crashes:
const char *mystrchr1(const char *s, int c) {
if (s == NULL) {
return NULL;
}
if ((c > 255) || (c < 0)) {
return NULL;
}
int s_len;
int i;
s_len = strlen(s);
for (i = 0; i < s_len; i++) {
if ((char) c == s[i]) {
return (const char*) &s[i];
}
}
return NULL;
}
You're no doubt seeing compiler errors anytime you write code that tries to use the char* result of mystrchr to modify the string literal being passed to mystrchr.
Modifying string literals is a security no-no, because it can lead to abnormal program termination and possibly denial-of-service attacks. Compilers may warn you when you pass a string literal to a function taking char*, but they aren't required to.
How do you use strchr correctly? Let's look at an example.
This is an example of what not to do:
#include <stdio.h>
#include <string.h>
/** Truncate a null-terminated string $str starting at the first occurence
* of a character $c. Return the string after truncating it.
*/
const char* trunc(const char* str, char c){
char* pc = strchr(str, c);
if(pc && *pc && *(pc+1)) *(pc+1)=0;
return str;
}
See how it modifies the string literal str via the pointer pc? That's no bueno.
Here's the right way to do it:
#include <stdio.h>
#include <string.h>
/** Truncate a null-terminated string $str of $sz bytes starting at the first
* occurrence of a character $c. Write the truncated string to the output buffer
* $out.
*/
char* trunc(size_t sz, const char* str, char c, char* out){
char* c_pos = strchr(str, c);
if(c_pos){
ptrdiff_t c_idx = c_pos - str;
if((size_t)n < sz){
memcpy(out, str, c_idx); // copy out all chars before c
out[c_idx]=0; // terminate with null byte
}
}
return 0; // strchr couldn't find c, or had serious problems
}
See how the pointer returned by strchr is used to compute the index of the matching character in the string? The index (also equal to the length up to that point, minus one) is then used to copy the desired part of the string to the output buffer.
You might think "Aw, that's dumb! I don't want to use strchr if it's just going to make me memcpy." If that's how you feel, I've never run into a use case of strchr, strrchr, etc. that I couldn't get away with using a while loop and isspace, isalnum, etc. Sometimes it's actually cleaner than using strchr correctly.
In function main() {...}
1) #include header file string.h
2) I prototype my own file, call it strcpy:
**char *strcpy(char *strSource , const char *dest);**
3) I also wish to use the "real" strlen function in string.h in main().
4) In another compilation file I have my version of strcpy.
Question: How can I get the linker to choose my version of strcpy instead of the prototype in string.h?
enter code here
#include <conio.h>
#include <string.h>
char *strcpy(char *source , const char *dest);
void main()
{
char *s, *d;
strcpy(s,d);
getch();
}
#include <stdio.h>
char *strcpy(char *strDestination, const char *strSource)
{
char *ptr;
printf("made it!");
return ptr;
}
You can't do that in C. That's one of the reasons why C++ introduces namespaces.
The only thing you can do is use a non-conflicting name for your own functions.
This is not a standard thing to do, and I'm pretty sure that if you can do it at all, you will have to read the manual for your linker. And if you try to port this, you will need to read the manual for each linker for each platform to which you try to port this.
The more usual way to do things is to write your own functions with your own names. If you need to hook functionality in a standard library, you would get the source for that library and build your own version.
It has been a while since I looked at C (still learning) and I just got back into the K&R book.
I just had a go to Exercise 5-3 (p107).
Write a pointer version of the function strcat that we showed in Chapter 2: strcat(s,t) copies the string t to the end of s.
I came up with this...
void strcat(char *s, char *t);
void strcat(char *s, char *t) {
while (*s++ != '\0');
s--;
while (*t != '\0') {
*s++ = *t++;
}
*--t = '\0';
}
int main() {
char str[] = "Hey, hello";
char str2[] = " are you?";
strcat(str, str2);
printf("%s\n", str);
return 0;
}
It seems to work.
What I am wondering, is that the K&R book often writes exercises with as little lines as possible - I'd expect had they provided their own code sample for above, you'd get things like this...
void strcat(char *s, char *t) {
while (*s++ != '\0');
s--;
while ((*s++ = *t++) != '\0');
*--t = '\0';
}
To me, this is less readable (maybe this example isn't as good, but I often look at their code and think if that was separated into a few lines, I'd understand it much better). The examples provided in the book seem to advocate this sort of assignment in the condition part of a loop, and in fact cramming as much code as possible per line.
Is the book right in trying to do as much possible where you can, even if readability suffers?
Is this just The C Way?
K&R explain the importance of idioms in the book. Yes, brevity of code is valued by C programmers, but it's not deliberately terse to punish beginners. After some time reading and writing C you start to recognize patterns, so when you see them in someone else's code you know what you're looking at.
Go through the iterations of strcpy() given as an example in K&R -- they explain their philosophy of brevity vs. clarity, and talk about idioms.
You should not expect your program to work, since you are invoking undefined behavior.
You define two buffers of a certain size (str is 11 bytes long, str2 is 10 bytes long). Then, during strcat, you try to write to str[11], which doesn't exist. From this point on there is no guarantee whatsoever about the execution of your program. It may crash, it may do what you expected, or it might just print "42" and make you wonder why.
Furthermore, you should not change *t in strcat, since in newer versions of C t has type const char *.
And third, when re-implementing a function that is also provided by your environment, give it another name. Otherwise your compiler might replace it with some builtin code that is equivalent to the function call. For example GCC has __builtin_strlen which sometimes replaces calls to strlen.
The fixed version of the code looks like this:
#include <stdio.h>
/* renamed strcat to str_cat to avoid confusing the compiler */
void str_cat(char *s, const char *t) { /* added the const qualifier to t */
while (*s++ != '\0');
s--;
while (*t != '\0') {
*s++ = *t++;
}
/* removed the needless modification of *t */
*s = '\0'; /* edit: added this line after the comment from Jonathan Leffler */
}
int main() {
char str[80] = "Hey, hello"; /* note the large array size here */
char str2[] = " are you?";
str_cat(str, str2);
printf("%s\n", str);
return 0;
}
Other more readable, more efficient examples can be found by using Google Codesearch.
Look at the source code for Android and BSD in particular as good examples of more modern C implementation of strcat.
Instead of strcat you should be writing an implementation of strlcat and many examples of that source can be found as well.
I have tried to implement the puts function.It in actual returns a value but i cant get what should it return.please check my code and guide me further
/* implementation of puts function */
#include<stdio.h>
#include<conio.h>
void puts(string)
{
int i;
for(i=0; ;i++)
{
if(string[i]=='\0')
{
printf("\n");
break;
}
printf("%c",string[i]);
}
}
See comments in code.
int puts(const char *string)
{
int i = 0;
while(string[i]) //standard c idiom for looping through a null-terminated string
{
if( putchar(string[i]) == EOF) //if we got the EOF value from writing the char
{
return EOF;
}
i++;
}
if(putchar('\n') == EOF) //this will occur right after we quit due to the null terminated character.
{
return EOF;
}
return 1; //to meet spec.
}
And, as an aside - I've written the equivalent of putc, puts several different times in relation to developing on embedded systems. So it's not always just a learning exercise. :)
Comment on EOF: It is a POSIX constant from stdio.h.
In my Linux stdio.h, I have this definition:
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
That definition code is GPL 2.1.
From the manual page:
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
Return Value
fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
puts() and fputs() return a non-negative number on success, or EOF on error.
Well, stdio's puts() returns a non-negative number on success, or EOF on error.
What's string supposed to be? You should define your function better, try:
void my_puts(const char *string)
instead of
void puts(string)
As noted in the link I included, you need to specify the data type of the argument you're passing (in your example string) and you cannot use the name of a function which has already been defined (i.e. puts ).
In addition to what has already been said, I am personally opposed to redefining standard library functions. However, if you absolutely must (e.g. for a homework assignment), and your compiler is complaining about conflicting types for 'puts', try putting this at the top:
#define puts _puts
#include <conio.h>
#include <stdio.h>
#undef puts
I don't see any point in implementing puts!
anyway, you should read the specs of puts so you can make it.
this may help
int myputs(char* s)
{
int x = printf("%s\n", s);
return (x > 0) ? x : EOF;
}
you should include stdio.h so you can use printf and EOF.
Note that this is not EXACT implementation of puts, because on error puts sets an error indicator and do some other stuff.
More details about puts, here.