seperate the word from a sentence without library function - c

Here i wrote a code to separate the words from a given sentence without using strtok() function.But the problem is it only prints the first word.Why rest of the words don't get printed ?
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This, a sample string.";
int i=0,k,begin,end;
while(str[i]!='\0'){
while(str[i]==' '){
i++;
}
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
char *ptr =(char *)malloc((end-begin)*sizeof(char));
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
}
}

The complete code should be like this.
I have changed code on top of your code.
int main ()
{
char str[] ="This, a sample string.";
int i=0,k,begin,end;
int t;
while(str[i]!='\0'){
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
char *ptr = (char *) malloc( (i-begin)*sizeof(char) + 1);
t=0;
for(k=begin;k<=end;k++){
ptr[t++] = str[k];
}
ptr[t] = '\0';
puts(ptr);
if(str[i]=='\0'){
break;
} else
while(str[i] == ' ') i++; //To avoid multiple spaces
}
return 0;
}
-Thanks

The problem with your code is here:
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
the k is being used as index variable for both ptr and str, what you should do is use a separate variable for ptr, so that it fills up characters from 0 index.
Also you are not allocating the correct amount of space. The number of characters are end - begin + 1 and you also have to allocate space for null character(string terminating character).
So correct allocation is:
char *ptr =(char *)malloc((end-begin+2)*sizeof(char));
and your correct code is:
int index = 0;
for(k = begin;k <= end; k++){
ptr[jj++] = str[k];
}
ptr[end - begin + 1] = '\0';

If you're allowed to modify the string in-place, you could do something like
#include <stdio.h>
static void print_words(char *str) {
char *start = str; // Word start pointer.
for(;*str;str++) { // While there are characters...
if(*str == ' ') { // Space found!
*str = '\0'; // Replace the space with a null to end the string
printf("%s\n", start); // Output the now null-delimited string
*str = ' '; // Return the string to its original form
start = str + 1; // Advance the word-start pointer
}
}
printf("%s\n", start); // Print the last word remaining unprinted, if any
}
int main()
{
char str[] = "This, a sample string.";
print_words(str);
}

You have missed some logics in your code.
you are traversing to second word by default. Which is not your requirement.
This block identifies word from given string.
You are allocation one byte less than we need.
One extra byte is required for termination string. null char.
**4. ptr[k] = str[k]
This is the hole in your code.
This should be like ptr[0] = str[k];**
you missed incrementing i value to iterate further.
==================point 1=======================
while(str[i]!='\0'){
while(str[i]==' '){ -> this is point no 1. This logic will skip first word
i++;
}
=================point 2 ================
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
**end = i-1;**
==========================================
char *ptr =(char *)malloc((end-begin)*sizeof(char)); -> point 3.
point 4 :
for(k=begin;k<=end;k++){
ptr[k] = str[k];
}
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
point 5 :
else
i++;
}
-Thanks

I have found the problem and come up with the solution :
1.First problem is i was not assigning the correct value to *ptr.so , i used a variable j to start from the beginning of current index
2.I needed to null terminate each capture
ptr[k]='\0';
3.So the changes i made overall is the following :
for(k=0,j=begin;k<=end-begin;k++,j++){ // use a variable j to start from the beginning of current index
ptr[k] = str[j];
}
ptr[k]='\0';
Full code:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This, an sample string.";
int i=0,j,k,begin,end;
char *ptr;
while(str[i]!='\0'){
while(str[i]==' '){
i++;
}
begin = i;
while(str[i]!=' ' && str[i]!='\0'){
i++;
}
end = i-1;
ptr =(char *)malloc((end-begin)*sizeof(char));
for(k=0,j=begin;k<=end-begin;k++,j++){ // use a variable j to start from the beginning of current index
ptr[k] = str[j];
}
ptr[k]='\0';
printf("%s\n",ptr);
if(str[i]=='\0'){
break;
}
}
}

Related

How many this word in the array string

