Why a string is not nulled terminated when passing in a function? - c

This is my call:
testFunc(0,0,"+++++A+++b+c++++d+e++++f+g+++++h+i","Abcdefghi");
To the function:
void testFunc(int isRight, int step, const char* str1, const char* str2)
{
static int testNum = 1;
printf("test%d: %d\n", testNum++, extendedSubStr(isRight, step, str1, str2));
}
That calls:
int extendedSubStr(int isRight, int gap, const char* str1, const char* str2)
{
// find location of the first char
char * pch;
char * firstOcur;
pch=strchr(str1,str2[0]);
firstOcur = pch;
int i=0;
while (pch!=NULL)
{
i++;
// find next char from the remaining string
pch=strchr(pch+1,str2[i]);
}
if(i==strlen(str2))
{
// return position of the first char
return firstOcur-str1;
}
}
My problem starts when i try to iterate through str1 using strchr() which expects a null terminated string. It keeps looping for some reason. I would prefer not to use memchr().
Why str1 and str2 aren't nulled terminated? How can i terminate them?

The two strings are definitely null terminated. What happens is that your code iterates past the null terminators.
You need to stop iterating when str2[i] reaches \0:
int i = 1;
while (pch != NULL && str2[i] != 0)
{
pch = strchr(pch + 1, str2[i++]);
}
From the strchr manpage:
The terminating null character is considered to be part of the string; therefore if c is \0,
the functions locate the terminating \0.
Basically, what happens is that once you reach the null character in str2, you match the null character in str1. After this, your loop proceed to look for characters that appear past the end of str2 in memory that follows str1. Chaos ensues.

use
while (pch!=NULL && *(pch+1)!='\0' && str2[i]!='\0')
instead of
while (pch!=NULL)

As others already mentioned, C style strings are terminated with '\0'.
You might want to look at strstr(s1, s2). strstr looks for the position of s2 in s1. Since the parameters isRight and gap aren't used, this would simplify extendedSubStr
int extendedSubStr(int isRight, int gap, const char* str1, const char* str2)
{
char *r = strstr(str1, str2);
return r != NULL ? r - str1 : -1;
}

Related

concatinate two String Using pointer in C

I'm trying to concatenate two strings using pointer in C, but it doesn't work 100%. At the end of the output String, many unknown characters appear...
char* concat_string (char* s1, char* s2) {
char *s;
int k=0;
s=(char *)malloc((strlen(s1)+strlen(s2))*sizeof(char));
while (*s1!='\0') {
*(s+k)=*s1;
k++;
s1++;
}
while (*s2!='\0') {
*(s+k)=*s2;
k++;
s2++;
}
return s;
}
int main () {
char *ch1, *ch2, *s;
char cch1[10], cch2[10];
printf("ch1 ? ");
scanf("%s",cch1);
printf("ch2 ? ");
scanf("%s",cch2);
ch1=cch1;
ch2=cch2;
s=concat_string(ch1, ch2);
printf("\n%s + %s = ", ch1, ch2);
while (*s!='\0') {
printf("%c", *s);
s++;
}
}
You're not including space for the terminator in the concatenated result. This:
s=(char *)malloc((strlen(s1)+strlen(s2))*sizeof(char));
should be:
s = malloc(strlen(s1) + strlen(s2) + 1);
You're not copying the terminator either, which explains the result you're seeing.
Also, don't cast malloc()'s return value in C, and make your input strings const.
Your code is very hard to read. The use of an integer indexing variable instead of just using pointers makes it needlessly complicated. For reference, here's how I would write it:
char * concat_string(const char *s1, const char *s2)
{
char *s = malloc(strlen(s1) + strlen(s2) + 1);
if(s != NULL)
{
char *p = s;
while((*p++ = *s1++) != '\0');
--p;
while((*p++ = *s2++) != '\0');
}
return s;
}
This is of course still somewhat terse, but I'd argue it's more readable than your version.
printf expects null terminated strings. Otherwise, it will print whatever characters in memory until it hits one. Your concat_string function doesn't put a null terminator on the string.
char* concat_string (char* s1, char* s2){char *s;int k=0;
s=(char *)malloc((strlen(s1)+strlen(s2))*sizeof(char));
while(*s1!='\0'){*(s+k)=*s1;k++;s1++; }
while(*s2!='\0'){*(s+k)=*s2;k++;s2++;}
*(s+k) = 0;
return s;
}
Also, this function is already written for you, just try using strcat.

Function To Match The Last Character Of A String

