I want to use this function to show lines from a file that starts with a string.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "RangeSelection.h"
bool RangeSelection(char * buffer, int len, char * argv[])
{
int i = 0, j, c;
char word[4];
bool is_break;
while((c = getchar()) != EOF)
{
is_break = false; //a variable for checking if instruction break was used
for(j = 0; j < 3; ++j) //load three first chars
{
word[j] = c;
c = getchar(); //to load chars into c
if(c == '\0' || c == EOF) //if there's less than 3 chars in this word, don't check it
{
is_break = true;
break;
} //if that's EOF or new line, break
}
if(!is_break)
{
word[3] = '\0';
}
if(strcmp(word, argv) == 0) //they're the same
{
printf("%c", word[0]);
printf("%c", word[1]);
printf("%c", word[2]);
do //do while as it will show the output at least three times
{
printf("%c", c); //print that char
}
while((c = getchar()) != '\0' && c != EOF);
}
else
{
while((c = getchar()) != '\0' && c != EOF) //load chars until a new line
{
;
}
}
}
return false;
}
But it doesn't work as I want to. Run with parameter "xxx" it has to show only lines starting with "xxx". For this input:
xxx
dasfdad
xxx works
x
it should print only:
xxx
xxx works
while it prints:
xxx
dasfdad
xxx works
x
However, while the input is like this one:
dasfdad
xxx works
x
It prints nothing although the program ought to show
xxx works
Char * argv[] is an argument provided by the user while running the program in a console(for example xxx). Thanks in advance.
Use memcmp() instead of strcmp() to make life much easier for yourself. The parameter len is never used in the RangeSelection() function. This should be removed unless it is needed for some future development. Unless the string indicated by buffer will be changed in the function, it would be good to use const char *buffer in the parameter list.
Also note that char *argv[] is converted to a pointer to a pointer to char in the function parameter list; I don't think that this is what is expected in the posted code. The function strcmp() expects pointers to char (pointers to the first elements of null-terminated character arrays), so the expression strcmp(word, argv) leads to undefined behavior due to type mismatch in the function call.
Here is an example program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool filter_line(const char * buffer, const char *tag)
{
bool is_tagged;
size_t tag_sz = strlen(tag);
if (strlen(buffer) < tag_sz) {
is_tagged = false;
} else {
is_tagged = !memcmp(buffer, tag, tag_sz);
}
return is_tagged;
}
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s line_tag\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *filter_tag = argv[1];
char line[4096];
while (fgets(line, sizeof line, stdin) != NULL) {
if (filter_line(line, filter_tag)) {
printf("%s", line);
}
}
return 0;
}
Sample interactions using text files as input:
test_filter_line.txt
xxx
dasfdad
xxx works
x
abc xxx
xxx
λ> ./line_filter xxx < test_filter_line.txt
xxx
xxx works
test_filter_line2.txt:
dasfdad
xxx works
x
λ> ./line_filter xxx < test_filter_line2.txt
xxx works
Your program prints the whole file when it starts with given pattern and prints nothing if it doesn't because you are not matching newline character \n at any time whereas you want to read your file line by line.
I would suggest you split the job into separate functions. This is how I would do it in C99 :
int starts_with(char *buf, char *pattern)
{
char *p = pattern;
for (int i = 0; i < strlen(pattern); i++)
{
if (!buf[i] || buf[i] != pattern[i])
return 0;
}
return 1;
}
Now you can store each line inside a buffer within your RangeSelection function and check if each buffer start with your pattern
Related
Update, Hello guys Thank you all for the help, my initial approach was wrong and I did not use ASCII codes at all.
Sorry for the late replay I had a half-day off today and made a new post for the complete code
there is no errors but the prgram is not working proberly ( this is an update of old post )
I wrote the program, and it is working with no errors But it is not giving me the results I wanted
My only problem is when I read a character how to check its ASCII and store it.
#include <stdio.h>
#include <string.h>
int main()
{
char dictionary[300];
char ch, temp1, temp2;
FILE *test;
test=fopen("HW2.txt","r");
for(int i=0;i<2000;i+=1)
{ ch=fgetc(test);
printf("%c",ch);
}
}
If we are talking about plain ASCII, values goes from 0 to 127, your table shoud look like:
int dictionary[128] = {0};
Regarding your question:
how to check its ASCII and store it
Consider a char being a tiny int, they are interchangeable and you don't need any conversion.
fgetc wants an int in order to handle EOF, and trying to read 2000 characters from a file containing less than 2000 bytes can have very bad consequences, to read the whole file:
int c;
while ((c = fgetc(test)) != EOF)
{
if ((c > 0) && (c < 128))
{
dictionary[c]++;
}
}
for (int i = 1; i < 128; i++)
{
if (dictionary[i] > 0)
{
printf("%c appeared %d times\n", i, dictionary[i]);
}
}
EDIT:
Rereading, I see that you want to store words, not chars, ok, then it's a bit more difficult but nothing terrible, do not limit yourself to 300 words, use dynamic memory:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// A struct to hold the words and the
// number of times it appears
struct words
{
size_t count;
char *word;
};
int main(void)
{
FILE *file;
file = fopen("HW2.txt", "r");
// Always check the result of fopen
if (file == NULL)
{
perror("fopen");
exit(EXIT_FAILURE);
}
struct words *words = NULL;
size_t nwords = 0;
char *word = NULL;
size_t nchars = 1;
size_t i;
int c;
// while there is text to scan
while ((c = fgetc(file)) != EOF)
{
if (isspace(c))
{
if (word != NULL)
{
// Search the word in the table
for (i = 0; i < nwords; i++)
{
// Found, increment the counter
if (strcmp(word, words[i].word) == 0)
{
words[i].count++;
free(word);
break;
}
}
// Not found, add the word to the table
if (i == nwords)
{
struct words *temp;
temp = realloc(words, sizeof(*temp) * (nwords + 1));
if (temp == NULL)
{
perror("realloc");
exit(EXIT_FAILURE);
}
words = temp;
words[nwords].word = word;
words[nwords].count = 1;
nwords++;
}
// Prepare the next word
word = NULL;
nchars = 1;
}
}
else
{
char *temp;
temp = realloc(word, nchars + 1);
if (temp == NULL)
{
perror("realloc");
exit(EXIT_FAILURE);
}
word = temp;
word[nchars - 1] = (char)c;
word[nchars++] = '\0';
}
}
for (i = 0; i < nwords; i++)
{
printf("%s appeared %zu times\n", words[i].word, words[i].count);
free(words[i].word);
}
free(words);
fclose(file);
return 0;
}
In C, characters are, essentially, their ASCII code (or rather, their char or unsigned char value). So once you read a character, you have its ASCII code already.
However, fgetc() doesn't always return the character it read for you; it may fail, for which reason it returns an int, not an unsigned char, which will be -1 in case of failure.
So:
You need to define an int variable to take the result of fgetc().
If it's not EOF, you can cast the result back into a unsigned char. That's your character, and it's ASCII value, at the same time.
PS - I'm ignoring non-ASCII characters, non-Latin languages etc. (But C mostly ignores them in its basic standard library functions too.)
I am a beginner in coding and having difficulty trying to take input from both command line as well as console(STDIN). my program is supposed to search and replace a group of characters from a string. For example, concatenate cat gat : the output must be congatenate!
This is my code so far!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*Function to replace a string with another string*/
char *rep_str(const char *s, const char *old, const char *new1)
{
char *ret;
int i, count = 0;
int newlen = strlen(new1);
int oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++)
{
if (strstr(&s[i], old) == &s[i])
{
count++;
i += oldlen - 1;
}
}
ret = (char *)malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s)
{
if (strstr(s, old) == s) //compare the substring with the newstring
{
strcpy(&ret[i], new1);
i += newlen; //adding newlength to the new string
s += oldlen;//adding the same old length the old string
}
else
ret[i++] = *s++;
}
ret[i] = '\0';
return ret;
}
int main(int argc, char*agrv[])
{
char mystr[100], c[10], d[10];
scanf("%s", mystr);
scanf(" %s",c);
scanf(" %s",d);
char *newstr = NULL;
newstr = rep_str(mystr, c,d);
printf("%s\n", newstr);
free(newstr);
return 0;
}
as for now, it shows correct output for either console input or commandline input, bur not both!
kindly suggest the changes to be made!
You can have a check on the variable argc of function int main().
// Path of executable file is passed by default so value of 'argc' will be at least 1
if(argc > 1)
{
// do stuff to work on input from command line
}else{
// do stuff to work on input from STDIN
}
Instead of trying to parse input file through argc and argv, simply pass all the input file through stdin. This means that you will always use scanf to read input data.
At command line you will need to call using pipes, something like this:
$ cat file.txt | yourprogram
I wrote a program in C, The expected result should be:
$ cat poem.txt
Said Hamlet to Ophelia,
I'll draw a sketch of thee,
What kind of pencil shall I use?
2B or not 2B?
$ ./censor Ophelia < poem.txt
Said Hamlet to CENSORED,
I'll draw a sketch of thee,
What kind of pencil shall I use?
2B or not 2B?
But I got this:
$ ./censor Ophelia < poem.txt
Said Hamlet tomlet CENSORED,
I'lllia drawlia arawlia sketcha ofetcha theecha,
Whatcha kindcha ofndcha pencila shallla Ihallla usellla?
2Bsellla orellla notllla 2Botllla?
I use tempWord to store every word and compare it with the word that needs to be censored. Then I use tempWord[0]='\0' to reset the temp String, so that I can do another comparison. But it seems not working. Can anyone help?
# include <stdio.h>
# include <string.h>
int compareWord(char *list1, char *list2);
int printWord(char *list);
int main(int argc, char *argv[]) {
int character = 0;
char tempWord[128];
int count = 0;
while (character != EOF) {
character = getchar();
if ((character <= 'z' && character >= 'a') ||
(character <= 'Z' && character >= 'A') ||
character == 39) {
tempWord[count] = character;
count++;
} else {
if (count != 0 && compareWord(tempWord, argv[1])) {
printf("CENSORED");
count = 0;
tempWord[0] = '\0';
}
if (count != 0 && !compareWord(tempWord, argv[1])) {
printWord(tempWord);
count = 0;
tempWord[0] = '\0';
}
if (count == 0) {
printf("%c", character);
}
}
}
return 0;
}
int printWord(char *list) {
// print function
}
int compareWord(char *list1, char *list2) {
// compareWord function
}
There are multiple issues in your code:
You do not test for end of file at the right spot: if getc() returns EOF, you should exit the loop immediately instead of processing EOF and exiting at the next iteration. The classic C idiom to do this is:
while ((character = getchar()) != EOF) {
...
For portability and readability, you should use isalpha() from <ctype.h> to check if the byte is a letter and avoid hardcoding the value of the value of the apostrophe as 39, use '\'' instead.
You have a potential buffer overflow when storing the bytes into the tempWord array. You should compare the offset with the buffer size.
You do not null terminate tempWord, hence the compareWord() function cannot determine the length of the first string. The behavior is undefined.
You do not check if a command line argument was provided.
The second test is redundant: you could just use an else clause.
You have undefined behavior when printing the contents of tempWord[] because of the lack of null termination. This explains the unexpected behavior, but you might have much worse consequences.
printWord just prints a C string, use fputs().
The compWord function is essentially the same as strcmp(a, b) == 0.
Here is a simplified and corrected version:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char tempWord[128];
size_t count = 0;
int c;
while ((c = getchar()) != EOF) {
if (isalpha(c) || c == '\'') {
if (count < sizeof(tempWord) - 1) {
tempWord[count++] = c;
}
} else {
tempWord[count] = '\0';
if (argc > 1 && strcmp(tempWord, argv[1]) == 0) {
printf("CENSORED");
} else {
fputs(tempWord, stdout);
}
count = 0;
putchar(c);
}
}
return 0;
}
EDIT: chux rightfully commented that the above code does not handle 2 special cases:
words that are too long are truncated in the output.
the last word is omitted if it falls exactly at the end of file.
I also realized the program does not handle the case of long words passed on the command line.
Here is a different approach without a buffer that fixes these shortcomings:
#include <ctype.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
const char *word = (argc > 1) ? argv[1] : "";
int count = 0;
int c;
for (;;) {
c = getchar();
if (isalpha(c) || c == '\'') {
if (count >= 0 && (unsigned char)word[count] == c) {
count++;
} else {
if (count > 0) {
printf("%.*s", count, word);
}
count = -1;
putchar(c);
}
} else {
if (count > 0) {
if (word[count] == '\0') {
printf("CENSORED");
} else {
printf("%.*s", count, word);
}
}
if (c == EOF)
break;
count = 0;
putchar(c);
}
}
return 0;
}
tempWord[0] = '\0';
It will not reset the variable to null. It just assign the '\0' to the first position. But The values which are assigned are still in memory only. Only the first position is assigned to '\0'. So, to reset the character array try the below.
memset(tempWord, 0, 128);
Add the above line instead of your tempWord[0] = '\0'.
And also this will solves you don't need to add the '\0' at end of each word. This itself will work. But for the first time your have to reset the character array using the same memset function. Before entering to the loop you have to set the tempWord to null using the memset function.
Using tempWord[0]='\0' will not reset the whole array, just the first element. Looking at your code, there are 2 ways you could go forward, either reset the whole array by using memset:
memset(tempWord, 0, sizeof tempWord);
or
memset(tempWord, 0, 128);
(or you can only clear it by the size of last word, also it needs string.h which you have already included),
Or you could just set the element after the length of 'current word' to be '\0' (ex, if current word is the then set tempWord[3]='\0', since strlen checks the string till null char only) which can be placed before those 2 ifs checking if the strings are equal or not, your new while loop will look like this:
{
character = getchar();
if((character<='z' && character>='a')||(character<='Z' && character>='A')||character == 39)
{
tempWord[count]=character;
count++;
}else {
tempWord[count]='\0';
if(count!=0 && compareWord(tempWord, argv[1]))
{
printf("CENSORED");
count=0;
}
if(count!=0 && !compareWord(tempWord, argv[1]))
{
printWord(tempWord);
count=0;
}
if (count==0)
{
printf("%c", character);
}
}
}
(it works, tested)
I had to rewrite two functions as per two exercises in a book I'm working from. One that simply reads a line of characters, readLine and another that compared two character strings and returned either 1 or 0 based on whether they match, 'equalStrings`.
The point of the exercise was to rewrite the functions so they used pointers, as opposed to arrays.
I've been struggling with prior exercises and was surprised how quickly I was able to do this so I'm concerned I'm missing something important.
Both programs compile and run as hoped though.
This is the original readLine function:
#include <stdio.h>
void readLine(char buffer[]);
int main(void)
{
int i;
char line[81];
for(i = 0; i < 3; i++)
{
readLine(line);
printf("%s\n\n", line);
}
return 0;
}
void readLine(char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
My edited with pointers:
#include <stdio.h>
void readLine(char *buffer);
int main(void)
{
int i;
char line[81];
char *pointer;
pointer = line;
for(i = 0; i < 3; i++)
{
readLine(pointer);
printf("%s\n\n", line);
}
return 0;
}
void readLine(char *buffer)
{
char character;
int i;
i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
Here is the original equalString function:
#include <stdio.h>
#include <stdbool.h>
bool equalStrings(const char s1[], const char s2[]);
int main(void)
{
const char stra[] = "string compare test";
const char strb[] = "string";
printf("%i\n", equalStrings(stra, strb));
printf("%i\n", equalStrings(stra, stra));
printf("%i\n", equalStrings(strb, "string"));
return 0;
}
bool equalStrings(const char s1[], const char s2[])
{
int i = 0;
bool areEqual;
while(s1[i] == s2[i] && s1[i] != '\0'){
i++;
if(s1[i] == '\0' && s2[i] == '\0')
areEqual = true;
else
areEqual = false;
}
return areEqual;
}
and the rewritten with pointers:
#include <stdio.h>
#include <stdbool.h>
bool equalStrings(const char *pointera, const char *pointerb);
int main(void)
{
const char stra[] = "string compare test";
const char strb[] = "string";
const char *pointera;
const char *pointerb;
pointera = stra;
pointerb = strb;
printf("%i\n", equalStrings(pointera, pointerb));
printf("%i\n", equalStrings(pointerb, pointerb));
printf("%i\n", equalStrings(strb, "string"));
return 0;
}
bool equalStrings(const char *pointera, const char *pointerb)
{
int i = 0;
bool areEqual;
while(pointera[i] == pointerb[i] && pointera[i] != '\0'){
i++;
if(pointera[i] == '\0' && pointerb[i] == '\0')
areEqual = true;
else
areEqual = false;
}
return areEqual;
}
Is there anything glaring out that needs to be changed?
Thank you.
There are (3) conditions you need to protect against in your readline function. (1) you must protect against writing beyond the end of your array. Utilizing a simple counter to keep track of the number of characters added will suffice. You can express this limit in your read loop. Your array size is 81 (which will hold a string of 80 characters +1 for the nul-terminating character. Assuming you create a #define MAXC 81 for use in your code, your first condition could be written as:
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && ...
(2) the second condition you want to protect against is reaching a '\n' newline character. The second condition for your read loop could be written as:
while (i + 1 < MAXC && (c = getchar()) != '\n' && ...
(3) the third condition you must protect against is encountering EOF with a line before a newline character is reached (many editors produce files with non-POSIX line-endings). With the final condition, your complete set of test conditions could look like the following:
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF)
(and that is why c must be signed (and should be a signed int), because EOF is generally -1)
Putting that together, with what it appears was intended in rewriting the function from using array-index notation to using pointer notation, you could do something like the following:
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF) {
*buffer++ = c;
i++;
}
*buffer = 0;
if (i + 1 == MAXC && *(buffer - 1) != '\n')
fprintf (stderr, "warning: line truncation occurred.\n");
}
You should also check, as shown above, whether you read all the characters in the line, or whether a short-read occurred (meaning after reading 80 allowable characters, there were still more characters in the line to be read, but to prevent writing beyond the end of your array, and leaving room for the terminating nul, you stopped reading before your reached the newline). You are free to handle it as you like, but be aware -- those characters still exist in the input buffer (stdin here) and will be the very next characters read on your next call to getchar(). So you may want a way to tell if that occurred.
Putting the function together in a short example with a helpful input file will help explain.
#include <stdio.h>
#define MAXC 81
void readline(char *buffer);
int main(void) {
int i;
char line[MAXC] = "", *pointer = line;
for(i = 0; i < 3; i++) {
readline (pointer);
printf ("%s\n\n", line);
}
return 0;
}
void readline (char *buffer)
{
int i = 0, c;
while (i + 1 < MAXC && (c = getchar()) != '\n' && c != EOF) {
*buffer++ = c;
i++;
}
*buffer = 0;
if (i + 1 == MAXC && *(buffer - 1) != '\n')
fprintf (stderr, "warning: line truncation occurred.\n");
}
How will your function behave if given a 90 character line to read?
Input File
Two lines with 90 characters each.
$cat dat/90.txt
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
Example Use/Output
Note what has occurred. On the first read attempt, 80 character were read, and a short read occurred. You were warned of that fact. The second read, read the reamining 10 characters in the first line (chars 81-90). The third, and final, read, again reads the first 80 chars of the second line and the code terminates.
$ ./bin/getchar_ptr <dat/90.txt
warning: line truncation occurred.
12345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890
warning: line truncation occurred.
12345678901234567890123456789012345678901234567890123456789012345678901234567890
I'll let you look this over and incorporate any of the suggestions you find helpul in the rest of your code. Let me know if you have any questions. Make sure you fully undetstand what is being passed as buffer in void readline (char *buffer) (copy as opposed to original) as basic pointer understandin has implications throughout 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];
}
}