Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need a help with a program (without using strtok() function) that should be doing this:
If the input is
car;dog;pet;elephant
and if the argument is 2, the ouput should be:
car;pet;elephant
if the argument is 4, the output should be:
car;dog;pet
and so on.
I've tried a lot of different solutions but nothing seems to work. So if anybody could help me, I would be really glad.
Thank you.
I think this solution always works with valid input.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc != 3)
return 1;
int x = atoi(argv[2]);
char *s = argv[1], *d = argv[1];
while (*s)
{
if (x == 0)
{
--x;
while (*s && *s != ';')
++s;
if (*s)
++s;
else
break;
}
if (*s == ';')
--x;
*d++ = *s++;
}
if (*(d - 1) == ';')
*(d - 1) = '\0';
else
*d = '\0';
puts(argv[1]);
return 0;
}
Here is a function to construct a new csv line with the field number pos (1-based) removed:
#include <stdlib.h>
#include <string.h>
char *removeField(const char *str, char delim, int pos)
{
char *out;
const char *p, *q;
size_t len1, len2;
int i, nsep = 0;
if (str == NULL)
return NULL;
/* skip the fields before the target field */
for (p = str, i = 1; *p && i < pos; i++) {
while (*p && *p != delim)
p++;
if (*p == delim) {
p++;
nsep++;
}
}
/* skip the field to remove */
for (q = p; *q && *q != delim; q++)
continue;
if (*q == delim) {
/* if there are more fields, skip the delimiter */
q++;
} else {
/* otherwise remove the trailing delimiter if the removed field was
the last one but not the first one */
if (pos > 1 && nsep == pos - 1)
p--;
}
/* allocate the exact amount of bytes */
len1 = p - str;
len2 = strlen(q);
out = malloc(len1 + len2 + 1);
if (out != NULL) {
/* copy the left and right parts */
memcpy(out, str, len1);
memcpy(out + len1, q, len2 + 1);
}
/* return the new CSV line or NULL if allocation failure */
return out;
}
Here is the function removing the substring from the "csv style" line. It takes info the account empty strings and (probably most as I did not properly test it) border cases.
It is not using "heavy" string functions like strtok or strdup as I believe this exercise is to write it using arrays or pointers.
char *dupAndDelete(const char *str, char delim, int pos)
{
char *out = NULL;
int cpos = 1;
if(str)
{
out = malloc(strlen(str) + 1);
char *wrk = out;
if(out)
{
while(*str)
{
if(cpos == pos)
{
while(*str && *str != delim)
str++;
}
else
{
*wrk++ = *str;
}
if(*str == delim)
{cpos++;}
if(*str) str++;
}
if(wrk > out)
if(*(wrk - 1) == delim && cpos == pos)
wrk--;
*wrk = 0;
}
}
return out;
}
int main(void)
{
char *str = ";;car;;dog;pet;elephant;;";
char *output;
for(int pos = 0; pos < 12; pos++)
{
output = dupAndDelete(str, ';', pos);
if(output) printf("pos = %2d str = \"%s\"\n", pos, output);
fflush(stdout);
free(output);
}
return 0;
}
You can search a ; with strchr()
This code searches the index you want to remove (1-based indexes)
int main(void)
{
for (size_t i = 0; i < 6; i++)
{
// This is you argument
int arg2 = i;
printf("%ld: ", i);
char *s = strdup(";car;dog;pet;elephant");
char *curr = s;
for (int i = 0; curr && i < arg2; i++)
curr = strchr(curr + 1, ';');
if (!curr)
{
printf("%s\n", s);
free(s);
continue;
}
char *next = strchr(curr + 1, ';');
if (!next)
{
*curr = 0;
}
else
{
size_t offset = next - curr;
size_t len = strlen(s);
for (size_t i = curr - s; i < len; i++)
s[i] = (i + offset < len ? s[i + offset + (curr == s)] : 0);
}
printf("%s\n", s);
free(s);
}
return 0;
}
Without any control/argument inspection, I think this is what you're looking for:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
if (argc < 3) {
printf("Argument missing!\n");
return 1;
}
char * output = calloc(sizeof(char), strlen(argv[1]));
int cnt = 1;
int memb = atoi(argv[2]);
int outputp = 0;
char* token = strtok(argv[1], ";");
while (token != NULL) {
if (cnt != memb) {
strcat(output+outputp, token);
outputp += strlen(token);
strcat(output+outputp, ";");
outputp++;
}
token = strtok(NULL, ";");
cnt++;
}
output[outputp-1] = '\0';
printf("%s\n", output);
free(output);
return 0;
}
use:
$ ./a.out "car;dog;pet;elephant" 2
car;pet;elephant
$ ./a.out "car;dog;pet;elephant" 4
car;dog;pet
Edit: you can use strsep() instead of strtok(), then if your substring is empty, that will counts too:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
if (argc < 3) {
printf("Argument missing!\n");
return 1;
}
char * output = calloc(sizeof(char), strlen(argv[1])+1);
int cnt = 1;
int memb = atoi(argv[2]);
int outputp = 0;
char * token;
while ((token = strsep(&argv[1], ";")) != NULL) {
printf("'%s'\n", token);
if (cnt != memb) {
strcat(output+outputp, token);
outputp += strlen(token);
strcat(output+outputp, ";");
outputp++;
}
cnt++;
}
output[outputp-1] = '\0';
printf("%s\n", output);
free(output);
return 0;
}
Related
I had a assignment for my class last week where I had to split a string with the spaces, tabs et \n as separators and store every "word" in an array. I think I'm very close but my output is very weird so if someone could tell what did I forget, it would be nice. Only thing is I can only use malloc.
char **ft_split_whitespaces(char *str)
{
int i;
int j;
int k;
char **tab;
i = 0;
j = 0;
k = 0;
tab = (char**)malloc(sizeof(*tab) * (ft_nb_words(str) + 1));
while (str[i])
{
while (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
i++;
if (str[i])
{
if ((tab[j] = (char*)malloc(sizeof(char) * (ft_len_word(str + i) + 1))) == NULL)
return (NULL);
while (k < ft_len_word(str + i))
tab[j][k++] = str[i++];
tab[j++][k] = '\0';
k = 0;
}
}
tab[j] = NULL;
return (tab);
}
The functions returning the length of a word and the number of words work fine so I think the problem comes from the main function.
This can be easily handled if you take one pointer to point the last occurrence of specific character('' '\n' \t).
char **ft_split_whitespaces(char *str)
{
int i;
int j;
int k;
char **tab;
char *prevToken=str;
i = 0;
j = 0;
k = 0;
tab = (char**)malloc(sizeof(*tab) * (ft_nb_words(str) + 1));
while (str[i] != '\0')
{
if(str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
{
i++;
if ((tab[j] = (char*)malloc(sizeof(char) * (ft_len_word(prevToken) + 1))) == NULL)
return (NULL);
while (k < ft_len_word(prevToken) &&
(prevToken[k] !=' ' && prevToken[k] != '\t' && prevToken[k] != '\n'))
tab[j][k] = prevToken[k++];
printf("tab=%s\n", tab[j]);
k = 0;
j++;
prevToken=(str+i);
}
else{
i++;
}
}
/* to handle the last word */
if ((tab[j] = (char*)malloc(sizeof(char) * (ft_len_word(prevToken) + 1))) == NULL)
return (NULL);
while (k < ft_len_word(prevToken) &&
(prevToken[k] !=' ' && prevToken[k] != '\t' && prevToken[k] != '\n'))
tab[j][k] = prevToken[k++];
printf("tab=%s\n", tab[j]);
tab[j] = NULL;
return (tab);
}
The following code contains an implementation of some useful C functions.
The function you search is strtok(). In the code are implemented also the functions strspn() and strpbrk() because strtok() uses them.
The best way to solve this kind of problems is to study the implementation of C standard functions.
The code stores the copies of max 100 token (the extracted words).
You have to remember that the function strtok() modifies the content of the source string inserting '\0' to terminate the strings found.
The functions here implemented are:
mystrtok()
mystrspn()
mystrpbrk()
The code:
#include <stdio.h>
#include <string.h> /* for the use of strcpy fn */
#include <malloc.h>
char * mystrtok (char * s, char * delim);
size_t mystrspn (const char *s, const char *accept);
char * mystrpbrk (const char *s, const char *accept);
char * mystrpbrk (const char *s, const char *accept)
{
while (*s != '\0')
{
const char *a = accept;
while (*a != '\0')
if (*a++ == *s)
return (char *) s;
++s;
}
return NULL;
}
size_t mystrspn (const char *s, const char *accept)
{
const char *p;
const char *a;
size_t count = 0;
for (p = s; *p != '\0'; ++p)
{
for (a = accept; *a != '\0'; ++a)
if (*p == *a)
break;
if (*a == '\0')
return count;
else
++count;
}
return count;
}
char * mystrtok (char *s, char *delim)
{
char *token;
static char *olds;
if (s == NULL) {
s = olds;
}
/* Scan leading delimiters. */
s += mystrspn (s, delim);
if (*s == '\0')
{
olds = s;
return NULL;
}
/* Find the end of the token. */
token = s;
s = mystrpbrk (token, delim);
if (s == NULL)
{
/* This token finishes the string. */
while(*olds)
olds++;
}
else
{
/* Terminate the token and make OLDS point past it. */
*s = '\0';
olds = s + 1;
}
return token;
}
int main(void)
{
char str[] = "I have an orange\tYou have some bananas\nShe has three pineapples\n";
char * x = NULL;
int cnt=0,i;
char **store;
/* Stores a max of 100 strings */
store = malloc(sizeof(char *)*100);
/* The total space for the tokens is
max the entire string + '\0' */
store[0] = malloc(strlen(str)+1);
/* Extract the first token */
x=mystrtok(str," \n");
while(x) {
printf("Storing %s\n",x);
/* Store a copy of the token */
strcpy(store[cnt],x);
store[cnt+1]=store[cnt]+strlen(x)+1;
cnt++;
/* extract the next token */
x=mystrtok(NULL," \n\t");
}
for(i=0;i<cnt;i++)
printf("Stored %s\n",store[i]);
free(store[0]);
free(store);
return 0;
}
Your code is inefficient as you call ft_len_word far too many times, but it does not seem broken apart from the undefined behavior on malloc failures.
The problem might lie in your versions of ft_len_word or ft_nb_words. You should post a full program exhibiting the problem for a proper investigation.
Here is a modified version that does not use these functions:
#include <stdlib.h>
int ft_is_space(char c) {
return (c == ' ' || c == '\t' || c == '\n');
}
char **ft_split_whitespaces(const char *str) {
int i, j, k, len, in_space, nb_words;
char **tab;
nb_words = 0;
in_space = 1;
for (i = 0; str[i]; i++) {
if (ft_is_space(str[i]) {
in_space = 1;
} else {
nb_words += in_space;
in_space = 0;
}
}
tab = malloc(sizeof(*tab) * (nb_words + 1));
if (tab != NULL) {
i = 0;
j = 0;
while (str[i]) {
while (ft_is_space(str[i]))
i++;
if (str[i]) {
for (len = 1; str[i + len] && !ft_is_space(str[i + len]); len++)
continue;
if ((tab[j] = malloc(sizeof(*tab[j]) * (len + 1))) == NULL) {
while (j > 0)
free(tab[--j]);
free(tab);
return NULL;
}
for (k = 0; k < len; k++)
tab[j][k] = str[i + k];
tab[j++][len] = '\0';
i += len;
}
}
tab[j] = NULL;
}
return tab;
}
You need to implement your version of strtok() if you do not want to use the library function or need a different functionality than the one provided by strtok().
Below is a simple string tokenizer, which, unlike the standard library's strtok(), still returns a value in case of consecutive delimiters. I used this function to parse CSV files, which sometimes include empty cells, hence consecutive , characters. Standard library's strtok() did not work for me, so I had to implement my own function.
I used other helper functions, which are now part of a simple string library I maintain on GitHub, called zString.
Below is how it behaves
Example Usage
char str[] = "A,B,,,C";
printf("1 %s\n",zstring_strtok(s,","));
printf("2 %s\n",zstring_strtok(NULL,","));
printf("3 %s\n",zstring_strtok(NULL,","));
printf("4 %s\n",zstring_strtok(NULL,","));
printf("5 %s\n",zstring_strtok(NULL,","));
printf("6 %s\n",zstring_strtok(NULL,","));
Example Output
1 A
2 B
3 ,
4 ,
5 C
6 (null)
and the code
char *zstring_strtok(char *str, const char *delim) {
static char *static_str=0; /* var to store last address */
int index=0, strlength=0; /* integers for indexes */
int found = 0; /* check if delim is found */
/* delimiter cannot be NULL
* if no more char left, return NULL as well
*/
if (delim==0 || (str == 0 && static_str == 0))
return 0;
if (str == 0)
str = static_str;
/* get length of string */
while(str[strlength])
strlength++;
/* find the first occurrence of delim */
for (index=0;index<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignment requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '\0';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
{
char str[1000], *arr;
int i = 0,len,counter=0,j=0;
arr = (char*)malloc((sizeof(char*) * 1000));
for (i = 0; str[i] != '\0'; i++)
{
str[i] = getchar();
if (str[i] == ' ')
{
str[i] = '\0';
arr[j] = malloc(sizeof(char)*counter);
strcpy_s(&arr[j], counter * sizeof(char), &str[i - counter]);//i dont know why but this line does me some problems
j++;
counter = 0;
}
counter++;
}
}
I am trying to create an array of strings but the strcpy is not letting me and i do not know why. help will be much appreciated.
This error is because str[i - counter] is a char, not a pointer. You need to write &str[i - counter] or (str + i - counter).
See the signature of strcpy_s: errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int count_spaces(char *str)
{
int count = 0;
if (str == NULL || strlen(str) == 0)
return (0);
int i = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return count++;
}
char **get_strings(char *str)
{
if (str == NULL || strlen(str) == 0)
return NULL;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL || (dest[0] = malloc(sizeof(char) * (strlen(str) + 1))) == NULL)
return NULL;
int i = 0, j = 0, k = 0;
while (str[i])
{
if (str[i] == ' ')
{
dest[k][j] = '\0';
j = 0;
dest[++k] = malloc(sizeof(char) * (strlen(str) + 1));
}
else
dest[k][j++] = str[i];
i++;
}
dest[k + 1] = NULL;
return dest;
}
int main()
{
char **dest;
dest = get_strings("this is a test for stackoverflow");
int i = 0;
while (dest[i] != NULL)
printf("%s\n", dest[i++]);
}
here is a quick (non-perfect) example to do it with char **
you give a string as parameter and the function will store each segment using space as delimiter in a char **
you can print it as i did in the main. Don't forget to free when you're done
I have problem with my alignement. This time I want my program to return words that ends and starts with the same letter. I've wrote something like this, but it seems to return random words.
#include <stdio.h>
#include <string.h>
void main()
{
char str[100];
int i, t, j, len;
printf("Enter a string : ");
scanf("%[^\n]s", str);
len = strlen(str);
str[len] = ' ';
for (t = 0, i = 0; i < strlen(str); i++)
{
if ((str[i] == ' ') && (str[i - 1] == str[0]))
{
for (j = t; j < i; j++)
printf("%c", str[j]);
t = i + 1;
printf("\n");
}
else
{
if (str[i] == ' ')
{
t = i + 1;
}
}
}
}
You can use strtok to split the strings from stdin, then apply a letter checker on each parsed word one at a time.
Something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
int is_start_end(char *word);
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
char str[MAXCHAR];
char *word;
char **all_words;
int words_size = 1, word_count = 0;
int i, found;
all_words = malloc(words_size * sizeof(*all_words));
exit_if_null(all_words, "initial Allocation");
printf("Enter words(enter empty line to terminate):\n");
while (fgets(str, MAXCHAR, stdin) != NULL && strlen(str) != 1) {
word = strtok(str, " \n");
while (word !=NULL) {
if (words_size == word_count) {
words_size *= 2;
all_words = realloc(all_words, words_size * sizeof(*all_words));
exit_if_null(all_words, "Reallocation");
}
all_words[word_count] = malloc(strlen(word)+1);
exit_if_null(all_words[word_count], "Initial Allocation");
strcpy(all_words[word_count], word);
word_count++;
word = strtok(NULL, " \n");
}
}
printf("Words that have equal first and last letters:\n");
found = 0;
for (i = 0; i < word_count; i++) {
if (is_start_end(all_words[i])) {
found = 1;
printf("%s\n", all_words[i]);
}
free(all_words[i]);
all_words[i] = NULL;
}
if (found == 0) {
printf("None Found\n");
}
free(all_words);
all_words = NULL;
return 0;
}
int
is_start_end(char *word) {
int len;
len = strlen(word);
if ((len == 1) || (tolower(word[0]) == tolower(word[len-1]))) {
return 1;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
This line removes the null terminator of the string:
len = strlen(str);
str[len] = ' ';
thus the string no longer exists, what is left is just an ordinary array of characters.
The next call to strlen, in the body of the for loop, will cause undefined behavior.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Right now I can replace the word indifferent in the given string with nonchalant but I need to make this function dynamic so indifferent can be replaced with any word. I know i need to use malloc to create a new array that will hold my original string with the new word but don't have a strong understanding of how to use malloc yet, Please explain how to use malloc properly in this situation. Thank you.
#include <stdio.h>
#include <stdlib.h>
int findPosition(char string[], char sub[]) {
int i = 0;
int j = 0;
int f = 0;
for (i = 0; string[i] != '\0'; i++) {
if (sub[j] == string[i]) {
if (sub[j + 1] == '\0') {
f = 1;
break;
}
j++;
} else
j = 0;
}
if (f == 1) {
return i - j;
}
return -1;
}
int findLength(char sub[]) {
int i = 0;
for (i = 0; sub[i] != '\0'; i++) {
}
return i;
};
void replaceWord(char string[], char sub[], char replace[]) {
int i = 0;
int j = 0;
int p = findPosition(string, sub);
int l = findLength(sub);
int k = p + l - 1;
for (i = p; i < k; i++) {
string[i] = replace[j];
j++;
}
while(string[k] != '\0') {
string[k] = string[k + 1];
k++;
}
}
int main(int argc, const char *argv[]) {
char stringArray[120] = "\"Mr.Fay, is this going to be a battle of wits? \""
"\t\"If it is,\" was the indifferent retort, \""
"you have come unarmed!\"";
replaceWord(stringArray, "indifferent", "nonchalant");
int i = 0;
while (stringArray[i] != '\0') {
printf("%c", stringArray[i]);
i++;
}
return 0;
};
You can use malloc to allocate memory for the new string where you replace each occurrence of one word with another word:
#include <stdio.h>
#include <stdlib.h>
/* use a local implementation of the string functions: */
size_t my_strlen(const char *s) {
size_t len;
for (len = 0; s[len] != '\0'; len++)
continue;
return len;
}
void *my_memcpy(void *dest, const void *src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((unsigned char*)dest)[i] = ((unsigned char*)src)[i];
}
return dest;
}
char *my_strdup(const char *s) {
size_t n = my_strlen(s) + 1;
char *p = malloc(n);
if (p) my_memcpy(p, s, n);
return p;
}
char *my_strstr(const char *s1, const char *s2) {
for (;; s1++) {
for (size_t i = 0;; i++) {
if (s2[i] == '\0') return s1;
if (s1[i] != s2[i]) break;
}
if (*s1 == '\0') return NULL;
}
}
char *replaceWord(const char *str, const char *s1, const char *s2) {
char *res = my_strdup(str); /* return value is always allocated */
char *p, *q;
size_t offset = 0;
size_t len = my_strlen(str);
size_t len1 = my_strlen(s1);
size_t len2 = my_strlen(s2);
if (len1 == 0)
return res;
while ((p = my_strstr(res + offset, s1)) != NULL) {
offset = p - res;
if (len1 == len2) {
/* no need to reallocate, replace in place */
my_memcpy(res + offset, s2, len2);
} else {
/* allocate a new array with the adjusted length */
q = malloc(len + len2 - len1 + 1);
/* copy the beginning of the string */
my_memcpy(q, res, offset);
/* copy the replacement string */
my_memcpy(q + offset, s2, len2);
/* copy the remainder of the string, and the final '\0' */
my_memcpy(q + offset + len2, res + offset + len1, len - offset - len1 + 1);
/* free the previous string */
free(res);
res = q;
}
/* search for matches from the end of the replacement */
offset += len2;
}
return res;
}
int main(int argc, const char *argv[]) {
char stringArray[120] = "\"Mr.Fay, is this going to be a battle of wits? \""
"\t\"If it is,\" was the indifferent retort, \""
"you have come unarmed!\"";
char *p = replaceWord(stringArray, "indifferent", "nonchalant");
printf("%s", p);
free(p);
return 0;
}