implementation of strstr() function - c

The code says at many places "invalid indirection".Please help.
int main()
{
char *s1,*s2,*position;
printf("Enter string:\n");
gets(s1);
printf("Enter word to find:\n");
gets(s2);
*position=ststr(*s1,*s1);
if(*position)
printf("word is found at %c loc\n",*position);
else
printf("word not found");
getch();
return 0;
}
char *strstr(char *s1,char *s2)
{
int flag=1;
char i,j;
for(i=0; ;i++)
{
if(*s1[i]==*s2[0])
for(j=i;*s2;j++)
{
if(*s1[j]!=*s2[j])
flag=0;
}
}
if(flag)
return i;
else
return 0;
}

First, s1 and s2 in main have not been initialized to point anywhere meaningful. Either declare them as static arrays, or allocate memory to them at runtime using malloc() or calloc():
#define SIZE 20 // or some number big enough to hold your input
...
char s1[SIZE], s2[SIZE], *position; // s1 and s2 declared statically
Second, NEVER NEVER NEVER NEVER NEVER use gets(); it will introduce a point of failure in your program. Use fgets() instead:
if (fgets(s1, sizeof s1, stdin) != NULL)
// process s1
else
// check for EOF or error on read
EDIT
And like everyone else has pointed out, your comparison in the strstr() function needs to be either
*s1 == *s2
or
s1[i] == s2[i]
but first you need to deal with allocating your buffers in main properly.

One of the problems I'm noticing is whenever you do *s1[j]. The asterisk is dereferencing the array, and so is the [] notation.
s[i] really means *(s + i), so you don't have to dereference it again. The way you have it would read **(s + i), and since it's a single pointer you can't do that.

if(*s1[i]==*s2[0])
is such an example where my gcc complains:
error: invalid type argument of ‘unary *’ (have ‘int’)
if s1 is a pointer to char, s1[i] is a char. So you can't dereference it any more (with the *), i.e. s1[i] does not point to anything any more.
Try
if(s1[i]==s2[0])
instead.
You should also change the return value of strstr: you return an integer where you declare to return a pointer to a character. So try returning s1+i instead.
This here:
for(j=i;*s2;j++)
probably does not what you want. You're not advancing the pointer s2 anywhere in the loop, in fact you're just testing whether s2[0] (which is the same as *s2) is zero for each iteration. If s2 isn't the empty string, this loop will never terminate.

