Reverse words in C Language - c

I'm trying to reverse the letters for words in a sentence. I am also trying to store these words in a new char array. At the moment I getting a runtime error, which for all my tweaking I can not solve. My approach is to create a new char array the same length as the sentence. Then loop through the sentence until I reach a ' ' character. Then loop backwards and add these characters to a word. Then add the word to the new Sentence. Any help would be much appreciated.
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence = malloc(strlen(sentence)+1);
int i,j,start;
start = 0;
for(i = 0; i <= strlen(sentence); i++)
{
if(sentence[i] == ' ')
{
char *word = malloc((i - start)+1);
for(j = sentence[i]; j >= start; j--)
{
word[j] = sentence[j];
}
strcat(newSentence,word);
start =sentence[i +1];
}
}
printf("%s",newSentence);
return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence;
int i,j,start, len;
start = 0;
len = strlen(sentence);
newSentence = malloc(len+1);
*newSentence = '\0';
for(i = 0; i <= len; i++)
{
if(sentence[i] == ' ' || sentence[i] == '\0')
{
char *word = malloc((i - start)+1);
int c = 0;
for(j = i - 1; j >= start; j--)
{
word[c++] = sentence[j];
}
word[c]='\0';
strcat(newSentence,word);
if(sentence[i] == ' ')
strcat(newSentence," ");
start = i + 1;
free(word);
}
}
printf("%s",newSentence);
return 0;
}

Logically, here:
j = sentence[i]
start =sentence[i +1];
start and j are index positions in the char array, you are trying to assign a char to them, which screws everything up.
should be:
j= i;
start = i +1;
if your algorithm is right.

Yet another variant of the same...
int main(int argc, const char *argv[])
{
char sentence [] = "this is a sentence";
size_t len = strlen(sentence);
char *newSentence = malloc(len + 1);
char *ptr_src = sentence;
char *ptr_dst = newSentence;
while(ptr_src)
{
char *next, *t;
next = strchr(ptr_src, ' '); // find next space
if (!next) next = sentence + len; // if not found, next = EOL
for (t = next; t > ptr_src;)
{
*ptr_dst++ = *--t;
}
if (*next)
{
*ptr_dst++ = *next++;
ptr_src = next;
}
else
{
*ptr_dst = 0;
break;
}
}
printf("[%s]",newSentence);
return 0;
}

Your program had few bugs. Which I've tried to remove in this program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char sentence [] = "this is a sentence";
char *newSentence = (char *)malloc(strlen(sentence)+1);
int i,j,start, k;
start = 0;
for(i = 0;; i++)
{
if(sentence[i] == ' ' || sentence[i] == '\0') //sentence[i] == '\0' for the last word.
{
char *word = (char *) malloc((i - start)+1);
for(j = i-1, k = 0; j >= start; j--, k++)
{
word[k] = sentence[j];
}
word[k++] = ' '; //space after each word
word[k] = '\0';
strcat(newSentence,word);
start = i+1;
}
if (sentence[i] == '\0')
break;
}
printf("%s\n",newSentence);
return 0;
}
Check live at http://ideone.com/Z9ogGk

strcat(newSentence,word);
newSentence has to be a string. And a string is a contiguous sequence of characters terminated by and including the first null character
EDIT: this answer has been downvoted 4 times for what is written above. If you think it is incorrect, please explain. Otherwise please remove your downvote.

Related

Inserting a character into a char array

