How to print a word with specific character in C? - c

Sample Input: Stack Overflow is Awesome
Character to Search: e
Output: Overflow Awesome
I wrote a code to split a string by space and store as words but i don't know how to check and print the result
#include <stdio.h>
#include <string.h>
int main()
{
char str1[100];
char newString[10][10];
int i,j,ctr;
printf("\n\n Split string by space into words :\n");
printf("---------------------------------------\n");
printf(" Input a string : ");
fgets(str1, sizeof str1, stdin);
j=0; ctr=0;
for(i=0;i<=(strlen(str1));i++)
{
// if space or NULL found, assign NULL into newString[ctr]
if(str1[i]==' '||str1[i]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=str1[i];
j++;
}
}
printf("\n Strings or words after split by space are :\n");
for(i=0;i < ctr;i++)
printf(" %s\n",newString[i]);
return 0;
}

You can use strchr() to easily check a string for a specific chararacter
for (i = 0; i < ctr; i++) {
if (strchr(newString[i], 'e') != NULL) {
printf(" %s\n", newString[i]);
}
}

Add the following lines at end to your code to print the filtered strings/words by character e
printf("\n Strings or words Containing character 'e' :\n");
for(i=0;i < ctr;i++)
if(strchr(newString[i], 'e') != NULL)
printf(" %s\n",newString[i]);

Since you are parsing str1 in order to find the beginning and the end of each word, why not using the for loop to detect if the current word contain the letter that you search ?
There are many little "error" too : do not use "strlen" in the for loop, it will be call each time ! Instead, detect '\0' !
Your result array newString is unsafe ! It should be [50][100] because you can input a string of one word with 100 char ( so [1][100] ) or 50 letter and 50 blank (so [50][2] ). So the result array must be [50][100] in order to take any possibility.

I would suggest to split the string using the strtok and using the strchr to check if the substring contains the letter e. In this way you can loop a single time over the original string and perform both the splitting and the checking.
Something like this:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="Stack Overflow is Awesome";
char* pch;
char* pch2;
//split string by spaces
pch = strtok (str," ");
while (pch != NULL)
{
//check if the substring contains the letter 'e'
pch2 = strchr(pch,'e');
if (pch2 != NULL) {
printf ("%s\n",pch);
}
pch = strtok (NULL, " ");
}
return 0;
}

Related

Trouble cycling through a string

I'm having trouble looping through a string and replacing instances of a character with a new character. I'm attempting to do so with a function that I've called replace.
// C program to replace all occurrences of a character with another in a string
#include <stdio.h>
#include <string.h>
/* Function declaration */
void replace(char *string, char toReplace, char replaceWith);
int main()
{
char string[100];
char toReplace, replaceWith;
printf("Enter any string: ");
scanf("%s", string);
printf("Enter character to replace: ");
scanf("%c\n", &toReplace);
getchar();
printf("Enter character to replace '%c' with: ", toReplace);
scanf("%c\n", &replaceWith);
replace(string, toReplace, replaceWith);
// print new string
printf("%s\n", string);
return 0;
}
// Replaces the all occurrence of a character with another in given string.
void replace(char *string, char toReplace, char replaceWith)
{
for (int i = 0; i <= strlen(string); i++)
{
if (string[i] == toReplace)
{
string[i] = replaceWith;
}
}
}
Snippets of code causing me the most grief are:
printf("Enter character to replace '%c' with: ", toReplace);
Does not print what I expect it to.
if (string[i] == toReplace)
Treats string[i] as the entire string, and not the individual members of the string.
Changing
scanf("%c\n", &toReplace);
to
scanf(" %c", &toReplace); helped, as this now ignores leading whitespace.
Your replace function is OK except for a few details:
you should not recompute the length of the string at each iteration, especially as the compiler cannot assume the string to be constant since it gets modified inside the loop.
the test should be i < len where len is the length of the string. It seems incorrect to test the null terminator for replacement.
i should be defined with type size_t instead of int.
The problem you observe is linked to your usage of scanf():
"%c\n" will read the pending newline from stdin and then consume any subsequent white-space, which should not occur as the user typed the character they were prompted for. The next call will read this character, consume the newline and leave the second character typed pending in stdin. You should use scanf(" %c", &toReplace) instead.
note also that scanf("%s", string); will stop at the first white-space character and may cause a buffer overflow. Using fgets() seems a better approach for this.
Here is a modified version:
#include <stdio.h>
#include <string.h>
/* Function declaration */
void replace(char *string, char toReplace, char replaceWith);
int main() {
char string[100];
char toReplace, replaceWith;
printf("Enter any string: ");
if (!fgets(string, sizeof string, stdin))
return 1;
printf("Enter character to replace: ");
if (scanf(" %c", &toReplace) != 1)
return 1;
printf("Enter character to replace '%c' with: ", toReplace);
if (scanf(" %c", &replaceWith) != 1)
return 1;
replace(string, toReplace, replaceWith);
// print new string
printf("%s", string);
return 0;
}
// Replaces the all occurrence of a character with another in given string.
void replace(char *string, char toReplace, char replaceWith) {
for (size_t i = 0, len = strlen(string); i < len; i++) {
if (string[i] == toReplace) {
string[i] = replaceWith;
}
}
}

