I am really new to C.
I want to use the strpos function but it is telling me it doesnt exist?
Here a complete snippet code to solve you problem.
PS: Isn't too late to help. ;)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NOT_FOUND -1
int main (){
int pos = NOT_FOUND;
if ( (pos = strpos( "subsstring", "string")) != NOT_FOUND )
printf("found at %d\n", pos);
else
printf("not found!\n");
return 0;
}
int strpos(const char *haystack, const char *needle)
{
const char *p = strstr(haystack, needle);
if (p)
return p - haystack;
return NOT_FOUND;
}
Edit: Answering Can Vural question:
No. I really think that it would be as it is. At structured programming paradigm, it's a common practice to use the scope structure as first parameter on every function that belongs to the structure's scope itself. The strstr function defined at string.h follow the same approach.
On OOP you have haystack.indexOf( needle ). At structured programming, you have indexOf( haystack, needle ).
The function you are looking for might be either strstr or strchr. You then need to include string.h. There is no strpos in the POSIX interface.
Yes. It's called strstr, related to strpos like (pseudo-code):
strpos(str, target) {
res = strstr(str, target);
if (res == NULL) return false;
else return res - str;
}
I have written strpos() function from scratch with position feature(Like PHP's strpos() function). Return value will be starting position of searched string. Enjoy! :)
In this example code output will be 12
#include <stdio.h>
#include <string.h>
int strpos(char *haystack, char *needle, int pos);
int main(){
printf("%d",strpos("abcdefabcdefabcdef asdfgavcabcddd","abc",10));
return 0;
}
int strpos(char *haystack, char *needle, int pos){
int i,j,check,result = -1;
int len_needle=strlen(needle);
int len_haystack=strlen(haystack);
i = pos;
if (len_needle>len_haystack || *needle==NULL || i>(len_haystack-1)) return result;
for(;i<len_haystack;i++){
check = 0;
for(j=0;j<len_needle;j++){
if(haystack[i+j]==needle[j]){
check++;
}
}
if(check==len_needle){
result = i;
break;
}
}
return result;
}
This is in response to Miere and Can Vural. I can't add comments yet so will add this as an answer.
Shouldn't it be strpos("string", "substring") – Can Vural
At structured programming, you have indexOf( haystack, needle ). Miere
In your code, you have:
int strpos(char *haystack, char *needle)
but you also have:
(pos = strpos( "subsstring", "string"))
I fully agree with the "int strpos(char *haystack, char *needle)" where the string to be searched comes first and the string to search FOR comes second. But to me, "subsstring" (in the context of "one is a substring and one is a string"), "subsstring" implies that IT is the shorter of the two and that you're trying to find "substring" in "string."
So the one part:
(pos = strpos( "subsstring", "string"))
should be:
(pos = strpos( "string" /*that which is being searched within*/, "substring" /*that which is being searched for in the previous parameter*/))
which would be the same as:
(pos = strpos( "haystack", "needle"))
Edit: One of the C comments above wasn't closed properly due to a typo.
There is no function strpos defined in the Standard C library nor in the POSIX Standard. PHP has a function strpos with this definition:
strpos(string $haystack, string $needle, int $offset = 0): int|false
This function locates a substring needle inside a string haystack and returns the offset from the beginning of the string haystack.
C has function strstr that can be used for this purpose and returns a pointer to the substring or NULL if no match is found:
char *strstr(const char *haystack, const char *needle);
Here is an implementation for a C equivalent of strpos relying on strstr for the dirty work. Note however that the name strpos is reserved for future functions in <string.h>:
#include <string.h>
int strpos(const char *haystack, const char *needle, int offset) {
char *p;
size_t len, pos;
len = strlen(haystack);
pos = 0;
if (offset < 0) {
if (len > INT_MAX || offset < -(int)len)
pos = len + offset;
} else {
if (len <= INT_MAX && offset > len)
return NULL;
pos = offset;
}
p = strstr(haystack + pos, needle);
if (p != NULL && p - haystack <= INT_MAX)
return (int)(p - haystack);
else
return -1;
}
Related
I would like not just to know if the substring exists in a buffer, but to get the position it ends. I am doing a ftp and it will look for #filestart; to start copying the file and only will return the file when it finds #fileend;
I will send the first message with something like that: #filestart;len=50;
The first part is easy, cause I can use the strstr to find #filestart. But after that I would like to know the end of len, so I can "run" into the buffer, from that position forward until find the equal sign and start copying the lenght until the char ";" or '\0" be found. Sorry for my crap english, I am from Brasil and don't know that good english but I hope you all understand. I made a function to do that, but I would like to know if isn't there a standard one. Here is mine:
#define unsigned int B32U
#define char B8
B32U strsub(B8 *data, B8 *key) {
if (data && key) {
B8 *d = data;
B32U len = strlen(key), p = 0;
if (len > strlen(d))
return (0);
while (*d != '\0') {
if (*(d + len) != '\0') {
B32U x = 0;
while (x < len) {
if (key[x] == *d) {
*d++;
p++;
} else
break;
x++;
}
if (x == len)
return (p);
} else {
if (len == 1)
if (*d == key[0])
return (p);
B32 x = 0;
while (x < len) {
if (key[x] == *d) {
*d++;
p++;
} else
return (0);
x++;
}
return (p);
}
p++;
*d++;
}
}
return (0);
}
These defines are really problematic and the code does not compile:
#define unsigned int B32U
#define char B8
With the above definition, you do not define B32U as a preprocessor macro, but unsigned and it will expand to int B32U, not what you intended.
You should instead use typedef to define these types:
typedef unsigned int B32U;
typedef char B8;
Or not define these types at all and use standard types.
You can use strstr to write a simple function that returns a pointer to the end of the match or NULL is no match was found:
#include <string.h>
char *strstr_end(const char *s1, const char *s2) {
char *p = strstr(s1, s2);
if (p)
p += strlen(s2);
return p;
}
If you insist on returning the offset from the beginning of the string, you could return a signed type with value -1 if there is no match and the offset of the end if there is a match. ptrdiff_t is an good type for this:
#include <stddef.h>
#include <string.h>
ptrdiff_t strstr_endpos(const char *s1, const char *s2) {
char *p = strstr(s1, s2);
if (p)
return p - s1 + strlen(s2);
else
return -1;
}
To solve your problem you can use :
char *strrchr(const char *str, int c)
This function (which is in string.h) will return the adress of the last occurrence of the character c (';' or '\0' in your case) in the string str. However you only can find a char, not a string.
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;
}
Folks, need to search through a character array and replace any occurrence of '+','/',or'=' with '%2B','%2F', and '%2F' respectively
base64output variable looks like
FtCPpza+Z0FASDFvfgtoCZg5zRI=
code
char *signature = replace_char(base64output, "+", "%2B");
signature = replace_char(signature, "/", "%2F");
signature = replace_char(signature, "=", "%3B");
char replace_char (char *s, char find, char replace) {
while (*s != 0) {
if (*s == find)
*s = replace;
s++;
}
return s;
}
(Errors out with)
s.c:266: warning: initialization makes pointer from integer without a cast
What am i doing wrong? Thanks!
If the issue is that you have garbage in your signature variable:
void replace_char(...) is incompatible with signature = replace_char(...)
Edit:
Oh I didn't see... This is not going to work since you're trying to replace a char by an array of chars with no memory allocation whatsoever.
You need to allocate a new memory chunk (malloc) big enough to hold the new string, then copy the source 's' to the destination, replacing 'c' by 'replace' when needed.
The prototype should be:
char *replace_char(char *s, char c, char *replace);
1.
for char use '' single quotes
for char* use "" double quotes
2.
The function does include the return keyword, therefore it does not return what you'd expect
3.
These webpages have examples on string replacement
http://www.cplusplus.com/reference/cstring/strstr/
What is the function to replace string in C?
You could go for some length discussing various ways to do this.
Replacing a single char is simple - loop through, if match, replace old with new, etc.
The problem here is that the length of the "new" part is longer than the length of the old one.
One way would be to determine the length of the new string (by counting chars), and either (1) try to do it in place, or (2) allocate a new string.
Here's an idea for #1:
int replace(char *buffer, size_t size, char old, const char *newstring)
{
size_t newlen = strlen(newstring);
char *p, *q;
size_t targetlen = 0;
// First get the final length
//
p = buffer;
while (*p)
{
if (*p == old)
targetlen += newlen;
else
targetlen++;
++p;
}
// Account for null terminator
//
targetlen++;
// Make sure there's enough space
//
if (targetlen > size)
return -1;
// Now we copy characters. We'll start at the end and
// work our way backwards.
//
p = buffer + strlen(buffer);
q = buffer + targetlen;
while (targetlen)
{
if (*p == old)
{
q -= newlen;
memcpy(q, newstring, newlen);
targetlen -= newlen;
--p;
}
else
{
*--q = *p--;
--targetlen;
}
}
return 0;
}
Then you could use it this way (here's a quick test I did):
char buf[4096] = "hello world";
if (replace(buf, sizeof(buf), 'o', "oooo"))
{
fprintf(stderr, "Not enough space\n");
}
else
{
puts(buf);
}
your replace_char signature returns void
void replace_char (char *s, char find, char replace)
But, when the linker tries to resolve the following
signature = replace_char(signature, "=", '%3B');
It doesn't find any function that's called replace_char and returns int (int is the default if there's no prototype).
Change the replace_char function prototype to match the statement.
EDIT:
The warning states that your function returns char, but you use it as a char *
also, your function doesn't return anything, do you need to return something ?
It looks like you don't really understand the code that you're working with.
Fixing errors and warnings without understanding exactly what you need to do is worthless..
fix like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *replace_char (char *str, char find, char *replace) {
char *ret=str;
char *wk, *s;
wk = s = strdup(str);
while (*s != 0) {
if (*s == find){
while(*replace)
*str++ = *replace++;
++s;
} else
*str++ = *s++;
}
*str = '\0';
free(wk);
return ret;
}
int main(void){
char base64output[4096] = "FtCPpza+Z0FASDFvfgtoCZg5zRI=";
char *signature = replace_char(base64output, '+', "%2B");
signature = replace_char(signature, '/', "%2F");
signature = replace_char(signature, '=', "%3B");
printf("%s\n", base64output);
return 0;
}
below is a code that ACTUALLY WORKS !!!!
Ammar Hourani
char * replace_char(char * input, char find, char replace)
{
char * output = (char*)malloc(strlen(input));
for (int i = 0; i < strlen(input); i++)
{
if (input[i] == find) output[i] = replace;
else output[i] = input[i];
}
output[strlen(input)] = '\0';
return output;
}
I know C is purposefully bare-bones, but I'm curious as to why something as commonplace as a substring function is not included in <string.h>.
Is it that there is not one "right enough" way to do it? Too many domain specific requirements? Can anyone shed any light?
BTW, this is the substring function I came up with after a bit of research.
Edit: I made a few updates based on comments.
void substr (char *outStr, const char *inpStr, int startPos, size_t strLen) {
/* Cannot do anything with NULL. */
if (inpStr == NULL || outStr == NULL) return;
size_t len = strlen (inpStr);
/* All negative positions to go from end, and cannot
start before start of string, force to start. */
if (startPos < 0) {
startPos = len + startPos;
}
if (startPos < 0) {
startPos = 0;
}
/* Force negative lengths to zero and cannot
start after end of string, force to end. */
if ((size_t)startPos > len) {
startPos = len;
}
len = strlen (&inpStr[startPos]);
/* Adjust length if source string too short. */
if (strLen > len) {
strLen = len;
}
/* Copy string section */
memcpy(outStr, inpStr+startPos, strLen);
outStr[strLen] = '\0';
}
Edit: Based on a comment from r I also came up with this one liner. You're on your own for checks though!
#define substr(dest, src, startPos, strLen) snprintf(dest, BUFF_SIZE, "%.*s", strLen, src+startPos)
Basic standard library functions don't burden themselves with excessive expensive safety checks, leaving them to the user. Most of the safety checks you carry out in your implementation are of expensive kind: totally unacceptable in such a basic library function. This is C, not Java.
Once you get some checks out of the picture, the "substrung" function boils down to ordinary strlcpy. I.e ignoring the safety check on startPos, all you need to do is
char *substr(const char *inpStr, char *outStr, size_t startPos, size_t strLen) {
strlcpy(outStr, inpStr + startPos, strLen);
return outStr;
}
While strlcpy is not a part of the standard library, but it can be crudely replaced by a [misused] strncpy. Again, ignoring the safety check on startPos, all you need to do is
char *substr(const char *inpStr, char *outStr, size_t startPos, size_t strLen) {
strncpy(outStr, inpStr + startPos, strLen);
outStr[strLen] = '\0';
return outStr;
}
Ironically, in your code strncpy is misused in the very same way. On top of that, many of your safety checks are the direct consequence of your choosing a signed type (int) to represent indices, while proper type would be an unsigned one (size_t).
Perhaps because it's a one-liner:
snprintf(dest, dest_size, "%.*s", sub_len, src+sub_start);
You DO have strcpy and strncpy. Aren't enough for you? With strcpy you can simulate the substring from character to end, with strncpy you can simulate the substring from character for a number of characters (you only need to remember to add the \0 at the end of the string). strncpy is even better than the C# equivalent, because you can overshoot the length of the substring and it won't throw an error (if you have allocated enough space in dest, you can do strncpy(dest, src, 1000) even if src is long 1. In C# you can't.)
As written in the comment, you can even use memcpy, but remember to always add a \0 at the end of the string, and you must know how many characters you are copying (so you must know exactly the length of the src substring) AND it's a little more complex to use if a day you want to refactor your code to use wchar_t AND it's not type-safe (because it accepts void* instead of char*). All this in exchange for a little more speed over strncpy
In C you have a function that returns a subset of symbols from a string via pointers: strstr.
char *ptr;
char string1[] = "Hello World";
char string2[] = "World";
ptr = strstr(string1, string2)
*ptr will be pointing to the first character occurrence.
BTW you did not write a function but a procedure, ANSI string functions: string.h
Here's a lighter weight version of what you want. Avoids the redundant strlen calls and guarantees null termination on the destination buffer (something strncpy won't do).
void substr(char* pszSrc, int start, int N, char* pszDst, int lenDest)
{
const char* psz = pszSrc + start;
int x = 0;
while ((x < N) && (x < lenDest))
{
char ch = psz[x];
pszDst[x] = ch;
x++;
if (ch == '\0')
{
return;
}
}
// guarantee null termination
if (x > 0)
{
pszDest[x-1] = 0;
}
}
Example:
char *pszLongString = "This is a long string";
char szSub[10];
substr(pszLongString, 0, 4, szSub, 10); // copies "long" into szSub and includes the null char
So while there isn't a formal substring function in C, C++ string classes usually have such a method:
#include <string>
...
std::string str;
std::string strSub;
str = "This is a long string";
strSub = str.substr(10, 4); // "long"
printf("%s\n", strSub.c_str());
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* substr(const char *string, size_t from, size_t to);
int main(int argc, char *argv[])
{
char *string = argv[1];
const char *substring = substr(string,6,80);
printf("string is [%s] substring is [%s]\n",string,substring);
return 0;
}
const char* substr(const char *string, size_t from, size_t to)
{
if (to <= from)
return NULL;
if (from >= to)
return NULL;
if (string == NULL)
return NULL;
if (strlen(string) == 0)
return NULL;
if (from < 0)
from = 0;
if (to > strlen(string))
to = strlen(string);
char *substring = malloc(sizeof(char) * ((to-from)+1));
size_t index;
for (index = 0; from < to; from++, index++)
substring[index] = string[from];
substring[index] = '\0';
return substring;
}
Is there a C library function that will return the index of a character in a string?
So far, all I've found are functions like strstr that will return the found char *, not it's location in the original string.
strstr returns a pointer to the found character, so you could use pointer arithmetic: (Note: this code not tested for its ability to compile, it's one step away from pseudocode.)
char * source = "test string"; /* assume source address is */
/* 0x10 for example */
char * found = strstr( source, "in" ); /* should return 0x18 */
if (found != NULL) /* strstr returns NULL if item not found */
{
int index = found - source; /* index is 8 */
/* source[8] gets you "i" */
}
I think that
size_t strcspn ( const char * str1, const char * str2 );
is what you want. Here is an example pulled from here:
/* strcspn example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "fcba73";
char keys[] = "1234567890";
int i;
i = strcspn (str,keys);
printf ("The first number in str is at position %d.\n",i+1);
return 0;
}
EDIT: strchr is better only for one char.
Pointer aritmetics says "Hellow!":
char *pos = strchr (myString, '#');
int pos = pos ? pos - myString : -1;
Important: strchr () returns NULL if no string is found
You can use strstr to accomplish what you want. Example:
char *a = "Hello World!";
char *b = strstr(a, "World");
int position = b - a;
printf("the offset is %i\n", position);
This produces the result:
the offset is 6
If you are not totally tied to pure C and can use string.h there is strchr()
See here
Write your own :)
Code from a BSD licensed string processing library for C, called zString
https://github.com/fnoyanisi/zString
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
You can write
s="bvbrburbhlkvp";
int index=strstr(&s,"h")-&s;
to find the index of 'h' in the given garble.