First occurrence return with strstr function - c

Following on from my previous question, it now appears that my code only outputs the first occurrence of cArray from cInput. Is there a way to get strstr to return all of the occurrences instead of stopping the program at the first? Much appreciated.
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0
Edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main() {
char *cArray[MAX_STR_LEN] = { "example", "this", "is", "an" };
char cInput[MAX_STR_LEN] = { 0 };
int y = 0;
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
cInput[strlen(cInput) - 1] = 0; /* strip newline from input */
printf("\nInitialised string array:\n");
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
{
char *ep = strchr (ptr, ' ');
if (ep) *ep = 0; /* null-terminate at space */
printf("%s\n", ptr++);
if (ep) *ep = ' '; /* put the space back */
}
y++;
}
return 0;
}
New output:
Type your message:
this is an example
Initialised string array:
example
this
is
is
an
Program ended with exit code: 0

here is the corrected program:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = { "example", "this" };
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
printf("Initialised string array:\n");
for (int y = 0; y <= 1; y++){
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL){
strncpy(cOutput, ptr, strlen(cArray[y]));
printf("[%d] - %s\n", y, cOutput);
memset(cOutput, 0, sizeof(cOutput));
ptr++;
}
}
getchar();
return 0;
}
Changes:
Used memset to reset the cOutput array so that during comparison
in the next iteration, it was empty.
Used the index y to keep track of each word from the array
Chagned array range from y<1 to y<=1

In addition to the other answers, here is a variation that eliminates intermediate variables and rearranges the loop logic slightly. There are many ways to approach the issue of returning all occurrences of strstr matches, so you have flexibility to use any manner that fits your needs:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main() {
char *cArray[MAX_STR_LEN] = { "example", "this" };
char cInput[MAX_STR_LEN] = { 0 };
int y = 0;
printf("Type your message:\n");
fgets(cInput, MAX_STR_LEN, stdin);
cInput[strlen(cInput) - 1] = 0; /* strip newline from input */
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
printf("\nInitialised string array:\n%s\n", ptr++);
y++;
}
return 0;
}
output:
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
my example of this example for fun
Initialised string array:
example of this example for fun
Initialised string array:
example for fun
Initialised string array:
this example for fun
To isolate only the word matching in cArray, you can use strchr to test if a space remains in the input string following the pointer returned the strstr. If so, just null-terminate the string where the next space appears which will isolate just the searched for word. If I misunderstood the comment, just leave another, I'm happy to help. (code changes only)
while (cArray[y])
{
char * ptr = cInput;
while ((ptr = strstr(ptr, cArray[y])) != NULL)
{
char *ep = strchr (ptr, ' ');
if (ep) *ep = 0; /* null-terminate at space */
printf("\nInitialised string array:\n%s\n", ptr++);
if (ep) *ep = ' '; /* put the space back */
}
y++;
}
isolated output:
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
my example of this example for fun
Initialised string array:
example
Initialised string array:
example
Initialised string array:
this
Here is a bit of code to look at whole words only using the inch-worm method. I haven't had a lot of time to look at all potential gotchas, but this should get you going. Just replace the code in your last version:
while (cArray[y])
{
char *ptr = cInput;
char *ep = NULL;
while ((ep = strchr (ptr, ' '))) /* set end-pointer to each space in input */
{
*ep = 0; /* null-terminate and compare word */
if (strcmp (ptr, cArray[y]) == 0)
printf("\nInitialised string array:\n%s\n", ptr);
*ep = ' '; /* restore space in string */
ptr = ++ep; /* set pointer to next char after space */
}
if (strcmp (ptr, cArray[y]) == 0) /* compare last word in input */
printf("\nInitialised string array:\n%s\n", ptr);
y++;
}
output w/updated cArray
alchemy:~/dev/src-c/tmp> ./bin/strstrmulti
Type your message:
this is an example to test the example for fun
Initialised string array:
example
Initialised string array:
example
Initialised string array:
this
Initialised string array:
is
Initialised string array:
an

Related

How can i add a character after every word in a string?