I want to count how many this word and operator in the string but I try to use strchr and it doesn't work.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
int x,count =0;
char buff[100]="1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
//gets(buff);
strupr(buff);
for (int i = 0; buff[i] != '\0'; i++)
{
if (buff[i] == '+' || buff[i] == '-' || buff[i] == '*' ||
buff[i] == '/' || buff[i] == '^'|| buff[i] == '(')
{
count++;
}
}
char *op2;
int check=0;
char cpysin[100],cpycos[100];
strcpy(cpysin,buff);
strcpy(cpycos,buff);
do
{
if(strchr(cpysin,'SIN')!=0)
{
count++;
strcpy(cpysin,strstr(cpysin,"SIN"));
cpysin[0] = ' ';
cpysin[1] = ' ';
cpysin[2] = ' ';
}
else
{
break;
}
}
while(check==0);
do
{
if(strchr(cpycos,'COS')!=0)
{
count++;
strcpy(cpycos,strstr(cpycos,"COS"));
cpycos[0] = ' ';
cpycos[1] = ' ';
cpycos[2] = ' ';
}
else
{
break;
}
}
while(check==0);
printf("FINAL \n%d",count);
}
I only work when I do it in the loop while trying to find how many sins are in there but it doesn't work when I put cos function on it. Please tell me how to fix this and what if I need to write more functions to find.
strchr(cpysin, 'SIN') is wrong.
Unfortunately the compiler may not give you a warning because 'SIN' can be interpreted as 4 byte integer. The second parameter is supposed to be an integer, but strchr really wants character, it chops it off to 'N'
Just remember that in C you work with single characters 'a' or strings "cos" (or you can come accross wide characters/strings)
Use strstr to find a string. For example, to find "cos":
char* ptr = buff;
char* find = strstr(ptr, "cos");
"1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
---------------^ <- find
find will point to "cos + cos sin_e-2x+x2*2!/_x1 sine"
You can increment ptr and look for the next occurrence of "cos".
Also note, you can declare char buff[] = "...", you don't have to assign the buffer size.
char buff[] = "1+2.3(7^8)sin cos + cos sin_e-2x+x2*2!/_x1 sine";
int count = 0;
const char* ptr = buff;
const char* text = "cos";
//must terminate when ptr reaches '\0' which is at the end of buff
//there is serious problem if we read past it
while(*ptr != '\0')
{
char* find = strstr(ptr, text);
if (find != NULL)
{
printf("update [%s]\n", find);
count++;
ptr = find + strlen(text);
//next search starts after
}
else
{
ptr++;
//next character start at next character
}
}
printf("%s count: %d\n", text, count);

C - Reverse order of words in an array of Strings

I did this program to reverse the order of the words in the give string. (And it works)
i.e. Output: sentence first the is This
However I am stuck when it comes to adding another sentence to the array.
For example I need to have an array {"This is the first sentence", "And this is the second"} producing as output: sentence first the is This , second the is this And
int main() {
char str[] = {"This is the first sentence"};
int length = strlen(str);
// Traverse string from end
int i;
for (i = length - 1; i >= 0; i--) {
if (str[i] == ' ') {
// putting the NULL character at the position of space characters for
next iteration.
str[i] = '\0';
// Start from next character
printf("%s ", &(str[i]) + 1);
}
}
// printing the last word
printf("%s", str);
return 0;
}
I am new to C so its not surprising that I got stuck even if the solution is quite easy. Any help would be appreciated! Thanks!
Since you already have the code to print the words of one string in reverse order, I would suggest making that a function which takes a single string as an argument, i.e.:
void print_words_reverse(char * const str) {
// your current code here
}
Then you can call it separately for each string:
char strings[][30] = {
"This is the first sentence",
"And this is the second"
};
for (int i = 0; i < sizeof(strings) / sizeof(*strings); ++i) {
print_words_reverse(strings[i]);
}
Note that since you are modifying the string (by replacing spaces with NUL bytes), the argument needs to be modifiable, which means you are not allowed to call it (in standard C) with a pointer to a string literal, which means you can't simply use const char *strings[] = { "first", "second" }. You could get rid of the ugly constant length (here 30) reserved for every string by making your code not modify the argument string. Or you could have a separate char array for each sentence and then use pointers to those (modifiable) strings.
First, you can try with a two-dimensional array or use an array of pointers.
Secondly, in your approach, you lose the initial value of your string, I don't know how important it is.
This is my fast approach using arrray of pointers.
#include <stdio.h>
#include <string.h>
static void print_word(const char *str)
{
for (int i = 0; str[i] && str[i] != ' '; i++)
printf("%c", str[i]);
putchar(' ');
}
int main(void)
{
int len;
const char *str[] = {"This is the first sentence",
"And this is second", NULL};
for (int i = 0; str[i]; i++) {
for (len = strlen(str[i]); len >= 0; len--) {
if (len == 0)
print_word(&str[i][len]);
else if (str[i][len] == ' ')
print_word(&str[i][len + 1]);
}
putchar('\n');
}
printf("Initial value of array of strings [%s | %s] \n", str[0], str[1]);
return 0;
}
output is:
sentence first the is This
second is this And
Initial value of array of strings [This is the first sentence | And this is second]
I suggest you using memcpy but without altering too much your code this seems to work
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_STRING_LENGTH 100
int main()
{
char *str[] = {"This is the first", "And this is the second sentence"};
const size_t NUM_STRING = sizeof(str)/sizeof(char*);
/*%z used to print size_t variables*/
printf("%zd strings found\n", NUM_STRING);
int length[2];
int i;
for (i=0; i<NUM_STRING; i++)
{
length[i] = strlen(str[i]);
}
printf("length initialized %d %d\n", length[0], length[1]);
// Traverse string from end
int j = 0;
char temp[MAX_STRING_LENGTH];
printf("\n\n");
for (j=0; j<NUM_STRING; j++)
{
/*Make sure the string respect the MAX_STRING_LENGTH limit*/
if (strlen(str[j])>MAX_STRING_LENGTH)
{
printf("ERROR: string %d exceding max string length %d defined in constant "
"MAX_STRING_LENGTH. Exiting from program.\n", j, MAX_STRING_LENGTH);
exit(1);
}
//reset temporary string
memset(temp, '\0', sizeof(temp));
//printf("temp variable reinitialized\n");
for (i = length[j] - 1; i >= 0; i--)
{
temp[i] = str[j][i];
if (str[j][i] == ' ')
{
// putting the NULL character at the position of space characters for next iteration.
temp[i] = '\0';
// Start from next character
printf("%s ", &(temp[i]) + 1);
}
}
// printing the last word
printf("%s ", temp);
}
printf("\n");
return 0;
}

