String Manipulation C Programming - c

int findChar(char * str, char c);
Searches for the character c in the string str and returns the index of the character in the string. If the character does not exist, returns -1
int replaceChar(char * str, char c1, char c2);
Searches for the character c1 in the string str and if found, replace it with c2.The
function returns the number of replacements it has performed. If the character does not
exist, returns 0.
int removeChar(char * str1, char * str2, char c);
Creates a copy of str1 into str2 except for the character c that should be replaced
with ‘*’
Hi guys So Far I have the following Code Which is not optimal. I have been trying to debug this for a bit and finally have come here for help.
findChar(char *str, char c);
replaceChar(char *str, char c1, char c2);
int main(){
char str[] ="all";
if (findChar(str, 'l'))
printf("Character found at index: %d\n", findChar(str, 'l'));
else
printf("No Character found\n");
if (replaceChar(str, 'x', 'a') !=0){
printf("%d",replaceChar(str,'x','a'));
printf("\n");
}
else
printf("Character does not exist\n");
system("pause");
return 0;
}
int findChar(char *str, char c){
for (int i = 0; i <strlen(str); i++){
if (str[i] == c)
return i;
}
return -1;
}
int replaceChar(char *str, char c1, char c2){
int position = 0;
int count = 0;
do{
int position = findChar(str, c1);
if (position != -1){
str[position] = c2;
count++;
}
} while (findChar(str, c1) != -1);
if (count == 0){
return 0;
}
else{
return count;
}
}

In replaceChar, anytime you call findChar(str, c1) it will always return the same value, since findChar grabs the first instance of c1 in str. So position is always the same and your loop condition is always the same.
Rather than having replaceChar call findChar, it should just loop through the string itself. Much simpler logic that way.
int replaceChar(char *str, char c1, char c2){
int i;
int count = 0;
int len = strlen(str);
for (i=0; i<len; i++) {
if (str[i] == c1) {
str[i] = c2;
count++;
}
}
return count;
}

Related

How can I access the certain indexes of string using the function?

