Related
I need ideas for a recursive code that deletes a specific char in a string, and move all the other sting chars together
for Example :
"the weather is cloudy"
the entered char is 'e':
result :
"th wathr is cloudy"
I really don't have any idea how to start, thanks for the help.
#include <stdio.h>
void remove_impl(char* s, char c, char* d) {
if (*s != c) {
*d++ = *s;
}
if (*s != '\0') {
remove_impl(++s, c, d);
}
}
void remove(char* s, char c) {
remove_impl(s, c, s);
}
int main() {
char s[] = "the weather is cloudy";
remove(s, 'e');
puts(s);
}
How it works? Consider remove_impl. s is the original string, c is the character to be deleted from s, d is the resulting string, into which the characters of s, not equal to c, are written. Recursively iterates through the characters of s. If the next character is not equal to c, then it is written in d. The recursion stop point is the condition of checking that the end of s is reached. Since it is necessary to modify the source string, the wrapper is implemented (remove) in which as d, the original string (s) is passed.
An easy way to do it is to loop over the string and add any letter that doesn't match the unwanted letter.
Here's a demonstration:
char *source = "the weather is cloudy";
int source_len = strlen(source);
char *target = (char *)calloc(source_len, sizeof(char));
int target_len = 0;
char to_remove = 'e';
for(int i = 0; i < source_len; i++)
{
if(source[i] != to_remove)
{
target[target_len++] = source[i];
}
}
puts(target); // Output "th wathr is cloudy" in the console
My turn to make a proposal ! I add a assert test and use existing functions (strchr and strcpy).
#include <string.h>
#include <stdio.h>
#include <assert.h>
int removeChar(char *str, char chr)
{
assert(str != 0); // Always control entry !
char *str_pnt = strchr(str, chr);
if (str_pnt) {
strcpy(str_pnt, str_pnt+1);
removeChar(str_pnt, chr);
}
}
void main (void)
{
char str[] = "the weather is cloudy";
char char_to_delete = 'e';
removeChar(str, char_to_delete);
puts(str);
}
This can be done in many ways. What i am thinking right now is store not Allowed char array which going to filter which char should show or not. Something like following..
#include <stdio.h>
#include <string.h>
// Global Scope variable declaration
int notAllowedChar[128] = {0}; // 0 for allowed , 1 for not allowed
char inputString[100];
void recursion(int pos, int len) {
if( pos >= len ) {
printf("\n"); // new line
return;
}
if( notAllowedChar[inputString[pos]]) {// not printing
recursion( pos + 1 , len );
}
else {
printf("%c", inputString[pos]);
recursion( pos + 1 , len );
}
}
int main() {
gets(inputString); // taking input String
printf("Enter not allowed chars:: "); // here we can even run a loop for all of them
char notAllowed;
scanf("%c", ¬Allowed);
notAllowedChar[notAllowed] = 1;
int len = strlen(inputString);
recursion( 0 , len );
}
How this work
Lets say we have a simple string "Hello world"
and we want l should be removed from final string, so final output will be "Heo word"
Here "Hello world" length is 11 chars
before calling recursion function we make sure 'l' index which is 108 ascii values link 1 in notAllowedChar array.
now we are calling recursion method with ( 0 , 11 ) value , In recursion method we are having mainly 2 logical if operation, first one is for base case where we will terminate our recursion call when pos is equal or more than 11. and if its not true , we will do the second logical operation if current char is printable or not. This is simply just checking where this char is in notAllowedChar list or not. Every time we increase pos value + 1 and doing a recursion call, and finally when pos is equal or more than 11 , which means we have taken all our decision about printing char or not our recursion will terminate. I tried assign variable with meaningful name. If you still not understand how this work you should go with simple recursion simulation basic ( search in youtube ) and also you should try to manually debug how value is changing in recursion local scope. This may take time but it will be worthy to understand. All the very best.
#include <stdio.h>
/**
* Returns the number of removed chars.
* Base case: if the current char is the null char (end of the string)
* If the char should be deleted return 1 + no of chars removed in the remaining string.
* If it's a some other char simply return the number of chars removed in the remaining string
*/
int removeCAfterwardsAndCount(char* s,char c){
if((*s) == '\0'){
return 0;
}
if((*s) == c){
int noOfChars = removeCAfterwardsAndCount(s+1,c);// s+1 means the remaining string
s[noOfChars] = *s; // move the current char (*s) noOfChars locations ahead
return noOfChars +1; // means this char is removed... some other char should be copied here...
}
else{
int noOfChars = removeCAfterwardsAndCount(s+1,c);
s[noOfChars ] = *s;
return noOfChars ; // means this char is intact ...
}
}
int main()
{
char s[] = "Arifullah Jan";
printf("\n%s",s);
int totalRemoved = removeCAfterwardsAndCount(s,'a');
char *newS = &s[totalRemoved]; // the start of the string should now be originalPointer + total Number of chars removed
printf("\n%s",newS);
return 0;
}
Test Code Here
To avoid moving the chars using loops. I am just moving the chars forward which creates empty space in the start of the string. newS pointer is just a new pointer of the same string to eliminate the empty/garbage string.
#include <stdio.h>
void RemoveChar(char* str, char chr) {
char *str_old = str;
char *str_new = str;
while (*str_old)
{
*str_new = *str_old++;
str_new += (*str_new != chr);
}
*str_new = '\0'; }
int main() {
char string[] = "the weather is cloudy";
RemoveChar(string, 'e');
printf("'%s'\n", string);
return 0; }
#include <stdio.h>
#include <string.h>
char *remove_char(char *str, int c)
{
char *pos;
char *wrk = str;
while((pos = strchr(wrk, c)))
{
strcpy(pos, pos + 1);
wrk = pos;
}
return str;
}
int main()
{
char str[] = "Hello World";
printf(remove_char(str, 'l'));
return 0;
}
Or faster but mode difficult to understand version:
char *remove_char(char *str, int c)
{
char *pos = str;
char *wrk = str;
while(*wrk)
{
if(*wrk == c)
{
*wrk++;
continue;
}
*pos++ = *wrk++;
}
*pos = 0;
return str;
}
Both require the string to be writable (so you cant pass the pointer to the string literal for example)
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 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];
}
}
I'm new to programming,and I have a small problem.
I have a file named questions.txt containing a string of questions, I want to read the string from the file then split it into array with each question having an index, for example a[i] = "Question i" etc.
I did so many tries, but it always ends up reading the last line in the file, when write a loop the program stops working.
This is what i came up with, it's all probably wrong:
char str[200];
char *ptr;
FILE * fp = fopen("questions.txt", "r");
while(fgets(str, 200, fp)!= NULL)
printf("%s", str);
ptr = strtok(str, "\n");
while(ptr != NULL)
{
ptr = strtok(str, "\n");
printf("%s\n", ptr);
ptr = strtok(NULL, "\n");
}
fclose(fp);
The file is:
what is your course?
who is your instructor?
Output i get is:
what is your course?
who is your instructor?
who is your instructor?
I want to read the string from the file then split it into an array with each question having an index...
Let me say, that you don't have a string to split into array.
You should better have a file with a one string of questions like this:
what is your course?:who is your instructor? // `:` is some kind of delimiter
I can suppose that you want to make a vector (one dimensional array) of the file. And in that vector, each element will contain a question from the file. Right?
I can share with you a function from my library I've made at the university. I'll write here a simple program. But it uses delimiters - :, for example. You can modify this function for working without delimiters -- this only depends on you.
In two words, this little program does the following:
// BEFORE: you have a string that ends with a null terminating character.
Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa\n
^
here ^<< printing 'string' stops
// AFTER: an array of questions. Each of them ends with a null terminating character.
Question_1_abcbadsad\nQUestion_2asasdasd\nQuestion_3sldasdsa\n
^
^<< printing argz[0] will stop here
main.c
#include "argz.h"
int main()
{
error_t func;
char *argz; // pointer to a vector; to an array of questions
size_t argz_len;
// size of that vector (the size of the string you've got from the file)
// Consider `string` to be your `ptr`. You read a string from the file so
// `ptr` will point to the string.
char *string = "Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa";
// Here `:` is a separate character.
func = argz_create_sep(string, ':', &argz, &argz_len);
if(func == OK)
argz_print(argz, argz_len);
else
printf("ERROR\n");
return 0;
}
argz.c
#include "argz.h"
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len)
{
int i;
char *ch;
int len = strlen(string);
if(len==0)
return ENOMEM;
*argz = (char*) malloc (sizeof(char)*(len + 1));
strcpy(*argz, string);
*argz_len = strlen(*argz);
ch = *argz;
for(i = 0; i < len; i++) {
if(*ch == sep) *ch='\0';
ch++;
}
return OK;
}
void argz_print(const char *argz, size_t argz_len)
{
const char *ch;
int i;
ch = argz;
for(i = 0; i < argz_len; i++) {
if(*ch == '\0')
printf("\n");
else
printf("%c",*ch);
ch++;
}
printf("\n\n\n");
}
argz.h
#include <stddef.h> // for size_t
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef enum {OK, ENOMEM} error_t;
/* function prototypes */
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len);
void argz_print (const char *argz, size_t argz_len);
I think what you want is something like this:
#include <stdio.h>
int main(){
int i=0;
char str[200],s='1'; //s is give a random character
FILE * fp = fopen("questions.txt", "r");
while (s!=EOF){ //works until s= the end of file
s=getc(fp); //s starts to receive characters from text file
str[i]=s; //each character of text is placed into the string array
i++;
}
str[i]='\0'; //s reached EOF so lets indicate where we stopped in the string
fclose(fp);
printf("%s\n",str);
//EDIT: changing 1D str to 2D str2
char str2[10][200]; // 10 for max no. of questions, 200 - length of each question
int j=0,k=0;
i=0;
for(j=0;j<200;j++){
str2[i][k]=str[j];
k++;
if (str[j]=='\n'){
i++;
k=0;}
}
for(i=0;i<10;i++) //prints your 2D string array
printf("%s",str2[i]); //after the last question there will be junk
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]);
}