Program to find the longest word in a string

I wrote a program to find the longest word in a string and print the number of letters in the longest word. But the code is not printing. I analyzed the program many times but I could not find the solution.
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i = 0, letters = 0, longest = 0;
start:
for (; string[i] !=' '; i++) {
letters++;
}
if (letters >= longest)
longest = letters;
if (string[i] == ' ') {
letters = 0;
i++;
goto start;
}
printf("%d", longest);
return 0;
}
Using goto is highly discouraged. You should convert your code to use a loop.
The main problem in your code is you do not stop the scan when you reach the end of the string.
Here is a modified version:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
for (letters = 0; string[i] != '\0' && string[i] != ' '; i++) {
letters++;
}
if (letters > longest) {
longest = letters;
longest_pos = i - longest;
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Note that the implementation can be simplified into a single loop:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, start = 0, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] == ' ') {
start = i + 1;
} else {
if (i - start > longest) {
longest = i - start;
longest_pos = start;
}
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Below is my approach. You should use C's string manipulation functions. This is the correct way to deal with strings in C.
In the code below, first I acquire the required bytes to store the input string in heap. Then I use strtok to split the string into tokens based on a delemeter and get the length of each sub string. Finally I free the space that I have allocated with malloc.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define phrase "Hello Kurnool"
int main()
{
char* string = malloc(strlen(phrase)+1);
strcpy(string,phrase);
int longest=0;
char *token;
char delimeter[2] = " ";
/* get the first token */
token = strtok(string, delimeter);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
if(longest < strlen(token)){
longest = strlen(token);
}
token = strtok(NULL, delimeter);
}
printf("%d",longest);
free(string);
return 0;
}
People say - dont use goto but there is nothing inherently wrong with goto. Only thing is if goto is not used judiciously, it makes code more difficult to understand and maintain. For example, the way you have used it in your program ( instead of goto, a loop is perfect fit in such cases). Check this:
To use goto or not?
What is wrong with using goto?
Coming to your code, the for loop condition does not have check for terminating null character
for (; string[i] !=' '; i++) {
Hence it will not stop at the end of string.
To find the number of letters in longest word of string, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters = 0, longest = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] != ' ') {
letters++;
if (letters > longest) {
longest = letters;
}
} else {
letters = 0;
}
}
printf("longest : %d\n", longest);
return 0;
}
First of all,Please avoid using Goto, it is not a good practice.
Secondly, your loop will run infinite times when it iterates the second time because:
for(;string[i]!=' ';i++) // Here String[i] will never be equal to ' ' As there is no white space after your last word.
You can never expect what might be going wrong with your program if you are using
goto statement
which is never advisable to use rather it's bad programming if you use it. Secondly it looks like you are stuck in an infinite loop so her is a solution to your problem:
#include<stdio.h>
#include<string.h>
void main()
{
char s[1000];
scanf("%s",s);
int i=0;
int letters;
int longest=0;
while(s[i]!=NULL)
{
if(s[i]==' ')
{
if(longest>=letters)
{longest=letters;}
letters=0;
}
else
{letters++;}
}
printf("%d\n",longest);
}
So, what I have done is assuming a string s which is the input given by the user. You itterate through s till the last input given by the user after which it encounters a NULL character. Now you are searching for the length of the longest word, so you create a variable letters for counting the no. of letters in each word of the string. And if the string s encounters a space indicating the end of a word, then you check if the variable longest is greater than or less than the word count. And again you initialize letters to 0, so that it can start counting the next word from 0 again.So, by this method at the end i.e. after the while loop terminates we get our required output which is stored in the variable longest.
So, I guess this will print the no. of letters in the longest word.