#include "stdio.h"
char *strstr(char *str, char *substr)
{
int len = strlen(substr);
char *ref = substr;
while(*str && *ref)
{
if (*str++ == *ref)
{
ref++;
}
if(!*ref)
{
return (str - len);
}
if (len == (ref - substr))
{
ref = substr;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
printf("%s \n", strstr("TEST IS NOT DONE", "IS NOT"));
}

if(*s1[j]!=*s2[j])
*s1 means "the character where s1 is pointing".
s1[j] means "*(s1+j)" or "the character j positions after where s1 is pointing"
You have to use one or the other; not both.

#include <stdio.h>
char* my_strstr(char *s2, char *s1)
{
int i, j;
int flag = 0;
if ((s2 == NULL || s1 == NULL)) return NULL;
for( i = 0; s2[i] != '\0'; i++)
{
if (s2[i] == s1[0])
{
for (j = i; ; j++)
{
if (s1[j-i] == '\0'){ flag = 1; break;}
if (s2[j] == s1[j-i]) continue;
else break;
}
}
if (flag == 1) break;
}
if (flag) return (s2+i);
else return NULL;
}
int main()
{
char s2[] = "This is the statement";
char s1[] = "the";
char *temp;
temp = my_strstr(s2,s1);
printf("%s\n",temp);
return 0;
}

Related

Which string is the longest

My code:
What I'm trying to do is to input two strings, then return the longest one. If they're the same length then return NULL. Now, the code is just outputting gibberish and I cannot find out why. The function returns a pointer to the first character of the largest string. Then it goes through the while loop, and I'm trying to dereference the pointer and print out its value.
Note: I'm revising for an exam and we have to use only pointers and not treat strings as arrays.
#include<stdio.h>
char* string_ln(char*, char*);
int main() {
char str1[20];
char str2[20];
char* length;
scanf("%s%s", str1, str2);
length = string_ln(str1, str2);
while (length != '\0') {
printf("%c", *length);
length++;
}
}
char* string_ln(char*p1, char*p2) {
int count1 = 0;
while (*p1 != '\0') {
count1++;
p1++;
}
int count2 = 0;
while (*p2 != '\0') {
count2++;
p2++;
}
if (count1 > count2) {
return p1;
}
else if (count2 > count1) {
return p2;
}
else {
return NULL;
}
}
In writing string_ln you iterate over both strings completely to find their lengths, and then compare those numbers. This can work, but you don't actually need to do this. You only need to know which is longer. It doesn't matter how much longer the longer string is.
char *string_ln(char *str1, char *str2) {
char *iter1, *iter2;
for (iter1 = str1, iter2 = str2;
*iter1 && *iter2;
iter1++, iter2++);
if (!(*iter1 || *iter2)) {
return NULL;
}
else if (*iter1) {
return str1;
}
else {
return str2;
}
}
We simply need to iterate over both strings, until at least one hits a NULL character. Once we get to that point, we can test to see which iterator is NULL. If it's both of them, then they're the same length. If the first iterator is not NULL, then the first string is longer. Otherwise, the second string is longer.
The benefit to this approach is that we avoid unnecessary work, and make it much quicker to compare strings of very different lengths.
There are a few problems here. First, you're modifying p1 and p2 in the function, so you won't actually return a pointer to the beginning of the largest string, but to its end. One way to avoid this is to iterate over copies of p1 and p2:
char* string_ln(char*p1, char*p2)
{
char* tmp1 = p1;
int count1 = 0;
while (*tmp1 != '\0') {
count1++;
tmp1++;
}
char* tmp2 = p2;
int count2 = 0;
while (*tmp2 != '\0') {
count2++;
tmp2++;
}
if(count1>count2){
return p1;
}
else if(count2>count1){
return p2;
}
else{
return NULL;
}
}
Second, in your main, you're using the %c format string, which works for a single char, not a whole string. Since you have a string anyway, you can avoid a format string and just print it directly. Also, note that you should explicitly check for NULLs:
int main() {
char str1[20];
char str2[20];
char* longest;
scanf("%s%s", str1, str2);
longest = string_ln(str1, str2);
if (longest) {
printf(longest);
} else {
printf("They are the same length");
}
}
I think you're missing to dereference the pointer. Instead of
while(length!='\0')
you'd need
while(*length!='\0')
That said, in the called function, you're reuring pointers after the increment, i.e., the returned pointers do not point to the start of the string anymore. You need to ensure that you return pointers which points to the beginning of the string. You can change your code to
int count1 = 0;
while (p1[count1] != '\0') {
count1++;
}
int count2 = 0;
while (p2[count2] != '\0') {
count2++;
}
so that p1 and p2 does not change.
For starters the function should be declared like
char * string_ln( const char *, const char * );
because the passed strings are not being changed within the function.
You are returning from the function the already modified pointer p1 or p2 that is being changed in one of the while loops
while (*p1 != '\0') {
count1++;
p1++;
}
while (*p2 != '\0') {
count2++;
p2++;
}
So the returned pointer points to the terminating zero '\0' of a string.
Moreover in main before this while loop
length = string_ln(str1, str2);
while(length!='\0'){
printf("%c", *length);
length++;
}
you are not checking whether the pointer length is equal to NULL. As a result the program can invoke undefined behavior.
The function itself can be defined the following way using only pointers.
char * string_ln( const char *p1, const char *p2 )
{
const char *s1 = p1;
const char *s2 = p2;
while ( *s1 != '\0' && *s2 != '\0' )
{
++s1;
++s2;
}
if ( *s1 == *s2 )
{
return NULL;
}
else if ( *s1 == '\0' )
{
return ( char * )p2;
}
else
{
return ( char * )p1;
}
}
and in main you need to write
char *length = string_ln( str1, str2 );
if ( length != NULL )
{
while ( *length )
printf( "%c", *length++ );
}
Pay attention to that the return type of the function is char * instead of const char *. It is because in C there is no function overloading and the returned pointer can point to a constant string or to a non-constant string. It is a general convention in C for declaring string functions.

Unable to return NULL when character not found in the function xstrchr

I am not able to make use of the else condition in main(). The code doesn't work when character is not found in string. How should I modify the return statement or the else condition in main ?
#include <stdio.h>
char *xstrchr(char *string, char ch);
void main() {
char str[20], ch;
printf("Enter a string :");
gets(str);
printf("Enter character to search in string :");
scanf("%c", &ch);
char *r = xstrchr(str, ch);
printf("%c is stored at %d\n", *r, r);
if (r != NULL)
printf("Character '%c' found at %d index.\n", ch, (r - str + 1));
else
printf ("Character not found.");
}
char *xstrchr(char *s, char ch) {
int flag = 0, i = 0;
while (*(s + i) != '\0') {
if (*(s + i) == ch) {
flag = 1;
return (s + i);
}
i++;
}
if (flag == 0) {
return NULL;
}
}
Your function does return NULL when the character is not found, but you have undefined behavior in main() when it does so as you dereference r in the printf statement before testing for a NULL result, causing your program to crash.
There are other problems:
the prototype for main should be int main(void) or int main(int argc, char *argv[]) or possibly int main().
you must nos use gets(). This function has been removed from the C language because it cannot be used safely. If the user types more than 19 characters at the prompt, your program will have undefined behavior as gets() will write beyond the end of the array.
pointers should not be printed with %d, you should write:
printf("%c is stored at %p\n", *r, (void *)r);
the difference of 2 pointers has type ptrdiff_t, which mau be larger than int and should not be printed with %d. The standard format for this is %td, but many C libraries do not support this, so converting the difference to int may be preferable:
printf("Character '%c' found at %d index.\n", ch, (int)(r - str + 1));
index values start at 0 in C. It is confusing to refer to the first element of an array as index 1.
you should test the return values of fgets() and scanf() to detect premature end of file or other input failures.
index values may exceed the range of type int. You should use type size_t for i in xstrchr().
flag is not used in the xstrchr function: the update code and the test are redundant and can be removed.
*(s + i) can be written s[i], which is much more readable. Unless you are required to use the pointer arithmetic syntax explicitly, you should use the bracketed syntax.
Here is a corrected version:
#include <stdio.h>
char *xstrchr(char *string, char ch);
int main() {
char str[200], ch;
printf("Enter a string: ");
if (!fgets(str, sizeof str, stdin))
return 1;
printf("Enter character to search in string: ");
if (scanf("%c", &ch) != 1)
return 1;
char *r = xstrchr(str, ch);
if (r != NULL) {
printf("Character '%c' found at %d index.\n", ch, (int)(r - str));
else
printf("Character not found.\n");
return 0;
}
char *xstrchr(char *s, char ch) {
size_t i = 0;
while (s[i] != '\0') {
if (s[i] == ch) {
return s + i;
}
i++;
}
return NULL;
}
Finally, the xstrchr() function does not completely match the specification of the standard strchr() function:
the argument type for ch is int, but its value is converted to char for comparison purposes.
the argument type for s is const char * as the string is not modified by this function, but the return type is char * so the return value must then be cast as (char *), which is an unfortunate but necessary step.
the null terminator at the end of the string will be matched if ch has a null value.
incrementing s instead of using an index variable is an alternative many C programmers would prefer.
Here is a modified version:
char *xstrchr(const char *s, int ch) {
for (;; s++) {
if (*s == (char)ch)
return (char *)s;
if (*s == '\0')
return NULL;
}
}

Function to reverse the input string.Display the reversed string but just with pointer no brackets[],no libraries..function will change in memory

int *i;
ters_cevir(){
char *term=i;
char *som=i;
char som1;
while (*term != '\0') { term++; }
while (*som != '\0') {
som1=som*;
*term=som;
term--;
som++;
}
}
int main() {
char *isim=malloc(sizeof(char));
i=&isim;
printf("Reverse words=");
scanf("%s",isim);
printf("Kelimenizin tersi:\n ");
ters_cevir(); // When I call this, it must make the reverse one that make from memory
while (*isim != '\0') {
printf("%c",*isim);
isim++;
sayac++;
}
return 0;
}
Hi I have modified your code. Please see below also see my comments:-
void ters_cevir(char *isim){
char *term=isim;
//char *som=isim;
//char som1;
while (*isim != '\0') { isim++; }
while (*term != '\0') {
//som1=som*;
*--isim=*term++//isim was pointing to the null character so we are pre decrement that pointer and post decrement term
//here we are coping the string in reverse order in isim
//term--;
//som++;
}
}
int main() {
char *isim=malloc(50);//you need enough space to store a string. you have just allocated only one byte which was not enough
//i=&isim;
printf("Reverse words=");
scanf("%s",isim);
printf("Kelimenizin tersi:\n ");
ters_cevir(isim); // now it will work fine. Here you are passing the address of isim
while (*isim != '\0') {
printf("%c",*isim);
isim++;
sayac++;
}
return 0;
}
Your code does not compile because of syntax errors such as som1=som*;
You should pass the string as an argument to ters_cevir(); instead of a global variable i with an incorrect type int *.
After fixing these problems, ters_cevir() will still not achieve the expected result because it overwrites the string from the end with characters from the start, with an off by one error.
You could correct this by swapping characters at *som and *term, but be careful to stop when som >= term otherwise you will reverse the string twice.
Futhermore, the code in main is completely broken.
Here is a corrected version:
#include <stdio.h>
char *reverse(char *str) {
char *term = str;
char *som = str;
char c;
while (*term != '\0') { term++; }
while (som < term) {
term--;
c = *som;
*som = *term;
*term = c;
som++;
}
return str;
}
int main() {
char buf[128];
printf("String to reverse: ");
if (scanf("%127[^\n]", buf) == 1) {
printf("Reversed string: %s\n", reverse(buf));
}
return 0;
}

Remove a word from a sentence (string)

I am in the stage of preparing myself for exams, and the thing that I m least proud of are my skills with strings. What I need to do is remove a word from a sentence, without using <string.h> library at all.
This is what I've got so far. It keeps showing me that certain variables are not declared, such as start and end.
#include <stdio.h>
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
s--;
return counter;
}
/* Function to remove a word from a sentence */
char *remove_word(const char *s1, const char *s2) {
int counter2 = 0;
/* We must remember where the string started */
const char *toReturn = s1;
/* Trigger for removing the word */
int found = 1;
/* First we need to find the word we wish to remove [Don't want to
use string.h library for anything associated with the task */
while (*s1 != '\0') {
const char *p = s1;
const char *q = s2;
if (*p == *q)
const char *start = p;
while (*p++ == *q++) {
counter2++;
if (*q != '\0' && counter2 < count(s2))
found = 0;
else {
const char *end = q;
}
}
/* Rewriting the end of a sentence to the beginning of the found word */
if (found) {
while (*start++ = *end++)
;
}
s1++;
}
return toReturn;
}
void insert(char niz[], int size) {
char character = getchar();
if (character == '\n')
character = getchar();
int i = 0;
while (i < size - 1 && character != '\n') {
array[i] = character;
i++;
character = getchar();
}
array[i] = '\0';
}
int main() {
char stringFirst[100];
char stringSecond[20];
printf("Type your text here: [NOT MORE THAN 100 CHARACTERS]\n");
insert(stringFirst, 100);
printf("\nInsert the word you wish to remove from your text.");
insert(stringSecond, 20);
printf("\nAfter removing the word, the text looks like this now: %s", stringFirst);
return 0;
}
your code is badly formed, i strongly suggest compiling with:
gcc -ansi -Wall -pedantic -Werror -D_DEBUG -g (or similar)
start with declaring your variables at the beginning of the function block, they are known only inside the block they are declared in.
your count function is buggy, missing a closing '}' (it doesn't compile)
should be something like
size_t Strlen(const char *s)
{
size_t size = 0;
for (; *s != '\n'; ++s, ++size)
{}
return size;
}
implementing memmove is much more efficient then copy char by char
I reformatted you code for small indentation problems and indeed indentation problems indicate real issues:
There is a missing } in count. It should read:
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
}
return counter;
}
or better:
/* Side function to count the number of letters of the word we wish to remove */
int count(const char *s) {
const char *s0 = s;
while (*s++) {
continue;
}
return s - s0;
}
This function counts the number of bytes in the string, an almost exact clone of strlen except for the return type int instead of size_t. Note also that you do not actually use nor need this function.
Your function insert does not handle EOF gracefully and refuses an empty line. Why not read a line with fgets() and strip the newline manually:
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
In function remove_word, you should define start and end with a larger scope, typically the outer while loop's body. Furthermore s1 should have type char *, not const char *, as the phrase will be modified in place.
You should only increment p and q if the test succeeds and you should check that p and q are not both at the end of their strings.
last but not least: you do not call remove_word in the main function.
The complete code can be simplified into this:
#include <stdio.h>
/* Function to remove a word from a sentence */
char *remove_word(char *s1, const char *s2) {
if (*s2 != '\0') {
char *dst, *src, *p;
const char *q;
dst = src = s1;
while (*src != '\0') {
for (p = src, q = s2; *q != '\0' && *p == *q; p++, q++)
continue;
if (*q == '\0') {
src = p; /* the word was found, skip it */
} else {
*dst++ = *src++; /* otherwise, copy this character */
}
}
*dst = '\0'; /* put the null terminator if the string was shortened */
}
return s1;
}
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
int main() {
char stringFirst[102];
char stringSecond[22];
printf("Type your text here, up to 100 characters:\n");
if (!input(stringFirst, sizeof stringFirst))
return 1;
printf("\nInsert the word you wish to remove from your text: ");
if (!input(stringSecond, sizeof stringSecond))
return 1;
printf("\nAfter removing the word, the text looks like this now: %s\n",
remove_word(stringFirst, stringSecond));
return 0;
}
Your start and end pointers are defined within a block which makes their scope limited within that block. So, they are not visible to other parts of your code, and if you attempt to reference them outside their scope, the compiler will complain and throw an error. You should declare them at the beginning of the function block.
That said, consider the following approach to delete a word from a string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int delete_word(char *buf,
const char *word);
int main(void)
{
const char word_to_delete[] = "boy";
fputs("Enter string: ", stdout);
char buf[256];
fgets(buf, sizeof(buf), stdin);
if (delete_word(buf, word_to_delete))
{
printf("Word %s deleted from buf: ", word_to_delete);
puts(buf);
}
else
{
printf("Word %s not found in buf: ", word_to_delete);
puts(buf);
}
system("PAUSE");
return 0;
}
int chDelimit(int ch)
{
return
(ch == '\n' || ch == '\t') ||
(ch >= ' ' && ch <= '/') ||
(ch >= ':' && ch <= '#') ||
(ch >= '[' && ch <= '`') ||
(ch >= '{' && ch <= '~') ||
(ch == '\0');
}
char *find_pattern(char *buf,
const char *pattern)
{
size_t n = 0;
while (*buf)
{
while (buf[n] && pattern[n])
{
if (buf[n] != pattern[n])
{
break;
}
n++;
}
if (!pattern[n])
{
return buf;
}
else if (!*buf)
{
return NULL;
}
n = 0;
buf++;
}
return NULL;
}
char *find_word(char *buf,
const char *word)
{
char *ptr;
size_t wlen;
wlen = strlen(word);
ptr = find_pattern(buf, word);
if (!ptr)
{
return NULL;
}
else if (ptr == buf)
{
if (chDelimit(buf[wlen]))
{
return ptr;
}
}
else
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
}
ptr += wlen;
ptr = find_pattern(ptr, word);
while (ptr)
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
ptr += wlen;
ptr = find_pattern(ptr, word);
}
return NULL;
}
int delete_word(char *buf,
const char *word)
{
size_t n;
size_t wlen;
char *tmp;
char *ptr;
wlen = strlen(word);
ptr = find_word(buf, word);
if (!ptr)
{
return 0;
}
else
{
n = ptr - buf;
tmp = ptr + wlen;
}
ptr = find_word(tmp, word);
while (ptr)
{
while (tmp < ptr)
{
buf[n++] = *tmp++;
}
tmp = ptr + wlen;
ptr = find_word(tmp, word);
}
strcpy(buf + n, tmp);
return 1;
}
If you have to do it manually, just loop over the indicies of your string to find the first one that matches and than you’ll have a second loop that loops for all the others that matches and resets all and jumps to the next index of the first loop if not matched something in order to continue the searching. If I recall accuretaly, all strings in C are accesible just like arrays, you’ll have to figure it out how. Don’t afraid, those principles are easy! C is an easy langugae, thiught very long to write.
In order to remove: store the first part in an array, store the second part in an array, alloc a new space for both of them and concatinate them there.
Thanks, hit the upvote button.
Vitali
EDIT: use \0 to terminate your newly created string.