Do-while or while loop that will keep taking an input from user but will terminate after I input the string "exit" (case insensitive) in c language

#include <stdio.h>
#include <ctype.h>
int main() {
char str[100];
char out[] = "exit";
do {
printf("Enter a string: ");
scanf("%s", str);
// some if else statement here
} while (toupper(str[3]) != toupper(out[3]));
}
I put the index 3 because if I put the index 0 there, the code will terminate if the entered string starts with letter e. I tried the while loop but it does not work for me. Also I want to print a prompt message that says "detected terminate keyword" after entering the word "exit" and then terminates the loop.
You will also notice the toupper() function. I used it there because I want my loop to be case insensitive, so regarless of lowercase or uppercase or combination of both, the loop should terminate when the word "exit" is entered.
toupper(str[3]) != toupper(out[3]) will compare the upper case 4th letter of str and out, so the loop will iterate till str[3] is 'T'. You want to use strcasecmp(str, out) instead. Remember to #include <strings.h>.
There are multiple problems:
it is confusing for a function isPalindrome() to return 0 for true.
to avoid undefined behavior on negative char values, a char argument to toupper should be cast as (unsigned char).
the test for the exit keyword is incorrect. You exit if the fourth letter is a t or a T. You should use strcasecmp to test for the exit word.
scanf("%s", str) has potential undefined behavior if the user enters a word with more than 99 bytes. Use scanf("%99s", str) and test the return value: it must be 1 for a successful conversion.
instead of a confusing do / while loop, use a for (;;) loop (also known as for ever loop), and test for 2 exit conditions: scanf() failure to read a word and reading the word exit.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int isPalindrome(const char *str) {
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
if (toupper((unsigned char)str[i]) != toupper((unsigned char)str[len - i - 1]))
return 0;
}
return 1;
}
int main() {
char str[100];
for (;;) {
printf("Enter a string: ");
if (scanf("%99s", str) != 1)
break;
if (!strcasecmp(str, "exit"))
break;
if (isPalindrome(str)) {
printf("%s is a palindrome!\n\n", str);
} else {
printf("%s is not a palindrome!\n\n", str);
}
}
return 0;
}
I put the index 3 because if I put the index 0 there, the code will terminate if the entered string starts with letter e
Exactly, and the code:
while (toupper(str[3]) != toupper(out[3])
Suffers from the same problem, any input with a t as its 4th character index 3 will match and the loop will end, you are comparing a specific character of the string, not the string itself. You can use strcasecmp to assess if the input is indeed exit and ignore casing.
Furthermore using %s specifier is not good, you run the risk of overrunning the destination buffer. You should use a width, %99s for a 100 characters buffer to leave space for the nul byte, if possible consider using fgets instead.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main() {
char str[100];
char out[] = "exit";
do {
printf("Enter a string: ");
scanf(" %99s", str); // space before specifier to clean leading whitespaces
// some if else statement here
} while (strcasecmp(str, out) != 0);
puts("Detected terminate keyword. Goodbye!");
}
char *removeLastChar(char *str, char ch)
{
size_t len;
if(str)
{
len = strlen(str);
if(str[len - 1] == ch) str[len -1] = 0;
}
return str;
}
char *strlwr(char *str)
{
char *wrk = str;
if(str)
{
while(*wrk)
{
*wrk = tolower((unsigned char)*wrk);
wrk++;
}
}
return str;
}
int main(void)
{
char str[100];
const char *out = "exit";
int x = 0;
do
{
printf("Enter a string: ");
if(!fgets(str, sizeof(str), stdin)) break;
removeLastChar(str, '\n');
printf("You entered: \"%s\"\n:", str);
} while (strcmp(strlwr(str), out));
}

Taking multiple strings and integers in a single line

I want to take multiple integer and strings in a single line such as "45 A4 Paper 217" but I want to store string A4 Paper in a single char array. I tried using scanf but it scans until space for string.
int int1;
int int2;
char str1[81];
scanf("%d %s %d",&int1,&str1,&int2);
I want str1 to be A4 Paper in str1 array
The scanf family functions are known as a poor man's parser. They can easily parse blank separated tokens, but anything more complex is at best tricky, or even impossible - more exactly other tools should be used.
Your requirement is to accept in a single string any token until an integer token is found (token here being a blank delimited string). This is just not possible in single scanf.
If the type and number of blank characters does not matter, you could use a scanf loop first trying to find an integer, next getting tokens as string:
i = scanf("%d", &int1); // get first integer
if (i != 1) {
// error condition
}
char *cur = str1;
for(;;) {
if (1 == scanf("%d", &int2)) break; // ok we have found the second integer
i = scanf("%s", cur);
if (i != 1) {
// error condition
}
cur += strlen(cur); // move cur to end of string
*cur++ = ' '; // and add a space
}
if (cur != str1) {
cur[-1] = '\0'; // erase last space
}
This should detect read errors, but does not even try to control overflow of str1. It should be added for production grade code.
This is my solution
#include <stdio.h>
#include <string.h>
int main() {
int int1,int2;
char str[100],str1[81];
char *p;
scanf("%[^\n]s",str);
p = strtok (str," ");
sscanf(p, "%d", &int1);
p = strtok (NULL, " ");
strcpy(str1,p);
strcat(str1," ");
p = strtok (NULL, " ");
strcat(str1,p);
p = strtok (NULL, " ");
sscanf(p, "%d", &int2);
printf("%d %s %d",int1,str1,int2);
return 0;
}

string checks the alphabet letters wth tabs in c pangramm

I have written this code but I have a little problem with it.
This code should get a string and check whether this string contains all the alphabet letters...
If it doesnt the output is "Not a pangramma!".
If it does "PanGramma!".
The probem is that I want it to count also the nuumber of the spaces between the words. But when the input is string with at least one space the output will always be "Not a PanGramma!", even if it contains all the alphabet letters.
Can someone please help me?
#include <stdio.h>
char UpCase (char c);
int isPangram (char *str);
int main()
{
char str[100];
printf("Please enter yout string: \n");
scanf("%s", str);
if (isPangram (str) == 1)
{
printf("PanGramma!\n");
}
else
{
printf("Not a PanGramma!\n");
}
return 0;
}
char UpCase (char c)
{
if (c>='a' && c<='z')
{
return c-'a'+'A';
}
return c;
}
int isPangram (char *str)
{
int i=0;
int hist[27]={0};
while (str[i] !=0)
{
str[i]=UpCase(str[i]);
if (str[i] == ' ')
{
hist[26]++;
}
else
{
hist[str[i] - 'A']++;
}
i++;
}
for (i=0; i<26; i++)
{
if(hist[i] == 0)
{
return 0;
}
}
return 1;
}
Your problems comes from the usage of scanf function: it does stops at each white space it catch.
From man scanf:
%s
Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
To make your program to work, you can use fgets function:
int main()
{
char str[100];
printf("Please enter yout string: \n");
fgets(str, sizeof str, stdin);
if (isPangram (str) == 1)
{
printf("PanGramma!\n");
}
else
{
printf("Not a PanGramma!\n");
}
return 0;
}
If you want to know more on scanf function, you can read A beginners' guide away from scanf(). It will also tell you why scanf could cause a buffer overflow in your code.
Thank you guys!
I have used this
scanf ("%[^\n]%*c", str);
thanks once again for your help!

Tokenizing a string

I am in the process of writing a C program that parses a string and tokenizing it by breaking the string characters into words that are seperated by white space. My question is when i run my current program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input[20];
printf("Please enter your word:\n");
scanf("%c", &input);
printf("%c", input[1]);
return 0;
}
If i was to enter the word "This", i would expect to get back "h" when i run the program but instead i get a downwards pointing arrow. However, when the input is set to print out input[0] i get back a "T".
Edit: I have modified my code so that it prints out the whole string now which i will show below
int main()
{
char input[20];
printf("Please enter your words:\n");
scanf("%s", input);
printf("%s", input);
return 0;
}
My goal is to be able to break that string into chars that i can search through to find whitespace and thus being able to isolate those words for example, if my input was "This is bad" i'd like the code to print out
This
is
bad
Edit:
I have modified my code to fit one of these answers but the problem i run into now is that it won't compile
int main()
{
char input[20];
printf("Please enter your words:\n");
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
}
printf("%c", input[]);
return 0;
Problems:
1) scanf("%c", input); only set the first element of the array input.
2) printf("%c", input[1]); prints the second element of the array input, which has uninitialized data in it.
Solution:
Small state machine. No limit on string size like 20.
#include <ctype.h>
#include <stdio.h>
int main() {
int ch = fgetc(stdin);
while (ch != EOF) {
while (isspace(ch)) {
// If only 1 line of input allowed, then add
if (ch == '\n') return 0;;
ch = fgetc(stdin);
}
if (ch != EOF) {
do {
fputc(ch, stdout);
ch = fgetc(stdin);
} while (ch != EOF && !isspace(ch));
fputc('\n', stdout);
}
}
return 0;
}
scanf("%c", &input); does not do what you think it does.
First of all, %c scans only a single character: http://www.cplusplus.com/reference/cstdio/scanf/
Second, array's name is already a pointer to it's first element, so stating &input you make a pointer to a pointer, so instead of storing your character in array's first element you store it in pointer to the array which is a very bad thing.
If you really want to use scanf, I recommend a loop:
size_t offset = 0;
do
{
scanf("%c", input + offset);
offset++;
}
while(offset < sizeof(input) && input[offset - 1] != '\n');
Using scanf("%s", input") leaves you vulnerable to buffer overflow attacks if the word is longer than 20 characters http://en.wikipedia.org/wiki/Buffer_overflow
In my example I assumed, that you want to finish your word with a newline character.
EDIT: In scanf documentation is also a good example:
scanf("%19s", input);
It scans no more than 19 characters, which also prevent buffer overflow. But if you want to change input size, you have to change it two places.
You can use
char * strtok ( char * str, const char * delimiters );
to tokenize your string. If you have your input in input[] array and want to tokenize the string accoring to whitespace character, you can do the following :
char *ptr;
ptr = strtok(input, " ");
while(ptr != NULL) {
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
Only the first call to strtok() requires the character array as input. Specifying NULL in the next calls means that it will operate on the same character array.
Your scanf only picks up the first character, input[1] contains random garbage. Use scanf("%19s", input) instead.

Resources