I have a char array containing a number.
char number[] = "12000000"
I need to have a function to insert a divider in every 3 digits. Like:
char result[] = "12,000,000"
My function accepts the number as a char pointer and it needs to return result as a char pointer too.
char* insert_divider(char* number) {
some magic;
return result;
}
I have no idea of working with pointers. Thanks.
Here you have a function that adds char c every num characters starting from the end. You need to make sure that the string buffer is long enough to accommodate the amended string.
char *addEvery(char *str, char c, unsigned num)
{
char *end = str;
if(str && *str && num)
{
size_t count = 1;
while(*(end)) end++;
while(end != str)
{
end--;
count++;
if(!(count % (num + 1)) && str != end)
{
memmove(end + 1, end, count);
*end = c;
count++;
}
}
}
return str;
}
int main(void)
{
char str[100] = "120000000000";
printf("%s", addEvery(str,',',3));
}
I came up with this piece of code:
char *result;
result = (char*) malloc(15);
int len= strlen(input);
uint8_t cursor= 0;
for(int i = 0; i < len; i++) {
if ((len- i) > 0 && (len- i) % 3 == 0) {
result[i + cursor] = ',';
cursor++;
}
result[i + cursor] = input[i];
}
result[len+ cursor] = '\0';
Thanks everyone for help and advice.
Here is another way to do it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* insert_divider(char* number, size_t length) {
int j = length + length/3; // every 3 digits a ',' will be inserted
char *out = (char*)malloc(j + 1);
out[j--] = '\0';
for (int i = length - 1, k = 1; i >= 0; i--, k++) {
out[j--] = number[i];
if ((k%3) == 0) {
out[j--] = ',';
}
}
return out;
}
int main(){
char number[] = "12000000";
char *outNumber = insert_divider(number, strlen(number));
printf("%s", outNumber);
free(outNumber);
return 0;
}

Segfault error when mallocing an array of structs

after a long time spent trying to debug this I've come for your help.
Basically in this exercise I'm trying to read the string "31|Name1;23|Name2;15|Name3" and store it in an array of struct s_perso where the | are marking the end of an age and the beginning of a name, and where the ; are marking the beginning of a new struct.
Here's the given ft_perso.h :
#include <string.h>
#ifndef FT__PERSO__H
#define FT__PERSO__H
typedef struct s_perso
{
char *name;
float life;
int age;
char *profession;
}
t_perso;
#endif
We will only use the datas age and name from this struct s_perso.
Here's my code :
#include "ft_perso.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int numberofstructs(char *str)
{
int i;
int length;
i = 0;
length = 0;
if (str[0])
length = 0;
else
{
while (str[i])
{
if (str[i] == ';')
length += 1;
i++;
}
}
return (length);
}
int get_data_length(char *str, int i)
{
int length;
length = 0;
while (str[i] != '|' && str[i] != ';' && str[i] != '\0')
{
length++;
i++;
}
return (length);
}
char *get_data(char *str, int i)
{
int j;
char *str2;
j = 0;
str2 = (char *)malloc(sizeof(char) * get_data_length(str, i) + 1);
while (str[i] != '|' && str[i] != ';' && str[i] != '\0')
{
str2[j] = str[i];
i++;
j++;
}
str2[j] = '\0';
return (str2);
}
t_perso **ft_decrypt(char *str)
{
int i;
int j;
t_perso **textttt_perso;
i = 0;
j = 0;
textttt_perso = (t_perso **)malloc(sizeof(t_perso **));
*textttt_perso = (t_perso *)malloc(sizeof(t_perso *) * numberofstructs(str));
while (j <= strlen(str) && str[j])
{
if (str[j] == ';')
{
i++;
j++;
}
textttt_perso[i]->age = atoi(get_data(str, j));
j = j + get_data_length(str, j) + 1;
textttt_perso[i]->name = get_data(str, j);
j = j + get_data_length(str, j);
}
textttt_perso[i+1] = 0;
return (textttt_perso);
}
int main(void)
{
int i;
t_perso **tab;
i = 0;
char str[29] = "31|Name1;23|Name2;15|Name3";
tab = ft_decrypt(str);
while(i <= numberofstructs(str))
{
printf("age = %d\n", tab[i]->age);
printf("age = %s\n", tab[i]->.name);
i++;
}
}
From my debugging, I get the segfault error on the second call (when i = 1 and we are working on the substring 23) instruction of t_perso **ft_decrypt(char *str) :
textttt_perso[i]->age = atoi(get_data(str, j));
My guess is that my allocation of memory either for the array of struct in itself or the number of arrays it can contain is wrong. I can't point my finger on the problem tho...
Thanks in advance for your help, have a nice day !
You never allocate space for an actual structure. In your example:
textttt_perso = (t_perso **)malloc(sizeof(t_perso **));
allocates space for one pointer and:
*textttt_perso = (t_perso *)malloc(sizeof(t_perso *) * numberofstructs(str));
allocates enough space for 3 pointers. At some point you need to allocate space for the actual structures.
You also have other issues. In numberofstructs() you have if(str[0]) that will cause length to always be zero. Also in numberofstructs(), you count the semi-colons. If there is data after the last sem-colon you would need to add 1 to length.
You have many other issues in this code that will show up if the data isn't perfect but here is an implementation of ft_decrypt that should work. Initial malloc should be to hold the array of pointers. Then the loop should allocate a structure for each array entry.
t_perso** ft_decrypt(char* str)
{
int i = 0;
int j = 0;
t_perso** textttt_perso;
textttt_perso = malloc(sizeof(*textttt_perso) * numberofstructs(str));
while (j <= strlen(str) && str[j])
{
if (str[j] == ';')
{
i++;
j++;
}
textttt_perso[i] = malloc(sizeof(*textttt_perso[i]));
textttt_perso[i]->age = atoi(get_data(str, j));
j = j + get_data_length(str, j) + 1;
textttt_perso[i]->name = get_data(str, j);
j = j + get_data_length(str, j);
}
return (textttt_perso);
}