Remove specified char from strings in C

I am making a program that will search in an array of strings, and for each string, it will search for a specified char. If it finds that char, remove it. In this example I want to remove the character 'r'.
Here is the code:
void convertStrings(char **line) {
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
I am not sure if the algorithm for the removal of chars is correct, however the main mistake is elsewhere. More specifically, I get a segmentation fault in the line:
if (line[str][ch] == 'r') {
Why am I getting a seg fault? Also, is the algorithm for removeChar correct?
Here is my main function:
int main() {
char line[3][10] = {"pep", "rol", "rak"};
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
return 0;
}
Thanks in advance.
This code works on my compiler :
#include<stdio.h>
#include<conio.h>
#define MAX_LINE_LENGTH 1024
#define MAX_STR_LENGTH 4
void removeChar(char *str, char c) {
int i = 0;
int j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j]=0;
}
void convertStrings(char line[][MAX_STR_LENGTH]) { //change 1
for (int str = 0; str < MAX_LINE_LENGTH; ++str) {
for (int ch = 0; ch < MAX_STR_LENGTH; ++ch) {
if (line[str][ch] == 'r') {
removeChar(line[str], 'r');
}
}
}
}
int main() {
char line[3][MAX_STR_LENGTH] = {"pep", "rol", "rak"}; //change 2
printf("%s\n", line[1]);
convertStrings(line);
printf("%s\n", line[1]);
getch();
return 0;
}
It's because line[str][ch] doesn't exist for all the value you give to str and/or ch.
You should check the value of MAX_LINE_LENGTH and MAX_STR_LENGTH and be sure that they are right.
The seg fault may be because you are using the constants "MAX_LINE_LENGTH" and "MAX_STR_LENGTH" however there may have the line length or string length. I would use the length of the array for the variable str in the first for loop instead of "MAX_LINE_LENGTH" and the length of array[str] instead of "MAX_STR_LENGTH". Unless each array you are searching has "MAX_LINE_LENGTH" and each string has "MAX_LINE_LENGTH" you will get a set fault. Hope this helps!
EDIT: you can find the length of the array by dividing the size of the array and the size of the type of the element.
sizeof(array)/sizeof(array[0])
finding the size of the char pointer is basically the same process.
You are getting a segfault either because array line contains fewer than MAX_LINE_LENGTH string pointers, or because at least one of the pointed-to strings contains fewer than MAX_STR_LENGTH characters; more likely the latter.
Instead of assuming a fixed number of strings of fixed length, you would be better off passing the actual number of strings as an argument. Alternatively, you could add NULL as sentinel value at the end of the list.
Moreover, there is no reason whatever to assume that each string is a fixed length. Look for the terminating character ('\0') to recognize when you've reached the end. For example:
void convertStrings(char **line) {
for (char **l = line; *l != NULL; l += 1) {
for (int ch = 0; (*l)[ch]; ch += 1) {
if ((*l)[ch] == 'r') {
removeChar(*l, 'r');
}
}
}
}
Your removeChar() function looks ok.
Do note, however, that there are library functions that could help with this (e.g. strchr()), and that there are various efficiency improvements possible (such as passing to removeChar() only the string tail, starting at the first appearance of the character to remove).
You have the array
char line[3][10] = {"pep", "rol", "rak"};
When you pass it to a function, it gets converted into a pointer of type char(*)[10]. So change
void convertStrings(char **line) {
to
void convertStrings(char (*line)[10]) {
or
void convertStrings(char line[][10]) {
An array of arrays (2D array) cannot be converted to a pointer to a pointer(in this case, char**)
Another problem is that you mention that MAX_LINE_LENGTH is 1024 and MAX_STR_LENGTH is 4. This is wrong as the loop would iterate and you access invalid memory locations. You should make MAX_LINE_LENGTH as 3 and MAX_STR_LENGTH as 4 as there are 3 strings, each with 4 characters.
You can also pass these variables as parameters to the function convertStrings. Change add two more parameters in the declartion of convertStrings:
void convertStrings(char (*line)[10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
or
void convertStrings(char line[][10], int MAX_LINE_LENGTH, int MAX_STR_LENGTH) {
and call the function from main using
convertStrings(line, sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line)); // `/sizeof(**line)` is 1 and is not needed
A better way would be to use
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char line[][MAX_STR_LENGTH]) {
or
void convertStrings(int MAX_LINE_LENGTH, int MAX_STR_LENGTH, char (*line)[MAX_STR_LENGTH]) {
and call the function using
convertStrings(sizeof(line)/sizeof(*line), sizeof(*line)/sizeof(**line), line); // `/sizeof(**line)` is 1 and is not needed
so that you can avoid using the magic number 10 in your function.
You would've certainly got some warnings from your compiler. Pay attention to them. If you did not get warnings, crank up the warnings in your compiler and include warning flags ( like -Wall in GCC ).
BTW, You can look into the strchr function from string.h to find if a character exists in a string.
Why do you check if you encounter the 'r' character twice? (in both function)
checking once would be enough.
A function to detect the char, and a function to delete it?
I would have done it this way :
#include <string.h>
#include <stdio.h>
void convertStrings(char *line);
void removeChar(char *str);
int main(int argc, char *argv[]) {
if (argc == 2)
{
printf("%s\n", argv[1]);
convertStrings(argv[1]);
printf("%s\n", argv[1]);
}
return (0);
}
void convertStrings(char *line)
{
for (int i = 0; line[i] != '\0'; i++)
{
if (line[i] == 'r') removeChar(&(line[i]));
}
}
void removeChar(char *str)
{
int i;
i = 0;
while (str[i] != '\0')
{
str[i] = str[i + 1];
i++;
}
}
But here is another one solution with only one function :
void convertStringsbis(char *line)
{
int delta;
int i;
i = 0;
delta = 0;
while (line[i++ + delta] != '\0')
{
if (line[i + delta] == 'r')
delta++;
line[i] = line[i + delta];
}
}

Resources