So what i have is a string(str) that i get from fgets(str, x, stdin);.
If i write for example "Hello World" i want to be able to add a character infront of each word in the string.
To get this "Hello? World?" as an example. I think i've made it alot harder for myself by trying to solve it this way:
add(char *s, char o, char c){
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != o) {
s[j] = s[i];
}
else {
s[j] = c;
}
j++;
}
}
add(str, ' ','?');
printf("\n%s", str);
This will read out "Hello?World" without the spaces. Now the only way i see this working is if i move everything after the first "?" one to the right while also making the positon of the "W" to a space and a "?" at the end. But for much longer strings i can't see myself doing that.
You can't safely extend a string with more characters without insuring the buffer that holds the string is big enough. So let's devise a solution that counts how many additional characters are needed, allocate a buffer big enough to hold a string of that length, then do the copy loop. Then return the new string back to the caller.
char* add(const char* s, char o, char c)
{
size_t len = strlen(s);
const char* str = s;
char* result = NULL;
char* newstring = NULL;
// count how many characters are needed for the new string
while (*str)
{
len += (*str== o) ? 2 : 1;
str++;
}
// allocate a result buffer big enough to hold the new string
result = malloc(len + 1); // +1 for null char
// now copy the string and insert the "c" parameter whenever "o" is seen
newstring = result;
str = s;
while (*str)
{
*newstring++ = *str;
if (*str == o)
{
*newstring++ = c;
}
str++;
}
*newString = '\0';
return result;
}
Then your code to invoke is as follows:
char* newstring g= add(str, ' ','?');
printf("\n%s", newstring);
free(newstring);
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "Hello World";
for(char* word = strtok(text, " .,?!"); word; word = strtok(NULL, " .,?!"))
printf("%s? ", word);
return 0;
}
Example Output
Success #stdin #stdout 0s 4228KB
Hello? World?
IDEOne Link
Knowing the amount of storage available when you reach a position where the new character will be inserted, you can check whether the new character will fit in the available storage, move from the current character through end-of-string to the right by one and insert the new character, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
...
(note: the string must be mutable, not a string-literal, and have additional storage for the inserted character. If you need to pass a string-literal or you have no additional storage in the current string, make a copy as shown by #Selbie in his answer)
Putting together a short example with a 1024-char buffer for storage, you can do something like:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
int main (void) {
char buf[MAXC];
if (!fgets (buf, MAXC, stdin))
return 1;
buf[strcspn(buf, "\n")] = 0;
puts (add (buf, ' ', '?'));
}
Example Use/Output
$ ./bin/str_replace_c
Hello World?
Hello? World?
Look things over and let me know if you have questions.
Just for fun, here's my implementation. It modifies the string in-place and in O(n) time. It assumes that the char-buffer is large enough to hold the additional characters, so it's up to the calling code to ensure that.
#include <stdio.h>
void add(char *s, char o, char c)
{
int num_words = 0;
char * p = s;
while(*p) if (*p++ == o) num_words++;
char * readFrom = p;
char * writeTo = p+num_words;
char * nulByte = writeTo;
// Insert c-chars, iterating backwards to avoid overwriting chars we have yet to read
while(readFrom >= s)
{
*writeTo = *readFrom;
if (*writeTo == o)
{
--writeTo;
*writeTo = c;
}
writeTo--;
readFrom--;
}
// If our string doesn't end in a 'c' char, append one
if ((nulByte > s)&&(*(nulByte-1) != c))
{
*nulByte++ = c;
*nulByte = '\0';
}
}
int main(int argc, char ** argv)
{
char test_string[1000] = "Hello World";
add(test_string, ' ','?');
printf("%s\n", test_string);
return 0;
}
The program's output is:
$ ./a.out
Hello? World?

Substring replace

I want to implement a c code such that it replaces only the exact matching not part of another string.
check out my code.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simpled simple string";
char * pch;
char str1[]= "simple";
pch = strstr (str,str1);
strncpy (pch,"sample",6);
puts (str);
return 0;
}
the above code gives the output : This is sampled simple string
I want the output to be : This is simpled sample string
please help
Thanks.
The best way to deal with these types of question is consider each and every word one-by-one. And then check whether, the pattern (which we are looking for?) is present in the given string or not, if yes then replace it with replacing word.
Below is my code. (I know it may seem bit odd one out, but trust me it will work for any pattern-matching and replacement problem). It will reduce and expand the final output according to the given pattern word and its corresponding replacement word.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
/* This program will replace the "demo" with "program" */
char input[] = " isdemo Hello this is demo. replace demo with demoes something else demo";
char pattern[] = "demo";
char replace[] = "program";
char output[105];
int index = 0;
/*Read the the input line word-by-word,
if the word == pattern[], then replace it else do nothing */
for(int i=0; i<strlen(input);) {
while(i<strlen(input) && !isalpha(input[i])) {
output[index++] = input[i++];
}
char temp[105]; int j = 0;
while(i<strlen(input) && isalpha(input[i])) {
temp[j++] = input[i++];
}
temp[j] = 0;
if(strcmp(temp, pattern) == 0) {
strncpy(output+index, replace, strlen(replace));
index += strlen(replace);
} else {
strncpy(output+index, temp, strlen(temp));
index += strlen(temp);
}
}
output[index] = 0;
puts(output);
return 0;
}
If i'm still missing any test case. I will be pleased to know about it.
First, you need search the entire string continuously until no substring is found, second, you need check the char before and after the substring returned by strstr, to make sure that the found substring is a complete word. When check for word boundary, take special care when the word is at the beginning or end of the longer string. For example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] ="simple simples is a simpled simple string simple";
char *s = str;
char *pch = str;
char str1[]= "simple";
int len = strlen(str1);
int pos;
while (1) {
pch = strstr(s, str1);
if (!pch) // no more occurrences of str1, quit
break;
pos = pch - str;
if (pos == 0) { // if it's the beginning
if (!isalpha(pch[len])) {
strncpy(pch, "sample", 6);
}
} else { // check two ends
if (!isalpha(*(pch-1)) && !isalpha(*(pch+len))) {
strncpy(pch, "sample", 6);
}
}
s = pch + len;
}
puts(str);
return 0;
}
I updated my code.This deals with the replacement that you want.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void replace(char *buf, size_t bufSize, const char *word_to_replace, const char *replacement_word);
int main(void)
{
char str[100] = "simple Asimple simpleB This is a simpled simple string and simple is good sometimes!, simple";
replace(str, sizeof(str), "simple", "sample");
printf("%s\n", str);
return 0;
}
void replace(char *buf, size_t bufSize, const char *word_to_replace, const char *replacement_word)
{
size_t buf_len = strlen(buf), word_len = strlen(word_to_replace);
char *ptr = strstr(buf, word_to_replace);
if (ptr == NULL) {
fprintf(stderr, "Could not find matches.\n");
return;
}
bool _G = 0;
char *tmp = (char *)malloc(bufSize);
// Deal with begining of line
if (ptr == buf) {
if (ptr[word_len] == ' ' || ptr[word_len] == '\0') {
_G = 1;
}
if (_G) {
strcpy_s(tmp, bufSize, ptr + word_len);
*ptr = 0;
strcat_s(buf, bufSize, replacement_word);
strcat_s(buf, bufSize, tmp);
_G = 0;
}
}
else {
if (*(ptr - 1) == ' ' && (ptr[word_len] == ' ' || ptr[word_len] == '\0')) {
_G = 1;
}
if (_G) {
strcpy_s(tmp, bufSize, ptr + word_len);
*ptr = 0;
strcat_s(buf, bufSize, replacement_word);
strcat_s(buf, bufSize, tmp);
_G = 0;
}
}
// deal with the rest
while (ptr = strstr(ptr + 1, word_to_replace))
{
if (*(ptr - 1) == ' ' && (ptr[word_len] == ' ' || ptr[word_len] == '\0')) {
_G = 1;
}
if (_G) {
strcpy_s(tmp, bufSize, ptr + word_len);
*ptr = 0;
strcat_s(buf, bufSize, replacement_word);
strcat_s(buf, bufSize, tmp);
_G = 0;
}
}
free(tmp);
}
A word can start with space or may lie at the start of string and can end with a space, a full stop, a comma or with the end of string. using these conditions you can easily identify any word within a string. Following code describes it according to your example.
Using this code you can replace a word with another word of any size.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
char str[] = "simple This is a simpled simple simple. simple, string simple";
char * pch;
char * result = str;
char * temp;
char str1[] = "simple"; //string to be replaced
char str2[] = "sample"; //string to be replaced with
pch = strstr(result, str1);
while(pch)
{
temp = result;
if ((pch == str || *(pch - 1) == ' ') && (strlen(pch) == strlen(str1) || !isalpha(*(pch + strlen(str1)))))
{
result = (char*)malloc(strlen(temp)+(strlen(str2) - strlen(str1))+1); //allocate new memory, +1 for trailing null character
strncpy(result, temp, pch - temp); // copy previous string till found word to new allocated memory
strncpy(result + (pch - temp), str2, strlen(str2)); // replace previous word with new word
strncpy(result + (pch - temp) + strlen(str2), pch + strlen(str1), strlen(pch + strlen(str1))); // place previous string after replaced word
strncpy(result + strlen(temp) + (strlen(str2) - strlen(str1)), "\0", 1); // place null character at the end of string
if (temp != str)
free(temp); // free extra memory
}
pch = strstr(result + (pch - temp) + 1, str1); // search for another word in new string after the last word was replaced
}
puts(result);
if (result != str)
free(result);
return 0;
}