I was practicing and found some exercise on the internet and it says that I should copy str2 to str1, perhaps the main problem is that I should copy only a certain index of that string (so from str2[a] to str2[b]). Therefore A and B should be entered so they reduce the range of copied indexes to str1. So here I used the function method to tackle this problem but something went wrong. So I don't get why function does not work, there must be a big mistake in my understanding or I did it all wrong.
#include <stdio.h>
#include <string.h>
#define N 50
void myfunction(char str1[], char str2[], int a, int b);
int main() {
char str1[N], str2[N];
int a, b;
printf("please input str1:");
gets(str1);
printf("please input str2:");
gets(str2);
printf("please input a and b:");
scanf("%d%d", &a, &b);
printf("str2=%s, str1=%s", str2, str1);
myfunction(str1, str2, a, b);
return 0;
}
void myfunction(char str1[], char str2[], int a, int b) {
int i, j;
for (i = a; i <= b; i++) {
str1 += str2[i];
}
}
I should copy str2 to str1, perhaps the main problem is that I should
copy only a certain index of that string (so from str2[a] to str2[b]).
It looks like you need to copy a part of one string in another character array starting from its initial position and as a result the character array shall also keep a string built from characters of the first string.
If so then the function should be declared like
char * myfunction( char str1[], const char str2[], size_t n );
that is one of parameters of your original function is redundand because using the pointer arithmetic you can always call the function like
myfunction( str1, str2 + a, b - a + 1 );
In your function implementation it seems there are typos.
void myfunction(char str1[], char str2[], int a, int b) {
int i, j;
for (i = a; i <= b; i++) {
str1 += str2[i];
}
}
For example the variable j is not used, And in this assignment statement
str1 += str2[i];
the left operand is a pointer. So you are just increasing the pointer itself without copying anything. For example if str2[i] contains the character 'A' then the above statement looks like
str1 += 'A';
If there is used the ASCII character table then the statement is equivalent to
str1 += 65;
That is the address stored in the pointer str1 is increased by 65 and will point beyond the destination array.
Also in main there is no great sense to input a string in the character array str1 because as it is supposed it will be overwritten in the function.
Pay attention to the function gets is unsafe and is not supported by the C Standard any more. Instead you should use the function fgets.
Here is a demonstrative program that shows how the function can be written without using standard string functions.
#include <stdio.h>
#define N 50
char * myfunction( char str1[], const char str2[], size_t n )
{
char *p = str1;
while ( *str2 && n-- )
{
*p++ = *str2++;
}
*p = '\0';
return str1;
}
int main(void)
{
char str1[N];
char str2[N] = "Hello World!";
puts( str2 );
puts( myfunction( str1, str2 + 6, 6 ) );
return 0;
}
The program output is
Hello World!
World!
If you will change the function the following way
char * myfunction( char str1[], const char str2[], size_t n )
{
char *p = str1;
while ( *str2 && n )
{
*p++ = *str2++;
--n;
}
while ( n-- ) *p++ = '\0';
return str1;
}
then it will behave the same way as the standard string function strncpy declared in the header <string.h> which you should familiarize yourself with.
There are multiple problems in your program:
you should not use gets()
myfunction just increments str1 instead of copying characters.
you should output the resulting string.
Here is modified version:
#include <stdio.h>
#include <string.h>
#define N 50
void myfunction(char str1[], char str2[], int a, int b);
// safe replacement for gets()
char *mygets(char *buf, size_t n) {
int c;
size_t i;
while ((c = getchar()) != '\n') {
if (c == EOF) {
if (i == 0)
return NULL;
break;
}
if (i + 1 < n)
buf[i++] = c;
}
if (i < n) {
buf[i] = '\0';
}
return buf;
}
int main() {
char str1[N], str2[N];
int a, b;
printf("please input str1: ");
if (!mygets(str1, sizeof str1))
return 1;
printf("please input str2: ");
if (!mygets(str2, sizeof str2))
return 1;
printf("please input a and b: ");
if (scanf("%d%d", &a, &b) != 2)
return 1;
printf("str2=%s, str1=%s\n", str2, str1);
myfunction(str1, str2, a, b);
printf("str1=%s\n", str1);
return 0;
}
void myfunction(char str1[], char str2[], int a, int b) {
int len1 = strlen(str1);
int len2 = strlen(str2);
int i, j;
if (a < 0)
a = 0;
if (b > len2)
b = len2;
for (i = 0, j = a; j <= b; i++, j++) {
str1[i] = str2[j];
}
if (i > len1) {
/* do not truncate str1 but set the null terminator if needed */
str1[i] = '\0';
}
}
Instead of copying characters between the strings, the line:
str1 += str2[i];
just increments the pointer.
You probably want:
void myfunction(char str1[], char str2[], int a, int b) {
int i, j = 0;
for (i = a; i <= b; ++i) {
str1[j] = str2[i]; // Copy the character in position i in str2 to position i in str1
++j;
}
str1[j] = '\0';
}
str1+= is not how you assign to elements of str1. It simply increments the pointer variable str1, which is not useful here.
You can use two variables, one for the index in str1 to assign to, and another for the index in str2 to read from.
You also need to check for reaching the end of str2, and add a null terminator to str1.
void myfunction(char str1[], char str2[], int a, int b) {
int i = 0, j = a;
if (a >= 0 && a <= strlen(str2)) {
for (; str2[j] && j <= b; i++, j++) {
str1[i] = str2[j];
}
}
str1[i] = '\0';
}
If you want to copy Characters one by one from array of characters you can use for loop like:-
Considering a to be index of str1 where to paste and b be index of str2 from where to Paste.
This is not exact Solution but you can take help from this...
void myfunction(char str1[], char str2[],int a, int b)
{
str1[a] = str2[b];
}

Error when extracting sub-string from the start of source string in C

