How to define "strchr(s,oldch)" in function definition in c program? - c

I am a beginner to C language. I dont understand the function defintion part. What does "strchr(s,oldch)" do?
I am trying to convert it into ctypes program.
#include <stdio.h>
#include <string.h>
#include <math.h>
/* Replace och with nch in s and return the number of replacements */
extern int replace(char *s, char och, char nch);
/* Replace a character in a string */
int replace(char *s, char oldch, char newch) {
int nrep = 0;
while (s = strchr(s,oldch)) {
*(s++) = newch;
nrep++;
}
return nrep;
}
/* Test the replace() function */
{
char s[] = "Skipping along unaware of the unspeakable peril.";
int nrep;
nrep = replace(s,' ','-');
printf("%d\n", nrep);
printf("%s\n",s);
}
what does while (s = strchr(s,oldch)) mean? what work it does ?
How to write it in other ways?
Can anyone explain it ?

The C library function char strchr(const char *str, int c) searches for the first occurrence of the character c (an unsigned char) in the string pointed to by the argument str.
strchr() function checks whether the original string contains defined characters. If the character is found inside the string, it returns a pointer value; otherwise, it returns a null pointer.
Syntax:
char *strchr(const char *str, int c)
Parameters
str − This is the C string to be scanned.
c − This is the character to be searched in str.
Example.
The following example shows the usage of strchr() function.
#include <stdio.h>
#include <string.h>
int main () {
const char str[] = "www.ted.com";
const char ch = '.';
char *ret;
ret = strchr(str, ch);
printf("String after |%c| is - |%s|\n", ch, ret);
return(0);
}
compile and run the above program that will produce the following result:
String after |.| is - |.ted.com|

The C library function strchr loops through an array of characters and returns the first occurrence of a certain character. In your case, you're looping through an array of characters(string) and replacing oldch with newch, then you're returning the total number of characters replaced in your string:-
/*
Declaring a function called replace that takes as input 3
arguments:-
> a string 's',
> character to be replaced in the string 'och'
> what to replace with 'nch'
*/
extern int replace(char *s, char och, char nch);
int replace(char *s, char oldch, char newch) {
//initialize our counter to keep track of characters replaced
int nrep = 0;
/*
call the function strchr and try to find if the next position of
the character we'd like to replace can be located, i.e. there's
still more old characters left in the string. If this is the
case, replace this character with 'newch' and continue doing this
until no more old characters can be found in the string, at which
point you return total number of old characters replaced (nrep).
*/
while (s = strchr(s,oldch)) {
//replace current oldch with newch and find next oldch
*(s++) = newch;
//increment number of characters replaced
nrep++;
}
return nrep;
}

Related

how to define a pointer in a string and make it as a start point? (based on K&R C exercise 5-4)

I am learning C language based on the book K&R 2nd edition, when tried the exercise 5-4, which ask to write an function (strlen) to check whether a string (char t[]) is in the end of another string (char s[]), my solution in the strlen function is, first find the length difference, and then take this difference as an index or address of the start position in the string s, and check whether the left items are equal in two strings via while loop, the problem happened in the while loop, below is my code:
#include <stdio.h>
#include <string.h>
int strend(char *s, char *t)
int main()
{
char s[] = "abcd";
char t[] = "cd";
printf("%d", strend(s,t));
}
/* if the string t is founded in the end of string s, return 1, otherwise return 0*/
int strend(char *s, char *t)
{
int start;
char *p;
start = strlen(s) - strlen(t); /*get the length difference of two string*/
p = &s[start]; /*set the position of pointer p*/
while (*p++ == *t++)
;
if (*t == '\0' && *p == '\0')
return 1;
else
return 0;
}
I also tried the code in the online process flow (attched picture below), when the program run to the while loop ( while (*p++ == *t++)), the pointer p can not move forward in the string s, could any one kindly please help me to figure out what is wrong? thanks!
enter image description here

sscanf get string until second symbol (include one)