So this is a problem : Write the function strend(s,t), which returns 1 if the char t occurs at the end of the string s, and zero otherwise.
This is my code:
int strend(char*, char);
int main()
{
int n = -1;
char str1[6] = "Hello", char1;
printf("Enter a character: ");
char1 = getchar();
n = strend(str1, char1);
printf("n = %d", n);
return 0;
}
int strend(char* str1, char str2)
{
while(*str1 != '\0')
{
str1++;
}
if(*str1 == str2)
{
return 1;
}
else
{
return 0;
}
}
However the character matching does not perform as intended. Where the mistake?
Thanks.
You're comparing the character to the \0 string terminator.
int strend(char* str1, char str2)
{
if (*str1 == '\0') {
return 0;
}
while(*str1 != '\0') /* removed ; that shouldn't be there */
{
str1++;
}
/* at this point, str1 is pointing to the 0-terminator */
str1--; /* pointer now points to last character of the string, not 0-terminator */
if(*str1 == str2)
{
return 1;
}
else
{
return 0;
}
}
I'll try my own explanation.
Suppose your while() loop has reached the last non-zero character of your string str1.
In this case, the line while( *str1 != '\0' ) is "asking" if this character is zero or not.
Since it is the character that you are looking for, logically it cannot be '\0'.
Then the comparison expressión is "true", and the increment str1++; is performed.
Now *str1 is the character '\0', and the immediate next iteration gives "false" when evaluating *str1 != '\0'.
Then the while() block is finished, and the program continues in the line if(*str1 == str2).
Here, the value *str1, which is '\0', is compared against str2, giving always the result "false".
However, the desired character is still in the immediate previous memory position of str1.
So, you can decrement str1 and then comparing, or well you can compare str2 against (str1 - 1).
// Option 1
str1--;
if(*str1 == str2)
//Option 2
if ((str1 - 1) == str2)
Without any error checking, (you can do that) here is a one liner that will check that the last character is matched:
int strend(char* str1, char str2)
{
return ((str1[strlen(str1)-1]) == str2)?(1):(0);
}
Or in a more readable form:
int strend(char* str1, char str2)
{
return ((str1[strlen(str1)-1]) == str2);
}

How to compare two strings in C ignoring the new line character?

I'm studying C programming, I know in C strcmp is used to compare two strings, but the comparing always contains the new line character, I want to ignore it. I know I can remove the new line character and then compare them, but is there any function that ignores the new line character automatically?
This is one of those cases where it's easier to open code the function. I've made it test for equality strictly (i.e. not alphabetise), though that would be a relatively easy change.
Try this, which should actually do what the original questioner asked:
/* Compare two strings s1 and s2, assuming s1 is terminated
* by \n or a NULL, and s2 is terminated by a NULL. A match
* returns 0, a non-match returns 1.
*/
int
strcmpst1nl (const char * s1, const char * s2)
{
char s1c;
do
{
s1c = *s1;
if (s1c == '\n')
s1c = 0;
if (s1c != *s2)
return 1;
s1++;
s2++;
} while (s1c); /* already checked *s2 is equal */
return 0;
}
Interestingly this wasn't particularly elegant to do with a for loop. More elegant answers appreciated.
A more generalised routine to compare two strings where either can be terminated by a \n or a NULL (not quite what you asked) would be:
/* Compare two strings s1 and s2, assuming either is
* terminated by \n or a NULL, A match
* returns 0, a non-match returns 1.
*/
int
strcmpnl (const char *s1, const char *s2)
{
char s1c;
char s2c;
do
{
s1c = *(s1++);
s2c = *(s2++);
if (s1c == '\n')
s1c = 0;
if (s2c == '\n')
s2c = 0;
if (s1c != s2c)
return 1;
}
while (s1c); /* already checked *s2 is equal */
return 0;
}
Another less efficient route (assuming s1 is terminated by \n) would be:
#include <string.h>
#include <strings.h>
int
strcmpst1nl2 (const char *s1, const char *s2)
{
int s1len, s2len;
s1len = strlen (s1);
s2len = strlen (s2);
/* check strings are equal length without \n */
if (s1len - 1 != s2len)
return 1;
/* we know s1len > 0, as s2len would be -1, so this is safe */
if (s1[s1len - 2] != '\n')
return 1;
return bcmp (s1, s2, s1len - 1);
}
You should first write a function that computes the length of the string, in which both the standard termination character and the endline character terminate the string. In doing so, I suggest you both check Line Feed and Carriage Return character (check here)
Then, you check that both strings have same length according to the previous definition.
If yes, you further check the string with strncmp (and using the found length as third parameter).
A function like the following could be used instead of strcmp(). It does the same thing, but ignores one (possible) trailing newline on the second string. It doesn't modify the strings.
int my_cmp(const char *str1, const char *str2)
{
int r,n;
/* Get length of str1, which is also the index of the 1st additional
* char in str2
*/
n = strlen(str1);
/* Compare the first n chars */
r = strncmp(str1,str2,n);
/* If 1st n chars match, make sure next char in str2 is either the null char
* or a newline followed by the null char. Otherwise, return -1 since str2 is
* longer (making str1 "less than" str2)
*/
if ( !r && str2[n] && (str2[n] != '\n' || str2[n+1]) )
return -1;
return r;
}
Here's another one that ignores all newlines anywhere in either string:
int my_cmp(const char *str1, const char *str2)
{
const unsigned char *a, *b;
/* loop over both strings */
for (a = str1, b = str2; ; a++, b++) {
while (*a == '\n') a++; /* skip newlines in str1 */
while (*b == '\n') b++; /* skip newlines in str2 */
/* If we reach the end of either string (or both), one of
* the if's below will terminate the loop */
/* return if we're at end of both strings */
if (!(*a || *b))
return 0;
/* positive return when str1's char is greater than str2's
* (or at end of str2) */
if (*a > *b)
return 1;
/* negative return when str1's char is less than str2's
* (or at end of str1) */
if (*a < *b)
return -1;
}
return 0;
}
Of course, if you just need to ignore a single trailing newline it's easy to strip it off anyway (just locate it and overwrite it with '\0')...