2D Pointer to 2D Pointer

I forgot most of my C, so please forgive me if this is a stupid question. Because I need to separate a string of words into individual words.
#include "argsInfo.h"
#include <stdlib.h>
/* Parses string argument which contains words
* separated by whitespace. It returns an
* argsInfo data structure which contains an
* array of the parsed words and the number
* of words in the array.
*/
argsInfo getArgsInfo(char * string) {
argsInfo info;
char ** temp;
int nWords=1;
int i=0;
int j,k;
//Test if the the input string is empty
if (string[0] == '\0'){
nWords=0;
}else{
//First I need to check how long the input String is, as-well as cout how many words are in the string.
while (string[i] != '\0'){
if (string[i] == ' '){
nWords++;
}
i++;
}
}
//This allocates enough memory for each word.
temp = (char**) malloc(nWords*sizeof(char*));
for (j=0;j<nWords;j++){
temp[j] = (char*) malloc(i*sizeof(char));
}
j=0;
k=0;
// If I encounter a white space, it signifies a new word, and I need to move it to the next element
while (j < i){
if (string[j] == ' '){
k++;
}
temp[k][j] = string[j];
j++;
}
info.argc = nWords;
info.argv = temp;
return info;
}
That 3rd last LINE. THAT'S where I think the problem is. info.argv = temp;
This is what the struct looks like:
typedef struct {
int argc;
char ** argv;
} argsInfo;
Example Input and Output:
Input: "ax bcd efghij"
Output: ax
If I remove the k++ line, the output becomes: ax bcd efghij
Likewise, if I input a b c. Only 'a' will show up when I run through the array.
First, this part is inefficient but works:
for (j=0;j<nWords;j++){
temp[j] = (char*) malloc(i*sizeof(char));
}
You are using the value of i which will be equal to the total number of characters in your original input string. This means that for each separate word you are allocation enough room to store the original sentence which is a waste of space.
You could, for example, while you are counting words, also remember the longest word seen thus far and use that as your allocation factor which will probably be much less than the whole sentence. We start the length at 1 to include the terminating character '\0'
int longest = 1;
int tempLength = 1;
//Test if the the input string is empty
if (string[0] == '\0'){
nWords=0;
}else{
//First I need to check how long the input String is,
//as-well as count how many words are in the string.
while (string[i] != '\0'){
if (string[i] == ' '){
if(tempLength > longest) {
longest = tempLength;
}
nWords++;
} else {
tempLength++; // count characters of current word
}
i++;
}
}
for (j=0;j<nWords;j++){
temp[j] = (char*) malloc(longest*sizeof(char));
}
Finally, the last part of your code needs a fix. It doesn't work because you are using j as an index in the overall sentence and as an index in a single word. You never reset j.
Let's say the first word is
apple
Once you encounter a space, you will have:
j = 5
temp[0] = "apple"
Now you increment k to 1 but j stays the same so you will start storing characters of the next word from position 5 instead of 0:
temp[1][5] = string[5];
Instead of:
temp[1][0] = string[5];
Therefore, you have 3 indexes to worry about:
Index a that iterates over the input string.
Index b that iterates over a single word of the string.
Index c that iterates over the array of words.
The code:
int a, b, c;
for(a = 0, b = 0, c = 0; a < i; a++) { // index i holds the total number of chars in input string
if(string[a] != ' ') {
temp[c][b] = string[a];
b++;
} else {
temp[c][b] = '/0'; // add terminating character to current word
b = 0;
c++;
}
}
info.argc = nWords;
info.argv = temp;
return info;
Pretty sure this is what you were after. This should only require scanning the string once. Your index math has several issues:
Your calculation of i is inefficient.
The hoops nWords seems to go through questionable
You don't seem to be interested in terminating each word, which is very bad.
That said, walk through the following very carefully in a debugger to see how it works.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
argsInfo getArgsInfo(const char * s)
{
argsInfo info = {0,NULL};
while (*s)
{
// find start of next word
while (*s && isspace((unsigned char)*s))
++s;
// find end of next word
const char *beg = s;
while (*s && !isspace((unsigned char)*s))
++s;
if ((s - beg) > 0)
{
char **tmp = realloc(info.argv, (info.argc+1)*sizeof(*tmp));
if (tmp)
{
info.argv = tmp;
tmp[info.argc] = malloc((s - beg + 1) * sizeof(char));
if (tmp[info.argc] != NULL)
{
memcpy(tmp[info.argc], beg, s-beg);
tmp[info.argc++][s-beg] = 0; // <<= TERMINATE
}
else
{
perror("Failed to allocate string");
exit(EXIT_FAILURE);
}
}
else
{
perror("Failed to expand string pointer array");
exit(EXIT_FAILURE);
}
}
}
return info;
}