How to get string until second symbol through sscanf?
for example:
char *str = "struct1.struct2.struct3.int";
char buf[256] = {0};
sscanf(str, "", buf); //have any format string could get string until second dot?
sscanf get string until second symbol (include one)
How to get string until second symbol through sscanf?
Not generally possible with a single use of sscanf().
Certainly, without a lot of work, a more involved use of sscanf() will work for many input strings, yet fail for select ones1. sscanf() is not the best fit here for this task.
strchr(), strcspn() better suited.
#include <string.h>
#include<stdlib.h>
// Return offset to 2nd needle occurrence
// or end of string, if not found.
size_t foo(const char *haystack, const char *needle) {
size_t offset = strcspn(haystack, needle);
if (haystack[offset]) {
offset++;
offset += strcspn(haystack + offset, needle);
}
return offset;
}
#include <stdio.h>
int main() {
const char *haystack = "struct1.struct2.struct3.int";
printf("<%.*s>\n", (int) foo(haystack, "."), haystack);
}
Output
<struct1.struct2>
1 Consider: "struct1.struct2", "struct1..", "..struct2", ".struct2.", "..", ".", "".
You can use a * to tell scanf to ignore an element:
const char *str = "struct1.struct2.struct3.int";
int main() {
char buf[256];
int i = sscanf(str, "%*[^.].%[^.]", buf);
printf("%d >%s<\n", i, buf);
return 0;
}
This outputs as expected:
1 >struct2<
because exactly 1 element was assigned even if another one was parsed.

Why isn't this case insensitive version of strstr() function working?

In an effort of solving a textbook problem, I'm trying to create a case insensitive version of the function called strstr() which is in the C language. So far, I've run into two problems. The first problem being that when I make the case insensitive version of strstr() it worked, but it didn't stop at the first matching string and continued to return the string even if they didn't match.
strstr() is supposed to see the first instance of a matching character up to n counts specified and then stop. Like if I wrote: "Xehanort" in string A and "Xemnas" in string B and specified 4, as the number, it would return Xe.
The idea behind the case insensitive version is that I can write : "Xehanort" in one string and "xemnas" in the next string and have it return Xe.
However, I've run into a new problem in new code I've tried: the function doesn't seem to want to run at all. I've tested this and it turns out the function seems to be at a crash and I'm not sure how to make it stop.
I've tried editing the code, I've tried using different for loops but figured that the code doesn't need to be too sophisticated yet, I've also tried different code entirely than what you are going to read, but that resulted in the problem mentioned earlier.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX 100
char *stristr4(const char *p1, const char *p2, size_t num);
int main() {
char c[MAX], d[MAX];
printf("Please enter the string you want to compare.");
gets(c);
printf("Please enter the next string you want to compare.");
gets(d);
printf("The first string to be obtained from \n%s, and \n%s is \n%s",
c, d, stristr4(c, d, MAX));
}
char *stristr4(const char *p1, const char *p2, size_t num) {
const char *str1 = p1;
const char *str2 = p2;
char *str3;
int counter = 0;
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
if (tolower(str1[i]) == tolower(str2[j])) {
str3[i] = str1[i];
counter++;
} else {
if (counter > 0) {
break;
} else
continue;
}
}
}
return str3;
}
The code you see will ask for the strings you want to input. Ideally, it should return the input.
Then it should do the stristr function and return the first instance of matching string with case insensitivity.
However, the function I've created doesn't even seem to run.
Your code has undefined behavior (in this case causing a segmentation fault), because you try to store the resulting string via an uninitialized pointer str3.
Standard function strstr returns a pointer to the matching subsequence, you should do the same. The third argument is useless if the first and second arguments are proper C strings.
Here is a modified version:
char *stristr4(const char *p1, const char *p2) {
for (;; p1++) {
for (size_t i = 0;; i++) {
if (p2[i] == '\0')
return (char *)p1;
if (tolower((unsigned char)p1[i]) != tolower((unsigned char)p2[i]))
break;
}
if (*p1 == '\0')
return NULL;
}
}
Notes:
function tolower() as other functions from <ctype.h> takes an int argument that must have the value of an unsigned char or the special negative value EOF. char arguments must be converted to unsigned char to avoid undefined behavior for negative char values. char can be signed or unsigned by default depending on the platform and the compilers settings.
you should never use gets(). This function is obsolete and cannot be used safely with uncontrolled input. Use fgets() and strip the trailing newline:
if (fgets(c, sizeof c, stdin)) {
c[strcspn(c, "\n")] = '\0'; // strip the trailing newline if any
...
}
A third string could be passed to the function and fill that string with the matching characters.
Use fgets instead of gets.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define MAX 100
int stristr4(const char* p1, const char *p2, char *same);
int main( void)
{
int comp = 0;
char c[MAX] = "", d[MAX] = "", match[MAX] = "";//initialize to all zero
printf ( "Please enter the string you want to compare. ");
fflush ( stdout);//printf has no newline so make sure it prints
fgets ( c, MAX, stdin);
c[strcspn ( c, "\n")] = 0;//remove newline
printf ( "Please enter the next string you want to compare. ");
fflush ( stdout);//printf has no newline so make sure it prints
fgets ( d, MAX, stdin);
d[strcspn ( d, "\n")] = 0;//remove newline
comp = stristr4 ( c, d, match);
printf ( "Comparison of \n%s, and \n%s is \n%d\n", c, d, comp);
if ( *match) {
printf ( "The matching string to be obtained from \n%s, and \n%s is \n%s\n"
, c, d, match);
}
return 0;
}
int stristr4 ( const char *p1,const char *p2, char *same)
{
//pointers not pointing to zero and tolower values are equal
while ( *p1 && *p2 && tolower ( (unsigned char)*p1) == tolower ( (unsigned char)*p2))
{
*same = tolower ( (unsigned char)*p1);//count same characters
same++;//increment to next character
*same = 0;//zero terminate
p1++;
p2++;
}
return *p1 - *p2;//return difference
}