Compare two strings - get right part of the longer one

I have two strings, e.g.:
str1 = "aaabbbcccdddeee"
str2 = "aaabbbccc"
How to do something like str1 - str2 to get the dddeee substring?
If str2 is guaranteed to be a prefix of str1, then this will suffice:
const char *str3 = &str1[strlen(str2)];
which is equivalent to this: (as #James points out in the comments)
const char *str3 = str1 + strlen(str2);
Of course, str3 is just a pointer into one of the original strings. If the contents of the original string changes, then so will your result. So you may want to create a copy, using malloc() and strcpy() (and then free() at some point).
This will skip the common prefix of two strings:
char* suffix(const char* prefix, const char* str) {
while (*prefix && *str && *prefix == *str) {
prefix++;
str++;
}
return str;
}
For example, if you pass "AAB" and "AACC", this would return "CC".
str3 will contain a copy of the prefix:
str1 = "aaabbbcccdddeee"
str2 = "aaabbbccc"
size_t length = strlen1 - strlen2;
char* str3 = calloc(sizeof(char), length + 1);
memcpy(str3, str1+strlen(str2), length);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char a[] = "aaaabbbbbdddeee";
char b[] = "aaaabbbbb";
const char* start = strstr(a, b);
if (start)
{
printf("%s\n", a + strlen(b));
}
return 0;
}
Since you have clarified that str2 is a prefix of str1, you can get the pointer to the extra part in str2 simply with the operation:
str1 + strlen(2);
For example, to print the "dddeee" part of your string:
printf("%s\n", str1 + strlen(str2));
How this works is simple. str1 + strlen(str2) is a pointer that is strlen(str2) N characters away from the beginning of the string pointed to be str1. strlen(str2) returns the number of characters in the second string and you skip those many characters in the first string and reach the extra part.

Is there a function in C to find a substring overlap?

in C, is there a function that when giver two strings, will return the substring overlap or size of the overlap? So like something that does:
char s1[5] = {cart};
char s2[4] = {car};
int overlap;
overlap = get_overlap(s1, s2); /*or have overlap be a string if it returns the overlap*.
and then overlap would be 3.
If not, how do i make one that will return the int value of the overlap.
Use strstr. Example from link:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
strncpy (pch,"sample",6);
puts (str);
return 0;
}
Output:
This is a sample string
Note:
The entire substring will be matched ; note that strstr does not do partial matches.
char *strstr(const char *str1, const char *str2);
The function strstr() finds the
occurrence of str2 in the str1 and
returns the pointer to occurrence of
str2 in str1. If no match found, then
a null pointer is returned.
Qualification: This function computed overlaps of the type
string1
ng1randomcharacters
In this case, the overlap is 3
// Traverses s1 from left to right and s2 from left to right, looking for overlap
int get_overlap(char *s1, char *s2)
{
int u2 = strlen(s2)-1;
int p1 = strlen(s1)-1;
int p2 = 0;
while( p1>=0 && p2<=u2 )
{
if (s1[p1--] != s2[p2++])
{
--p2; // no overlap, so correct for incremented value
break;
}
}
return(p2);
}
There's no builtin function, but it's pretty simple to write:
size_t overlap(const char *s1, const char *s2)
{
size_t i = 0;
while (s1[i] && s2[i] && s1[i] == s2[i])
i++;
return i;
}

Resources