gcc 4.4.4 c89
I am reading in from a text file and the text file consists of names in double quotes.
"Simpson, Homer"
etc
However, I want to remove the double quotes from the string.
This is how I have done it, but I am not sure its the best way.
int get_string(FILE *in, char *temp)
{
char *quote = NULL;
/* Get the first line */
fgets(temp, STRING_SIZE, in);
printf("temp before [ %s ]\n", temp);
/* Find the second quote */
if((quote = strrchr(temp, '"')) == NULL) {
fprintf(stderr, "Text file incorrectly formatted\n");
return FALSE;
}
/* Replace with a nul to get rid of the second quote */
*quote = '\0';
/* Move the pointer to point pass the first quote */
temp++;
printf("temp after [ %s ]\n", temp);
return TRUE;
}
Many thanks for any suggestions,
No, this won't work. You are changing the parameter temp, but the calling function will still have an old value. The temp outside the function will point to the opening quote. You ought to move the characters in your buffer.
However I would suggest allocating the buffer in heap and returning a pointer to it, letting the caller free the buffer when needed. This seems to be a cleaner solution. Again, this way you won't rely on the caller to pass a sufficiently large buffer.
In general, a robust reading lines from a text file is not a trivial task in C, with its lack of automatic memory allocating functions. If possible to switch to C++, I would suggest trying much simpler C++ getline.
char *foo(char *str, int notme)
{
char *tmp=strdup(str);
char *p, *q;
for(p=str, q=tmp; *p; p++)
{
if((int)*p == notme) continue;
*q=*p;
q++;
}
strcpy(str, tmp);
free(tmp);
return str;
}
simple generic remove a char
is all lines look that way why not simple remove the first and the last char?
quote++; // move over second char
quote[strlen(quote)-1]='\0'; // remove last char
Don't know if this will help, it is a simple tokenizer i use
#include <stdlib.h>
#include <string.h>
int token(char* start, char* delim, char** tok, char** nextpos, char* sdelim, char* edelim) {
// Find beginning:
int len = 0;
char *scanner;
int dictionary[8];
int ptr;
for(ptr = 0; ptr < 8; ptr++) {
dictionary[ptr] = 0;
}
for(; *delim; delim++) {
dictionary[*delim / 32] |= 1 << *delim % 32;
}
if(sdelim) {
*sdelim = 0;
}
for(; *start; start++) {
if(!(dictionary[*start / 32] & 1 << *start % 32)) {
break;
}
if(sdelim) {
*sdelim = *start;
}
}
if(*start == 0) {
if(nextpos != NULL) {
*nextpos = start;
}
*tok = NULL;
return 0;
}
for(scanner = start; *scanner; scanner++) {
if(dictionary[*scanner / 32] & 1 << *scanner % 32) {
break;
}
len++;
}
if(edelim) {
*edelim = *scanner;
}
if(nextpos != NULL) {
*nextpos = scanner;
}
*tok = (char*)malloc(sizeof(char) * (len + 1));
if(*tok == NULL) {
return 0;
}
memcpy(*tok, start, len);
*(*tok + len) = 0;
return len + 1;
}
The parameters are:
char* start, (pointer to the string)
char* delim, (pointer to the delimiters used to break up the string)
char** tok, a reference (using &) to a char* variable that will hold the toke
char** nextpos, a reference (using &) to a char* variable that will hold the position after the last token.
char* sdelim, a reference (using &) to a char variable that will hold the value of the -start delimiter
char* edelim, a reference (using &) to a char varaible that will hold the value of the end delimiter
The last three are optional.
Pass in the start address, the delimeter is a ", and pass reference to a char * to hold the actual middle string.
The result is a newly allocated string so you have to free it.
int get_string(FILE *in, char *temp)
{
char *token = NULL;
/* Get the first line */
fgets(temp, STRING_SIZE, in);
printf("temp before [ %s ]\n", temp);
/* Find the second quote */
int length = token(temp, "\"", &token, NULL, NULL, NULL)
// DO STUFF WITH THE TOKEN
printf("temp after [ %s ]\n", token);
// DO STUFF WITH THE TOKEN
// FREE IT!!!
free(token);
return TRUE;
}
The tokenizer is a multipurpose tool that can be used in a crap ton of places, this being a very small example.
Suppose
string="\"Simpson, Homer\""
then
string_without_quotes=string+1;
string_without_quotes[strlen(string)-2]='\0';
ready!
Related
I am getting used to writing eBPF code as of now and want to avoid using pointers in my BPF text due to how difficult it is to get a correct output out of it. Using strtok() seems to be out of the question due to all of the example codes requiring pointers. I also want to expand it to CSV files in the future since this is a means of practice for me. I was able to find another user's code here but it gives me an error with the BCC terminal due to the one pointer.
char str[256];
bpf_probe_read_user(&str, sizeof(str), (void *)PT_REGS_RC(ctx));
char token[] = strtok(str, ",");
char input[] ="first second third forth";
char delimiter[] = " ";
char firstWord, *secondWord, *remainder, *context;
int inputLength = strlen(input);
char *inputCopy = (char*) calloc(inputLength + 1, sizeof(char));
strncpy(inputCopy, input, inputLength);
str = strtok_r (inputCopy, delimiter, &context);
secondWord = strtok_r (NULL, delimiter, &context);
remainder = context;
getchar();
free(inputCopy);
Pointers are powerful, and you wont be able to avoid them for very long. The time you invest in learning them is definitively worth it.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
Extracts the word with the index "n" in the string "str".
Words are delimited by a blank space or the end of the string.
}*/
char *getWord(char *str, int n)
{
int words = 0;
int length = 0;
int beginIndex = 0;
int endIndex = 0;
char currentchar;
while ((currentchar = str[endIndex++]) != '\0')
{
if (currentchar == ' ')
{
if (n == words)
break;
if (length > 0)
words++;
length = 0;
beginIndex = endIndex;
continue;
}
length++;
}
if (n == words)
{
char *result = malloc(sizeof(char) * length + 1);
if (result == NULL)
{
printf("Error while allocating memory!\n");
exit(1);
}
memcpy(result, str + beginIndex, length);
result[length] = '\0';
return result;
}else
return NULL;
}
You can easily use the function:
int main(int argc, char *argv[])
{
char string[] = "Pointers are cool!";
char *word = getWord(string, 2);
printf("The third word is: '%s'\n", word);
free(word); //Don't forget to de-allocate the memory!
return 0;
}
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]);
}
I have a function that is basically a rewritten strtok_r because that function is causing me grief.
char *betterStrtok(char *str, char *delim, char **loc)
{
int iter = 0;
char *tmp;
if(str)
{
char mod[strlen(str) + 2];
char *out = malloc(strlen(str) + 2);
char curr = str[0];
strcpy(mod, str);
while(curr)
{
tmp = strchr(delim, curr);
if(tmp)
{
mod[iter] = 0;
strcpy(out, mod);
*loc = &mod[iter + 1];
//printf("Inside function: \"%s\"\n", *loc);
return out;
}
if(curr)
{
curr = mod[++iter];
}
else
{
*loc = &mod[0];
strcpy(out, mod);
return out;
}
}
return NULL;
}
else
{
char mod[strlen(*loc) + 2];
strcpy(mod, *loc);
char *tloc = malloc(sizeof loc + 2);
char *out = malloc(strlen(*loc) + 2);
char curr = mod[0];
while(curr)
{
tmp = strchr(delim, curr);
if(tmp)
{
mod[iter] = 0;
strcpy(out, mod);
tloc = &mod[iter + 1];
strcpy(*loc, tloc);
return out;
}
if(curr)
{
curr = mod[++iter];
}
else
{
*loc = &mod[0];
strcpy(out, mod);
return out;
}
}
return NULL;
}
}
So my issue is *loc has the appropriate thing in it after the first pass, and when I check what's in it outside the function, it's mostly there except the last character is something weird. Let's say this is the setup:
char *addr = malloc(60);
char **supaddr = &addr;
char *strtotok = "Hello, world!";
char *thetok;
thetok = betterStrtok(strtotok, ",", supaddr);
printf("Outside function: \"%s\"\n", addr);
Adding print statements right before the return and right after calling the function shows something like this:
Inside function: " world!"
Outside function: " w"
The question is: how can I prevent the string from changing or how can I do something else so I can save the "rest" of the original string without returning it?
If you start replacing standard library (or POSIX) functions with your own implementations, first look hard at how the facility is used. For example, compare fgets() and getline().
If I were you, I'd probably use
size_t extract_token(const char *src_ptr, const size_t src_len,
char **token_ptr, size_t *token_size, size_t *token_len);
which extracts a token from a src_len -byte buffer at src_ptr. (Unlike string-based methods, this can handle embedded nul bytes.)
The return value is the number of characters consumed from src_ptr. The token is copied (expanded?) to dynamically allocated token_ptr. The allocated length is in token_size, and the length of the token in token_len.
If extract_token() encounters only whitespace but no token, it returns the number of whitespace chars consumed, with zero assigned to token_len. For simplicity, let's assume the function always sets errno; to zero if success, to a nonzero error code if an error occurs.
A simple loop that tokenizes lines read from standard input would be
char *line_ptr = NULL;
size_t line_size = 0;
ssize_t line_len;
long line_num = 0;
char *token_ptr = NULL;
size_t token_size = 0;
size_t token_len;
char *cur, *end;
size_t n;
while (1) {
line_len = getline(&line_ptr, &line_size, stdin);
line_num++;
if (line_len < 1) {
if (ferror(stdin) || !feof(stdin)) {
fprintf(stderr, "Standard input: Line %ld: Read error.\n", line_num);
return EXIT_FAILURE;
}
break;
}
cur = line_ptr;
end = line_ptr + line_len;
while (1) {
if (cur >= end) {
errno = 0;
cur = end;
break;
}
n = extract_token(cur, (size_t)(end - cur),
&token_ptr, &token_size, &token_len);
if (errno) {
/* cur + n is the offending character in input */
fprintf(stderr, "Standard input: Line %ld: Cannot tokenize line.\n", line_num);
exit(EXIT_FAILURE);
}
/* Do something with token;
token_ptr points to the token,
token_len is the length of the token
token_size is the size allocated for the token
*/
}
}
/* Since the line and token buffers are no longer needed,
free them. I like to clear the variables too, just in
case.
*/
free(line_ptr);
line_ptr = NULL;
line_size = 0;
free(token_ptr);
token_ptr = NULL;
token_size = 0;
Note that when reading files with clear record-and-field formatting, like CSV files, I do prefer to read the tokens directly from the file using a getline()-like interface, either
int next_field(char **ptr, size_t *size, size_t *len, FILE *in);
int next_record(FILE *in);
or
int next_wfield(wchar_t **ptr, size_t *size, size_t *len, FILE *in);
int next_wrecord(FILE *in);
where next_field() (or next_wfield() for wide input) obtains the next field in the current record, preferably handling de-quoting and de-escaping, and next_wrecord() skips any leftover fields in the current record, and moves to the beginning of next record.
Using fgetc() or fgetwc() the code implementing the above is quite straightforward (even if CSV quoting rules are implemented), although it won't be as fast as possible using more advanced methods. Because CSV and other such file formats are not optimal anyway, the slight loss in speed is normally neglible/unnoticeable. Most importantly, if you try it out, you'll see that code that uses next_field()/next_record() is quite robust, and easy to read, write, and maintain in the long term.
The answer was in the comments. Turns out if I changed mod to a pointer it worked perfectly.
I have written the following program to resolve a path to several directory names
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *
tokenizer(char *path, char **name){
char s[300];
char *buffer;
memcpy(s, path, strlen(path)+1);
printf("%s\n",s); // PROBLEM
int i=0;
while(s[i] == '/'){
i++;
}
if (i == strlen(path)){
return NULL;
}
*name = strtok_r(s, "/", &buffer);
return buffer;
}
int main(void){
char str[300];
char *token, *p;
scanf("%s",str);
p = tokenizer(str, &token);
if (p != NULL)
printf("%s\n",token);
else
printf("Nothing left\n");
while((p=tokenizer(p, &token)) != NULL){
printf("%s\n",token);
}
}
Output of the above program
Input: a/b/c
Output: a/b/c
a/b/c
a
b/c
b
c
c
If I comment the line labelled PROBLEM
Input: a/b/c
Output: Some garbage value
Can somebody explain me the reason for this strange behavior?
Note:
I have realised that s is a stack allocated variable and it ceases to exist in function main() but why does the program works when I use printf() ?
In addition to what geekasaur says:
strtok_r's 3rd parameter is used incorrectly, in two ways:
1. It should be initialized to NULL before the first call.
2. It shouldn't be used in any way (you return it to the caller). It should only be passed to another strtok_r call.
You are returning a pointer into a stack-allocated string (buffer points into s); s's memory ceases to be meaningful after tokenize returns.
You cannot do this
char s[300];
char *buffer;
...
*name = strtok_r(s, "/", &buffer);
return buffer;
Here buffer is a pointer to a s[300] position. s[300] is a function local variable allocated on the stack when the function is called and destroyed when the function returns.
So you are not returning a valid pointer, you cannot use that pointer out of the function.
Along with the observations that you're returning a pointer to a local variable, I think it's worth noting that your tokenizer is almost 100% pointless.
Most of what your tokenizer does is skip across any leading / characters before calling strtok_r -- but you're passing '/' as the delimiter character to strtok_r, which will automatically skip across any leading delimiter characters on it own.
Rather simpler code suffices to print out the components of a path without the delimiters:
char path[] = "a/b/c";
char *pos = NULL;
char *component = strtok_r(path, "/", &pos);
while (NULL != component) {
printf("%s\n", component);
component = strtok_r(NULL, "/", &pos);
}
Try this:
char*
token(char * path, char ** name){
static char * obuffer = NULL;
char * buffer = NULL, * p, * q;
if(path == NULL) {
buffer = realloc(buffer, strlen(obuffer) + 1);
p = obuffer;
} else {
buffer = malloc(257);
p = path;
}
if(!buffer) return NULL;
q = buffer;
if(!p || !*p) return NULL;
while(*p != '\0') {
if(*p == '/') {
p++; /* remove the / from string. */
break;
}
*q ++ = *p++;
}
*q ++ = '\0';
obuffer = p;
*name = buffer;
return buffer;
}
int main(void)
{
char * s = "foo/baa/hehehe/";
char * name = NULL;
char * t = token(s, &name);
while(t) {
printf("%s\n", name);
t = token(NULL, &name);
}
return 0;
}
the output:
foo
baa
hehehe
But you are basically "reinventing the wheel" of strtok() function..
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]);
}