remove a character from the string which does not come simultaneously in c

for example, given the string str1 = "120jdvj00ncdnv000ndnv0nvd0nvd0" and the character ch = '0', the output should be 12jdvj00ncdnv000ndnvnvdnvd. That is, the 0 is removed only wherever it occurs singly.
this code is not working
#include<stdio.h>
char remove1(char *,char);
int main()
{
char str[100]="1o00trsg50nf0bx0n0nso0000";
char ch='0';
remove1(str,ch);
printf("%s",str);
return 0;
}
char remove1(char* str,char ch)
{
int j,i;
for(i=0,j=0;i<=strlen(str)-1;i++)
{
if(str[i]!=ch)
{
if(str[i+1]==ch)
continue;
else
str[j++]=str[i];
}
}
str[j]='\0';
}
Your code looks for an occurrence of something other than the character to be removed with "if(str[i]!=ch)", then if the next character is the one to be removed it skips (i.e. does not keep the characters it has just seen), otherwise it copies the current character. So if it sees 'a0' and is looking for '0' it will ignore the 'a'.
What you could do is copy all characters other than the one of interest and set a counter to 0 each time you see one of them (for the number of contiguous character of interest you've seen at this point). When you find the one of interest increment that count. Now whenever you find one that is not of interest, you do nothing if the count is 1 (as this is the single character you want to remove), or put that many instances of the interesting character into str if count > 1.
Ensure you deal with the case of the string ending with a contiguous run of the character to be removed, and you should be fine.
char *remove1(char* str, char ch){
char *d, *s;
for(d = s = str;*s;++s){
if(*s == ch){
if(s[1] == ch)
while(*s == ch)
*d++=*s++;
else
++s;//skip a ch
if(!*s)break;
}
*d++ = *s;
}
*d = '\0';
return str;
}
Code to copy the basic
for(d = s = str;*s;++s){
*d++ = *s;
}
*d = '\0';
Special processing to be added.
for(d = s = str;*s;++s){
if(find a character that is specified){
Copy that in the case of continuously than one character
if one letter then skip
}
*d++ = *s;
}
*d = '\0';
Here is the working code
output is : "1o00trsg5nfbxnnso0000"
#include<stdio.h>
char remove1(char *,char);
int main()
{
char str[100]="1o00trsg50nf0bx0n0nso0000";
char ch='0';
remove1(str,ch);
printf("%s",str);
return 0;
}
char remove1(char* str,char ch)
{
int j,i;
int len = strlen(str);
for(i = 0;i < (len - 1);i++){
if(str[i] == ch){
/* if either of check prev and next character is same then contd. without removal */
if((str[i+1] == ch) || (str[i-1] == ch))
continue;
/* replacing the char and shifting next chars left*/
for(j = i;j < (len - 2);j++) {
str[j] = str[j + 1];
}
/* string length is decrementing due to removal of one char*/
len--;
}
}
str[len] = '\0';
}

Resources