How to scan a string for specific terms

I'm trying to scan user input text for specific words and then, when those words occur, print them to the console.
#import <Foundation/Foundation.h>
#include <stdio.h>
int main(){
char cArray[] = "example";
char cInput[] = "";
char cOutput[] = "";
printf("\nType your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, 120, stdin);
}
printf("\nInitialised character array:\n");
for (int x=0; x<1; x++){
if(strncmp(&cInput[x], &cArray[x], 120) == 0){
strncpy(cOutput, cArray, strnlen(cInput, +1));
printf("%s\n", cOutput);
break;
}
}
}
Output:
Type your message:
example
Initialised character array:
Program ended with exit code: 120
Appreciate any feedback as I'm still learning :)
Thanks.
The edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Works although I'm encountering a different problem now. The output only seems to register one word before it completes, thus only "example" is printed.
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0
char cInput[] = "";
The sizeof this array is 1.
fgets(cInput, 120, stdin);
This is array out of bound write which will lead to undefined behavior.
Have
char cInput[120] = "";
You need to take care of
char cOutput[120] = "";
also. Since you are trying to write to this array after comparing.
You need strstr function from string.h
const char * strstr ( const char * str1, const char * str2 );
the following gives you an example of usage:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char cArray[MAX_STR_LEN] = "example"; // string to be searched in the input string
char cInput[MAX_STR_LEN] = ""; // input string
char cOutput[MAX_STR_LEN] = ""; // buffer for found string
printf("\nType your message:\n");
for (int y=0; y<1; y++){ // this loop from original example looks strange, but it works
fgets(cInput, MAX_STR_LEN, stdin);
}
// search in the input string
char * ptr;
if( ( ptr=strstr(cInput, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String that was found: \n%s\n", cOutput);
}
else
{
printf("String was not found in the input!\n");
}
}
EDIT:
If you want to all the strings, use the following loop instead of if-else:
// search in the input string
char * ptr = cInput;
while( ( ptr=strstr(ptr, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String \"%s\" was found at position %d\n", cOutput, (int)(ptr - cInput + 1));
// find next string
ptr++;
}

How to assign char * to character array?

I have following code:
int main(){
char sentence[] = "my name is john";
int i=0;
char ch[50];
for (char* word = strtok(sentence," "); word != NULL; word = strtok(NULL, " "))
{
// put word into array
// *ch=word;
ch[i]=word;
printf("%s \n",ch[i]);
i++;
//Above commeted part does not work, how to put word into character array ch
}
return 0;
}
I am getting error: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
I want to store each word into array, can someone help?
To store a whole set of words you need an array of words, or at least an array of pointers pointing to a word each.
The OP's ch is an array of characters and not an array of pointers to characters.
A possible approach would be:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WORDS_MAX (50)
int main(void)
{
int result = EXIT_SUCCESS;
char sentence[] = "my name is john";
char * ch[WORDS_MAX] = {0}; /* This stores references to 50 words. */
char * word = strtok(sentence, " "); /* Using the while construct,
keeps the program from running
into undefined behaviour (most
probably crashing) in case the
first call to strtok() would
return NULL. */
size_t i = 0;
while ((NULL != word) && (WORDS_MAX > i))
{
ch[i] = strdup(word); /* Creates a copy of the word found and stores
it's address in ch[i]. This copy should
be free()ed if not used any more. */
if (NULL == ch[i])
{
perror("strdup() failed");
result = EXIT_FAILURE;
break;
}
printf("%s\n", ch[i]);
i++;
word = strtok(NULL, " ")
}
return result;
}

Split string in C every white space

I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what I have done so far:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
Although the output is what I want, I have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end.
I can understand that there is a mistake at my malloc() implementation, but I do not know what it is.
Is there another more elegant or generally better way to do it?
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.
From the website:
char * strtok ( char * str, const char * delimiters );
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.
Parameters
str
C string to truncate.
Notice that this string is modified by being broken into smaller strings (tokens).
Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiter characters.
These may vary from one call to another.
Return Value
A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
For the fun of it here's an implementation based on the callback approach:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
malloc(0) may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?
Consider using strtok_r, as others have suggested, or something like:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
Something going wrong is get_words() always returning one less than the actual word count, so eventually you attempt to:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc() isn't returning a valid ptr, though, I don't know.
You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.
Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
you can scan the char array looking for the token if you found it just print new line else print the char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}

Resources