I can't figure out strcpy

This is an unfinished code for converting alphanumeric characters into Morse code. So far only the character "A" is in set. I can't seem to copy the Morse code string of "a" into the variable "c". The compiler tells me that passing argument 1 of strcpy makes pointer from integer without a cast.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(){
char c; /* variable to hold character input by user */
char sentence[ 80 ]; /* create char array */
int i = 0; /* initialize counter i */
const char *a = ".- ";
/* prompt user to enter line of text */
puts( "Enter a line of text:" );
/* use getchar to read each character */
while ( ( c = getchar() ) != '\n') {
c = toupper(c);
switch (c){
case 'A':
strcpy(c, a);
break
}
sentence[ i++ ] = c;
} /* end while */
sentence[ i ] = '\0'; /* terminate string */
/* use puts to display sentence */
puts( "\nThe line entered was:" );
puts( sentence );
return 0;
}
c is a single character, while a is a string (which explains both why c can only hold a single character, and why the compiler is complaining). If you want c to hold a whole string, declare it as such (like you did for sentence).
You've declared the variable c to have type char:
char c;
Then you're trying to use strcpy(c,a) -- but what type does strcpy expect for its first argument? Here's the signature from the manpage:
char *strcpy(char *dest, const char *src);

read the characters between special characters in C

I'm new to C language and I need a help on String functions.
I have a string variable called mcname upon which I would like to compare the characters between special characters.
For example:
*mcname="G2-99-77"
I expect the output to be 99 as this is between the - characters.
How can I do this in C please?
Travel the string (walking pointer) till u hit a special character.
Then start copying the characters into seperate array untill u hit the next special character (Place a null character when u encounter the special character second time)
You can do this by using strtok or sscanf
using sscanf:
#include <stdio.h>
int main()
{
char str[64];
int out;
char mcname[] = "G2-99-77";
sscanf(mcname, "%[^-]-%d", str, &out);
printf("%d\n", out);
return 0;
}
Using strtok:
#include <stdio.h>
#include <string.h>
int main()
{
char *str;
int out;
char mcname[] = "G2-99-77";
str = strtok(mcname, "-");
str = strtok (NULL, "-");
out = atoi(str);
printf("%d\n", out);
return 0;
}
sscanf() has great flexibility. Used correctly, code may readily parse a string.
Be sure to test the sscanf() return value.
%2[A-Z0-9] means to scan up to 2 characters from the set 'A' to 'Z' and '0' to '9'.
Use %2[^-] if code goal is any 2 char other than '-'.
char *mcname = "G2-99-77";
char prefix[3];
char middle[3];
char suffix[3];
int cnt = sscanf(mcname, "%2[A-Z0-9]-%2[A-Z0-9]-%2[A-Z0-9]", prefix, middle,
suffix);
if (cnt != 3) {
puts("Parse Error\n");
}
else {
printf("Prefix:<%s> Middle:<%s> Suffix:<%s>\n", prefix, middle, suffix);
}

Resources