This is from an exercise in Chapter 9 of Programming in C 4th Edition. The programme is to read in characters into a string and extract a portion of the string into a sub-string by specifying a start position and number of characters.
The programme compiles and runs well except when the zeroth position of the source is stated as the start. Nothing is then displayed.
This is my code.
/* Programme to extract a portion from a string using function
sub-string (source, start, count, result) ex9.4.c
ALGORITHM
Get text input into a char array (declare to be fixed size);
Determine length of source string;
Prepare result array to be dynamic length using desired count + 1;
Copy from source array into result array
*/
#include <stdio.h>
#include <stdbool.h>
#define MAX 501
void read_Line (char buffer[]);
int string_Length (char string[]);
void sub_String (char source[], int start, int count, char result[]);
int main(void)
{
char strSource[MAX];
bool end_Of_Text = false;
int strCount = 0;
printf("This is a programme to extract a sub-string from a source string.\n");
printf("\nType in your text (up to 500 characters).\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(strSource);
if (strSource[0] == '\0')
{
end_Of_Text = true;
}
else
{
strCount += string_Length(strSource);
}
}
// Declare variables to store sub-string parameters
int subStart, subCount;
char subResult[MAX];
printf("Enter start position for sub-string: ");
scanf(" %i", &subStart);
getchar();
printf("Enter number of characters to extract: ");
scanf(" %i", &subCount);
getchar();
// Call sub-string function
sub_String(strSource, subStart, subCount, subResult);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to count determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to extract substring
void sub_String (char source[], int start, int count, char result[])
{
int i, j, k;
k = start + count;
for (i = start, j = 0; i < k || i == '\0'; ++i, ++j)
{
result[j] = source[i];
}
result[k] = '\0';
printf("%s\n", result);
}
I am using Code::Blocks on Linux Mint.
Being someone that just started learning programming recently with CS50 and 'Programming in C' books, I did not know how to setup the debugger in Code::Blocks. But thanks to the push by #paulsm4, I managed to get the debugger working. Using the watches window of the debugger, I could see that the while loop in the main function was overwriting the first character in the source array with a null character. The fix was to add a break statement. Thanks to #WhozCraig and #Pascal Getreuer for pointing out other errors that I had missed. This is the corrected code now:
/* Programme to extract a portion from a string using function
sub-string (source, start, count, result) ex9.4.c
ALGORITHM
Get text input into a char array (declare to be fixed size);
Determine length of source string;
Prepare result array to be dynamic length using desired count + 1;
Copy from source array into result array
*/
#include <stdio.h>
#include <stdbool.h>
#define MAX 501
void read_Line (char buffer[]);
int string_Length (char string[]);
void sub_String (char source[], int start, int count, char result[]);
int main(void)
{
char strSource[MAX];
bool end_Of_Text = false;
int strCount = 0;
printf("This is a programme to extract a sub-string from a source string.\n");
printf("\nType in your text (up to 500 characters).\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(strSource);
if (strSource[0] == '\0')
{
end_Of_Text = true;
}
else
{
strCount += string_Length(strSource);
}
break;
}
// Declare variables to store sub-string parameters
int subStart, subCount;
char subResult[MAX];
printf("Enter start position for sub-string: ");
scanf(" %i", &subStart);
getchar();
printf("Enter number of characters to extract: ");
scanf(" %i", &subCount);
getchar();
// Call sub-string function
sub_String(strSource, subStart, subCount, subResult);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to count determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to extract substring
void sub_String (char source[], int start, int count, char result[])
{
int i, j, k;
k = start + count;
// Source[i] == '\0' is used in case count exceeds source string length
for (i = start, j = 0; i < k || source[i] == '\0'; ++i, ++j)
{
result[j] = source[i];
}
result[j] = '\0';
printf("%s\n", result);
}

c- finding how many times a character occurs in a string

#include <stdio.h>
#include <string.h>
#define SIZE 40
int main(void)
{
char buffer1[SIZE] = "computer program";
char *ptr;
int ch = 'p', j = 0, i;
for (i = 0; i<strlen(buffer1); i++)
{
ptr = strchr(buffer1[i], ch);
if (ptr != 0) j++;
printf(" %d ", j);
}
}
I want to count how many times a character occurs in a string.
In my program I chose the character 'p'.
I know Pascal, I am learning C now. In pascal is a function called Pos(x,y) which is searching for x in y. Is something familiar to this? I think what I used here is not.
The function signature of strchr is
char *strchr(const char *s, int c);
You need to pass a char* but you have passed a char. This is wrong.
You have used the strlen in loop - making it inefficient. Just calculate the length of the string once and then iterate over it.
char *t = buffer;
while(t!= NULL)
{
t = strchr(t, ch);
if( t ) {
t++;
occurences++;
}
}
And without using standard library functions you can simply loop over the char array.
size_t len = strlen(buffer);
for(size_t i = 0; i < len; i++){
if( ch == buffer[i]) occurences++;
}
Or alternatively without using strlen
char *p = buffer;
while(*p){
if( *p == ch ){
occurences++;
}
p++;
}
Or
for(char *p = buffer; *p; occurences += *p++ == ch);
Try this example :
int main()
{
char buffer1[1000] = "computer program";
char ch = 'p';
int i, frequency = 0;
for(i = 0; buffer1[i] != '\0'; ++i)
{
if(ch == buffer1[i])
++frequency;
}
printf("Frequency of %c = %d", ch, frequency);
return 0;
}

hi i am writing a c program to get the position of a character in a given string

I am developing a code to return a position of a character in string.
I have removed all the error but when I run the program my compiler
crashes.
find a position in a given string
// int str_find_char(char *str, char *ch) -
// returns the position where ch is in str and if not present returns -1
#include <stdio.h>
char arr[5] = {'a','b','c','d','e'};
char d;
int str_find_char(char (*ptr),char *chr)
{
int i;
for(i=0; i<5; i++)
{
printf("h");
}
}
int main(void)
{
char (*ptr)[5];
char arr[5] = {'a','b','c','d','e'};
ptr = &arr;
int i,k=0;
char *chr;
char ch;
chr = &ch;
printf("enter the value to search = ");
scanf("%c",&ch);
str_find_char( (*ptr), chr);
if(*(ptr[i]) = ch)
{
printf("element found at = %d",i);
k = 1;
}
else if(k == 1)
{
printf("element found at = %d",i);
return 0;
}
else {
return -1;
}
}
First of all you said you search in a string that means it must be null terminated.
You can change
char arr[5] = {'a','b','c','d','e'};
to
char arr[] = "abcde";
and use the code below
int GetCharPos(char* str, char ch)
{
int i = 0;
int ret = -1;
while(*str){
if(*str++ == ch){
ret = i;
break;
}
i++;
}
return ret ;
}
Note that this code will work only if you pass a null terminated string.
Annti Haapala is right. Your compiler should be generating truckloads of warnings, among which should also be a few errors.
You should repeatedly check if you've found a matching character
int str_find_char(const char* str, char ch){
const char* p = str;
for(;*p;p++)
if(*p== ch)
return (p - str);
return -1;
}
...and as a good practice, use a const pointer if the function does not change the string.
Also notice UBs:
int i,k=0; // i is uninitialized
char *chr;
char ch;
chr = &ch;
printf("enter the value to search = ");
scanf("%c",&ch);
str_find_char( (*ptr), chr);
if(*(ptr[i]) = ch) // Use an uninitialized variable?
{ // Now exit with Segmentation fault!

Run-Time Check Failure #2 - Stack around the variable 'command' was corrupted

I'm getting this error while running the code above:
#include <stdio.h>
#include <stdlib.h>
int ln(char *str);
int compare(char *str1, char *str2);
void reverse(char *str, int n);
void main(){
int n;
int len;
char *str;
char command[2];
printf("Enter your string:\n");
scanf("%d", &n);
str = malloc(n);
scanf("%s", str);
printf(">");
scanf("%s", command);
if (compare(command, "ln")) {
len = ln(str);
printf("%d\n", len);
}
if (compare(command, "rv")) {
reverse(str, n);
printf("The current string is %s\n", str);
}
free(str);
}
int ln(char *str) {
int i = 0;
while (str[i] != '\0') {
i++;
}
return i;
}
int compare(char *str1, char *str2) {
int i = 0;
while (str1[i] == str2[i] && str1[i] != '\0' && str2[i] != '\0') {
i++;
}
if (str1[i] == '\0' && str2[i] == '\0') {
return 1;
}
else {
return 0;
}
}
void reverse(char *str, int n){
int i;
for (i = 0; i < n / 2; i++){
char tmp = str[i];
str[i] = str[n - 1 - i];
str[n - i - 1] = tmp;
}
}
I've searched online, but any related error I've read about was about writing to much to the allocated memory and such things.
The error happens when I enter the values "5 abcde" or "4 abcd" or any other number & string (the number equals the string length), and the "rv" (reverse) command.
While debugging, I found that the code works perfectly, and the error appears only at the last line (after the string has been reversed).
Any help would be appriciated!
char command[2]; declares a buffer of length 2. So it can contain a string of length 1 at most because you need one char more for the zero terminator.
As soon as you enter a string longer than 1 during scanf("%s", command); you will get a buffer overflow which corrupts the stack, hence the error.
Reserve a longer buffer for example with char command[200];
EDIT
Other problem:
Instead of reverse(str, n); use reverse(str, ln(str)); . n contains the maximum string length used fot malloc and the reverse function wants the actual string length in the second parameter.

Resources