Reversing the order of words backwards in a string

Sorry for such a mediocre question, but I ran into what seems to be a tiny problem, but simply can't get over it. For my task I have to take a line of string from a file, and put it into another file backwards, for example:
one two three
four five six
would be
three two one
six five four
My problem is, is that I'm getting
three two one
si five four
So basically the flaw is that there is a space character at the beginning of each line and the last letter of the last word is always missing. Here's my reverse function:
void reverse(char input[], int length, char output[]) {
char space = 32;
input[length - 1] = space;
int value = 0;
int i, k = 0, j;
for (i = 0; i <= length; i++) {
if (input[i] == space) {
for (j = i - 1; j >= k; j--, value++) {
output[value] = input[j];
}
if (j == -1) {
output[value] = space;
value++;
}
k = i;
}
}
char c = 0;
for (int i = 0, j = length - 1; i <= j; i++, j--) {
c = output[i];
output[i] = output[j];
output[j] = c;
}
}
What I'm doing is first reversing each word by character, and then the whole line. If someone could help me find the last bits that I've missed I would greatly appreciate it.
The flaws come from your approach:
why do you force a space at offset length - 1? If you read the line with fgets(), there is probably a newline ('\n') at the end of the line, but it might be missing at the end of the input, which would explain the x getting overwritten on the last line.
you should not modify the input buffer.
Here is a simplified version, along with a simple main function:
#include <stdio.h>
#include <string.h>
void reverse(const char *input, int length, char *output) {
int i, j, k, v;
for (i = k = v = 0;; i++) {
if (i == length || input[i] == ' ') {
for (j = i; j-- > k; v++) {
output[v] = input[j];
}
for (; i < length && input[i] == ' '; i++) {
output[v++] = ' ';
}
if (i == length) {
output[v] = '\0';
break;
}
k = i;
}
}
for (i = 0, j = length - 1; i < j; i++, j--) {
char c = output[i];
output[i] = output[j];
output[j] = c;
}
}
int main() {
char input[256];
char output[256];
while (fgets(input, sizeof input, stdin)) {
reverse(input, strcspn(input, "\n"), output);
puts(output);
}
return 0;
}
Output:
three two one
six five four
Here is a simpler reverse function that operates in one pass:
#include <string.h>
void reverse(const char *input, int length, char *output) {
int i, j, k, v;
for (i = k = 0, v = length;; i++) {
if (i == length || input[i] == ' ') {
for (j = i; j-- > k;) {
output[--v] = input[j];
for (; i < length && input[i] == ' '; i++) {
output[--v] = ' ';
}
if (v == 0) {
output[length] = '\0';
break;
}
k = i;
}
}
}
Replace input[length - 1] = space; with input[length] = space;

Splitting a string (Segmentation Fault on test)

I'm trying to extract a substring from a giving input,
for example if i have : "Hello I am here" in a char *
I want to get :
char tab[0] = "Hello";
char tab[1] = "I";
/// etc
But it gives me a Segfault, any help ?
Here is my function to divide my char * :
#include <stdlib.h>
char **str_to_wordtab(char *str)
{
int i;
int j;
int k;
char **tab;
i = 0;
k = 0;
tab = malloc(my_strlen(str) * sizeof(*tab));
while (str[k] != '\0')
{
j = 0;
tab[i] = malloc(my_strlen(str) * sizeof(*tab[i]));
while (str[k] != ' ')
tab[i][j++] = str[k++];
tab[i][j] = '\0';
if (str[k] == ' ')
k++;
i++;
}
return (tab);
}
And here is the main to test it :
int main(int ac, char **av)
{
char **tab;
int i;
i = 0;
tab = str_to_wordtab("Hello I am here");
while (tab[i])
{
my_putstr(tab[i++]);
my_putstr("\n");
}
}
Thanks for helping me.
Your inner while loop should look like this:
while (str[k] != ' ')
{
tab[i][j++] = str[k++];
if (str[k-1] == 0)
{
tab[++i] = 0 ;
return tab ;
}
}
This is not a division that you want but a split of string.
Consider strtok with space as a delimiter.
About your segfault, here are some leads:
while (str[k] != '\0') might be dangerous if you forgot to recopy the \0 in your string
your post-incrementations might be source of errors too

how to perform reversing a sentence Word by Word in C?

#include <stdio.h>
int main(void)
{
int i,j;
int wordstart = -1;
int wordend = -1;
char words[]= "this is a test";
char temp;
// Reverse each word
for (i = 0; i < strlen(words); ++i)
{
wordstart = -1;
wordend = -1;
if(words[i] != ' ')
wordstart = i;
for (j = wordstart; j < strlen(words); ++j)
{
if(words[j] == ' ')
{
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = strlen(words);
for (j = wordstart ; j <= (wordend - wordstart) / 2; ++j)
{
temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
printf("reversed string is %s:", words);
}
}
I tried in this way but i am getting this output:
siht is a test
my expected output is:
test a is this
I would appreciate if some one could come with a different approach for which time complexity is very less or correct me if it is the right approach. Thanks
Perhaps this belongs on the code review site instead?
Your approach seems very efficient to me (except that I would only call strlen(words) once and save the result in a register).
Two possible bugs look like:
wordend = strlen(words);
should be
wordend = strlen(words)-1;
and
for(j = wordstart ; j <= (wordend - wordstart) / 2 ; ++j) {
should be
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
Final code looks like (with some extra {}):
#include <stdio.h>
int main(int argc,char *argv[])
{
int i,j;
char words[]= "this is a test";
int L=strlen(words);
// Reverse each word
for(i = 0; i < L; ++i) {
int wordstart = -1;
int wordend = -1;
if(words[i] != ' ')
{
wordstart = i;
for(j = wordstart; j < L; ++j) {
if(words[j] == ' ') {
wordend = j - 1;
break;
}
}
if(wordend == -1)
wordend = L-1;
for(j = wordstart ; j <= (wordend + wordstart) / 2 ; ++j) {
char temp = words[j];
words[j] = words[wordend - (j - wordstart)];
words[wordend - (j - wordstart)] = temp;
}
i = wordend;
}
}
printf("reversed string is %s:",words);
return 0;
}
You can create a double linked list as a base data structure. Then, iterate through the words and insert them in the list as you find them.
When you reach the end of the sentence, simply traverse the list backwards and print the words as you go through them
Simply we can just use a n*1 2D character array tailored to suit our needs!!!
#include <stdlib.h>
int main()
{
char s[20][20];
int i=0, length=-1;
for(i=0;;i++)
{
scanf("%s",s[i]);
length++;
if(getchar()=='\n')
break;
}
for(i=length;i>=0;i--)
printf("%s ",s[i]);
return 0;
}
Start tokenizing the line from the last character and continue to the first character. Keep one pointer anchored at the base of the current word, and another pointed which will decrease while a word start is not found. When you find a word start while scanning like this, print from the word start pointer to the word end anchor. Update the word end anchor to the previous character of the current word start char.
You might want to skip the blankspace characters while scanning.
UPDATE
This is a quick implementation:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_BUF 256
void show_string (char *str, int i, int n)
{
while (i <= n)
{
printf ("%c", str[i]);
i++;
}
}
int main (void)
{
char str[MAX_BUF];
int end_anchor, start_ptr;
int state;
printf ("\nEnter a string: ");
scanf (" %[^\n]", str);
start_ptr = strlen (str) - 1;
end_anchor = start_ptr;
state = 0;
while (start_ptr >= -1)
{
switch (state)
{
case 0:
if ((!isspace (str[start_ptr]) && (start_ptr >= 0)))
{
start_ptr--;
}
else
{
state = 1;
}
break;
case 1:
show_string (str, start_ptr + 1, end_anchor);
state = 2;
start_ptr--;
printf (" ");
break;
case 2:
if (!isspace (str[start_ptr]))
{
state = 0;
end_anchor = start_ptr;
}
else
{
start_ptr--;
}
break;
}
}
printf ("\n");
return 0;
}
The end_anchor points to each end word, and the start_ptr finds the start of the word of which the end is held by end_anchor. When we find a word start (by blankspace characters or start_ptr = -1), we print all the characters from start_ptr + 1 to end_anchor. The + 1 is because of the implementation: start_ptr points to the blankspace character, and the print routine will print all the characters from i to n. Once we have detected one blank space we print it and we skip adjacent blankspaces (in case 2) and preserve only one which is manually printed. Once a non blankspace is detected, we have got another word end, for which we set the end_anchor to this index in the case 2, and set state = 0 , so that we can search for the word start again.
if(words[i] != ' ')
wordstart = i;
This statement what about the else part? if words[i] == ' ', and wordstart remains -1.
So maybe try to use:
while (words[i] && words[i] == ' ') ++i;
if (!words[i])
break;
wordstart = i;
Then you should output the result out of the i loop.
Finally, if you want to get the result you expected, you should reverse the whole sentence once more, with the way you used in the loop.
I would use write function similar to strrchr for finding last occurence of ' ', if its found print word that follows, rewrite this ' ' with '\0' and repeat it in loop till no more words are found. At the end I would print the content of this string again because there is most likely no ' ' before the first word.
I would write own function instead of strrchr because strrchr calculates the lenght of the given string, which is redundant in this case. This length doesn't have to be calculated more than once.
Here's the code:
char* findLastWord(char* str, int* len)
{
int i;
for (i = *len - 1; i >= 0; --i)
{
if (str[i] == ' ')
{
str[i] = '\0';
if (i < *len - 1)
{
*len = i - 1;
return &str[i + 1];
}
}
}
return NULL;
}
int main (int argc, char *argv[])
{
char str[] = " one two three four five six ";
int len = strlen(str);
char* lastWord = findLastWord(str, &len);
while (lastWord != NULL)
{
printf("%s\n", lastWord);
lastWord = findLastWord(str, &len);
}
if (len > 1)
printf("%s\n", str);
return 0;
}
output:
six
five
four
three
two
one
Hope this helps ;)
#include<stdio.h>
#include<string.h>
void reverse(char *str, size_t len)
{
char tmp;
size_t beg, end;
if (len <=1) return;
for (beg=0,end=len; beg < --end ; beg++) {
tmp = str[beg];
str[beg] = str[end];
str[end] = tmp;
}
}
int main(void)
{
char sentence[] = "one two three four five";
size_t pos, len;
printf("Before:%s\n",sentence);
for (pos = len= 0; sentence[pos]; pos += len) {
pos += strspn( sentence+pos, " \t\n" );
len = strcspn( sentence+pos, " \t\n" );
reverse ( sentence + pos, len );
}
reverse ( sentence , pos );
printf("After:%s\n",sentence);
return 0;
}
#include <iostream>
#include <string>
using namespace std;
char* stringrev(char s[], int len)
{
char *s1 = (char*)malloc(len+1);
int i=0;
while (len>0)
{
s1[i++] = s[--len];
}
s1[i++] = '\0';
return s1;
}
void sentrev(char s[], int len)
{
int i=0; int j=0;
char *r = (char*)malloc(len+1);
while(1)
{
if(s[j] == ' ' || s[j] == '\0')
{
r = stringrev(s+i, j-i);
i = j+1;
cout<<r<<" ";
}
if (s[j] == '\0')
break;
j++;
}
}
int main()
{
char *s = "this is a test";
char *r = NULL;
int len = strlen(s);
cout<<len<<endl;
r = stringrev(s, len);
cout<<r<<endl;
sentrev(r, len);
return 0;
}
The above code snap reverse the sentence, using char *r
and printing cout<
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main()
{
char st[50], rst[50];
printf("Enter the sentence...\n");
gets(st);
int len=strlen(st), p;
int j=-1,k;
p=len;
for(int i=(len-1); i>=0; i--)
{
//searching for space or beginning
if(st[i]==' ')
{
//reversing and storing each word except the first word
for(k=i+1;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
j++;
rst[j]=' ';
printf("\n");
p=i;
}
else if(i==0)
{
//for first word
for(k=i;k<p;k++)
{
//printf("%c",st[k]);
rst[++j]=st[k];
}
}
}
printf("Now reversing the sentence...\n");
puts(rst);
return 0;
}
Use a main for loop to traverse till the end of the sentence:
Copy the letters in a string until you find a space.
now call add#beginning function and in that function add the string each time you pass a string to the linked list.
print the contents of the linked list with a space inbetween to get the expected output
My code,just traverse from the last and if you find a space print the characters before it,now change the end to space-1;This will print till the second word,finally just print the first word using a single for loop.Comment for alter approach.
Program:
#include<stdio.h>
int main()
{
char str[200];
int i,j,k;
scanf("%[^\n]s",&str);
for(i=0;str[i]!='\0';i++);
i=i-1;
for(j=i;j>=0;j--)
{
if((str[j])==' ')
{
for(k=j+1;k<=i;k++)
{
printf("%c",str[k]);
}
i=j-1;
printf(" ");
}
}
for(k=0;k<=i;k++)
{
printf("%c",str[k]);
}
}
using stack
#include <iostream>
#include <stdio.h>
#include <stack>
int main()
{
std::stack<string> st;
char *words= "this is a test";
char * temp = (char *)calloc(1, sizeof(*temp));
int size1= strlen(words);
int k2=0;
int k3=0;
for(int i=0;i<=size1;i++)
{
temp[k2] = words[i];
k2++;
if(words[i] == ' ')
{
k3++;
if(k3==1)
temp[k2-1]='\0';
temp[k2]='\0';
st.push(temp);
k2=0;
}
if(words[i] == '\0')
{
temp[k2]='\0';
st.push(temp);
k2=0;
break;
}
}
while (!st.empty())
{
printf("%s",st.top().c_str());
st.pop();
}

Resources