I am new a C. I would like to get help to finish my function.
The mission is:
Write a function that accepts a string maximum length of 256 characters containing characters from 'a' to 'z'.
The function to print the number of occurrences of each character.
For example: input abba output will be:
a = 2 b = 2 c = 0 d = 0 .... z = 0
Do not use if during any function.
I would like to get your help to finish this program please.
This is my code
#include "stdlib.h"
#include "conio.h"
#include "stdio.h"
#include "string.h"
#define size 256
void repeat(char *str);
void main()
{
char str[size];
printf("Please enter a string:\n");
flushall;
gets(str);
repeat(str);
system("pause");
return ;
}
void repeat(char *str)
{
char temp=strlen(str);
int i, count=0;
do
{
for (i=0; i<temp ; i++)
{
count += (*str == str[temp-i]);
}
printf("Char %c appears %d times\n ",*str,count);
count=0;
}
while(*(str++));
}
Please enter a string:
abbba
Char a appears 1 times
Char b appears 2 times
Char b appears 1 times
Char b appears 0 times
Char a appears 0 times
Char appears 0 times
Press any key to continue . . .
this is the output!
I would like to do it in the same building i did.
and should be like
Char a appears 2 times
Chars b appears 3 times
You make a stipulation about not using if. This satisfies that restriction.
#include <stdio.h>
int main(void) {
int i, c;
int counts[256] = { 0 };
const char lower[] = "abcdefghijklmnopqrstuvwxyz";
while ((c = getchar()) != EOF) {
counts[c] += 1;
}
for (i = 0; lower[i]; ++i) {
c = lower[i];
printf("Char %c appears %d times.\n", c, counts[c]);
}
return 0;
}
The problem with your attempt is that you do not track any state to remember which characters you have already printed information about. It also fails to include the character under consideration as part of the count. It also makes multiple passes over the string to collect count information about each character, but that doesn't affect correctness, just performance. If you can somehow remember which character you have already printed out information for, so that you don't do it again when the same character appears later in the string, your method should print out the counts for the characters that appear. Afterwards, you would need to print out zero counts for the characters that did not appear at all. If the outputs need to be in alphabetical order, then you need to make sure you take care of that as well.
One way to track the information properly and to allow your output to be printed in alphabetical order is to maintain counts for each character in an array. After making a pass over the string and incrementing the count associated with each found character, you can iterate over the count array, and print out the counts.
The following program is for zubergu:
#include <stdio.h>
#include <string.h>
int main (void) {
int i, c;
int counts[26] = { 0 };
const char lower[] = "abcdefghijklmnopqrstuvwxyz";
while ((c = getchar()) != EOF) {
switch (c) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z':
counts[strchr(lower, c) - lower] += 1;
break;
default:
break;
}
}
for (i = 0; lower[i]; ++i) {
printf("Char %c appears %d times.\n", lower[i], counts[i]);
}
return 0;
}
It might be one of the ugliest solutions, but also the simplest:
while(*str!='\0')
{
switch(tolower(*str))
{
case 'a': a_count++;break;
case 'b': b_count++;break;
.
.
.
}
str++;
}
It checks if str points to valid letter, then turns it to lower, so it's not case sensitive('A' will be same as 'a' character). No 'if' used and will work with every length char array terminated with '\0' char.
EDIT I have edited the program to follow the requirements of #SagiBinder.
(In my old version, I used an if sentence that checked if the character is in the set 'a'...'z').
The type of temp must be "bigger", that is, something different to char.
Try int, instead.
The algorithm would be this (some details of your program are not repeated here):
int temp = strlen(str);
int i, j;
unsigned char c;
int ch[UCHAR_MAX]; // The macro CHAR_MAX needs the header <limits.h>
for (i = 1; i <= UCHAR_MAX; i++)
ch[i] = 0;
for (j=0; j<temp ; j++) {
c = (unsigned char)(str[j]);
ch[c]++;
}
for (c = 'a'; c <= 'z'; c++)
printf("%c == %d\n", c, ch[c]);
The variable temp holds the length of the string str.
The macro UCHAR_MAX (existing in the header <limits.h>, that you have to #include at the beginning of the program). It is the max. value that holds in a unsigned char.
The array ch[] contains a component for each possible value in the range of the type unsigned char. The intent is that, for some character c, the element ch[c] is the amount of times that c is in str.
I have used unsigned char in order to ensures that the index c of the array ch[] when writting ch[c] is a non-negative integer value, because an array cannot have negative indexes.
The 2nd for goes through the string str. In the step number j, the j-th character of the string str is taken.
This character is a value of type char.
Since one cannot be sure that char have not negative values, I have converted it to (unsigned char) with an explicit cast.
This value is held in the variable c.
The value of c has the (unsigned char version of the) j-th character in str,
so we are going to count it.
How?
Well, we access the array of counters: ch[] with index c, and increment its value in 1:
ch[c]++;
After the for is finished, we have in the array ch[] the information we want.
Finally, we check for the characters from 'a' to 'z'.
(For this, we have supposed that the character encodings in our system follow the convention that the letters have contiguous values).
The 3rd for goes from 'a' to 'z', and the values of the letter (the variable c that controls the for) and the counting of this letter, that is, ch[c].
Moreover: to show the count of any character, you need a re-cast to char, in this way:
printf("%c: %d\n", (char)c, ch[c]);
But this is not necessary with the letters 'a' to 'z', because they belong to the basic execution character set which means that their values are non-negative and equal to their unsigned char counterparts. So, in this case, it is enough to write:
printf("%c: %d\n", c, ch[c]);
EDIT 2: I will use the idea in the answer of #jxh to improve my code.
Since it cannot be guaranted that the encodings of letters 'a' to 'z' are in contiguous order, we can use a string holding the letters:
char letters[] = "abcdefghijklmnopqrstuvwxyz";
The "last" element is, by C convention, a \0 character held after the element 'z'.
Now, we can show the letter counting by changing the 3rd `for` in this way:
for (i = 0; letter[i] != '\0'; i++)
printf("%c == %d\n", letter[i], ch[letter[i]]);
This is equivalent to write:
for (i = 0; letter[i] != '\0'; i++) {
c = letter[i];
printf("%c == %d\n", c, ch[c]);
}
Optimized solution. complexity O(N), N - Input String length.
your void repeat function will be like this,
void repeat(char *str)
{
int temp=strlen(str);// use int here
int i, count=0;
int charCount[26] = {0};
#if 0
//your logic, traverses the string (n*n) time, n - input string length.
do
{
for (i=0; i<temp ; i++)
{
count += (*str == str[temp-i]);
}
printf("Char %c appears %d times\n ",*str,count);
count=0;
}
while(*(str++));
#endif
#if 1
// This logic traverses string once only. n time, n - input string length.
for (i=0; i<temp ; i++)
{
charCount[str[i]%'a']++;
}
for (i=0; i<26 ; i++)
{
printf("%c appears : %d times \n", 'a'+i, charCount[i]);
}
#endif
}
[EDIT]
Here
charCount[str[i]%'a']++; // 'a' is used a its ASCII Value.
You can use it as
charCount[str[i]%97]++;
If you wan to count lower case letter and upper case letter both.
use it like this
if(str[i] >= 'a' && str[i] <= 'z'){
iMap = str[i]%97; // 97 is ASCII Value of 'a'
charCount[iMap]++;
}else if(str[i] >= 'A' && str[i] <= 'Z'){
iMap = str[i]%65; // 65 is ASCII Value of 'A'
charCount[iMap]++;
}
//iMpa is a integer (int iMap;), used for better undersanding.
i = 0;
while (s[i] !=0)
if (( s[i] >= 'a' && s[i] <= 'z') || (s[i] <= 'A' && s[i] >= 'Z'))
{
letters++;
i++;
}
else
if (( s[i] >= '!' && s[i] <= ')'))
{
other++;
}
else
if (( s[i] >= '0' && s[i] <= '9'))
{
numbers++;
}
total = letters + numbers + other;
Related
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int main(void){
char dnachar [10]
int cytosine; //first int
int thymine; //second int
int guanine;
int adenine;
printf("Enter DNA Sequence ");
scanf("%10s",dnachar);
printf("dna:%s\n", dnachar);
for (int i = 0; i < 10; i++){
char x = dnachar[i];
if(x == 'c')
cytosine++;
if(x == 't')
thymine++;
if(dnachar[i] == 'g')
guanine++;
if(dnachar[i] == 'a')
adenine++;
}
printf("%d,%d,%d,%d",thymine, guanine, cytosine, adenine);
return 0;
}
Hi, I am new to C and I noticed that the program only prints the first two ints accurately - cytosine and thymine. The others show a random string of incoherent numbers. Why is that and how can I fix it?
edit: I changed i<20 to i<10, I don't know how I made that mistake.
Among the multitude of things wrong in this code
Wrong format limiter
Given:
char dnachar[10];
The code:
scanf("%10s",dnachar);
will read a string up to 10 characters long, not including the terminating null, which it will always place. Therefore, that scanf can write as many as eleven (11) chars in a space only declared to hold ten (10). The result of a ten character string read (or longer) will be undefined behavior.
Solution:
if (scanf("%9s", dnachar) != 1)
return EXIT_FAILURE;
Note: if your sequences are really ten characters each, then dnachar should be declared as:
char dnachar[11]; // account for 10-chars + terminator
And the format string for scanf should be %10s accordingly.
Indeterminate Counters
All four of your counters are indeterminate. They have no specified initial value as automatic variables, and therefore operations expecting predictable results are unfounded. If they had static linkage (either globals or declared static) they would have default values of 0, but that isn't what your code does.
Solution:
int cytosine = 0;
int thymine = 0;
int guanine = 0;
int adenine = 0;
Incorrect Loop Limit
Given:
for (int i = 0; i < 20; i++){
char x = dnachar[i];
This assumes there are twenty characters in dnachar (which is impossible unless you've invoked undefined behavior from the item above). One you access dnachar[10] and beyond, more undefined behavior. Ideally you stop processing chars when there are no more, which is much easier with a pointer than an index.
Solution:
for (char *p = dnachar; *p; ++p)
{
switch(*p)
{
case 'c':
++cytosine;
break;
case 't':
++thymine;
break;
case 'g':
++guanine;
break;
case 'a':
++adenine;
break;
default:
break;
}
}
I am trying to replace the loop containing repeated getchar calls with a single call to fgets
When I try to type an input I get Segmentation Fault (core dumped) and I don't know what that is or why I get it.
Starter Code
/* Example: analysis of text */
#include <stdio.h>
#include <string.h>
#define MAX 1000 /* The maximum number of characters in a line of input */
main()
{
char text[MAX], c;
int i;
int lowercase, uppercase, digits, other;
int length;
puts("Type some text (then ENTER):");
/* Save typed characters in text[]: */
// In ex1.c, please implement the following loop with fgets() and use strlen() to compute the length of the string
//
for (i = 0; i < MAX; i++)
{
text[i] = getchar();
if (text[i] == '\n')
break;
}
length = i;
/* Analyse contents of text[]: */
for (i = lowercase = uppercase = digits = other = 0; i < MAX; i++)
{
c = text[i];
if (c >= 'a' && c <= 'z')
lowercase++;
else if (c >= 'A' && c <= 'Z')
uppercase++;
else if (c >= '0' && c <= '9')
digits++;
else
{
if (c == '\n')
break;
other++;
}
}
puts("\nYou typed:");
printf("A string with %d characters\n", length);
printf("\t%d lower case letters\n", lowercase);
printf("\t%d upper case letters\n", uppercase);
printf("\t%d digits\n", digits);
printf("\t%d others\n", other);
}
Starter Code Test
Type some text (then ENTER):
asd213qaIW
You typed:
A string with 10 characters
5 lower case letters
2 upper case letters
3 digits
0 others
My Code
/* Example: analysis of text */
#include <stdio.h>
#include <string.h>
#define MAX 1000 /* The maximum number of characters in a line of input */
main()
{
char text[MAX], c;
int i;
int lowercase, uppercase, digits, other;
int length;
puts("Type some text (then ENTER):");
/* Save typed characters in text[]: */
// In ex1.c, please implement the following loop with fgets() and use strlen() to compute the length of the string
//
c = fgets(text, MAX, stdin);
length = strlen(c);
/* Analyse contents of text[]: */
for (i = lowercase = uppercase = digits = other = 0; i < MAX; i++)
{
c = text[i];
if (c >= 'a' && c <= 'z')
lowercase++;
else if (c >= 'A' && c <= 'Z')
uppercase++;
else if (c >= '0' && c <= '9')
digits++;
else
{
if (c == '\n')
break;
other++;
}
}
puts("\nYou typed:");
printf("A string with %d characters\n", length);
printf("\t%d lower case letters\n", lowercase);
printf("\t%d upper case letters\n", uppercase);
printf("\t%d digits\n", digits);
printf("\t%d others\n", other);
}
My Code Test
Type some text (then ENTER):
asd213qaIW
Segmentation fault (core dumped)
Any and all help is greatly appreciated.
I'm also very new to C so if you could explain as simply as possible.
Changing length = strlen(c); to length = strlen(text); fixed it. Thank you!
Your error, or at least one of them, appears to be in the following lines:
char text[MAX], c;
// ...
c = fgets(text, MAX, stdin);
length = strlen(c);
The return value of fgets is a pointer to char, but you’re storing it in a char and then try to pass the char value to a function that expects a pointer to char. Since char is only 8 bits wide (on any machine you’d be compiling on) and a pointer needs 32 or 64 bits, most of the bits get lost and the result is an invalid pointer. This will—if you’re lucky—crash the program with a segmentation fault.
This code really should not have compiled at all. If you didn’t get at least a warning that c cannot hold a pointer to char, you need to turn on more warning flags. (On gcc or clang, I usually compile with -std=c99 -Wall -Wextra -Wpedantic -Wconversion.) Then, at least while you’re learning the language, treat any warning you get as a bug in your program. Better yet, add -Werror (or the equivalent for your compiler) to make the compiler treat them that way.
The simplest fix is to eliminate c and write instead
fgets( text, MAX, stdin );
length = strlen(text);
Suppose if I pass a string like "I am Programmer".
If a letter has occurred one time it should print "I has occurred 1 time", or else if a letter appears twice in the string it should print "a has occurred 2 times", "m has occurred 3 times" and so on for every letter in the string. I searched it and found in some website. Is there any way we could rewrite the code because I didn't understand the code.
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int c = 0, count[26] = {0};
printf("Enter a string\n");
gets(string);
while (string[c] != '\0')
{
/** Considering characters from 'a' to 'z' only
and ignoring others */
if (string[c] >= 'a' && string[c] <= 'z')
count[string[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
/** Printing only those characters
whose count is at least 1 */
if (count[c] != 0)
printf("%c occurs %d times in the entered string.\n",c+'a',count[c]);
}
return 0;
}
Ok here is the rewrite, the original code is better but this one might be easier to understand:
#include <stdio.h>
#include <string.h>
int main()
{
char cur_char;
char string[100];
int index = 0, count[255] = {0};
printf("Enter a string\n");
gets(string);
while (string[index] != '\0')
{
char cur_char = string[index];
// cur_char is a char but it acts as the index of the array like
// if it was an unsigned short
count[cur_char] = count[cur_char] + 1;
index++;
}
for (index = 0; index < 255; index++)
{
if (count[index] != 0)
printf("%c occurs %d times in the entered string.\n", index, count[index]);
}
return 0;
}
A variable type char can be considered as an integer (it's how they are stored in the memory anyway) so you can write:
int test = 'a';
printf("%i", test);
And it will print you 97. Also letters from a to z are represented by continuous intergers, that means 'b' = 98. So taht also means 'b' - 'a' = 1
In your solution, they create an array of 26 integers to count the occurence of each letters betwin 'a' and 'z' (note that they ignore all others including A-Z by doing this)
They decided that in the array count, index 0 is here to count occurences of a, 1 for b .... 25 for z, that explains this:
count[string[c]-'a']++;
If string[c] is a b then string[c]-'a' = 1 so we have our index for count array and increase the amount of occurence of b.
So all you need to understand this code is that you can manipulate a char like an int basically, you should make a quick search about what is ASCII code as well.
If you still need a rewrite of this code to understand, tell me.
I'm new in C and I couldnt find the answer to my question in the forum.
The point is, I need to get a value of deck cards from the user. So it can spread from 2 to 10 and also be 'J', 'Q', 'K' or 'A'. That means it can be a integer or a character.
I'm trying to put it in an integer variable called "_val1". This work for any number from 0 to 10. I expected that if I typed a letter, _val1 would get the ASCII value of that character (wich I could use later for my pourposes). But instead _val1 geta value '0' and the letter is automatically passed to my next variable call (wich is _naipe1).
How can I solve that?
That means, how cam I use scanf to get either a integer value or the ASCII value of a character?
short int _val1, _val2;
char _naipe1, _naipe2;
printf("Qual a 1ª carta?\n Valor:");
scanf(" %hd", &_val1);
printf("Valor 1 = %hd \n", _val1 );
printf(" Naipe:");
scanf(" %c", &_naipe1);
well, if I were you I'd try to simplify the problem:
get the ASCII value of the card representation from '2' to '9' and 'J','Q','K','A' ; there you can simply use a scanf("%c") or even better a getchar() operation.
then either you keep using the ASCII representation of your cards throughout your algorithm, or you can translate it using a mapping function such as:
int map(char card) {
switch (card) {
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return card-'0';
case 'A':
return 1;
case 'J':
return 10;
case 'Q':
return 11;
case 'K':
return 12;
}
}
First, there are 52 cards to a typical poker deck, These are split into 4 suits: hearts, diamonds, spades and clubs. This kind of suggests that user input will be something like: 10s, Ad, 3c, etc (meaning 10 of spades, Ace of diamonds and 3 of clubs) So, not only must you determine the value of the individual card, you also must determine the suit.
This will not solve all of those requirements, but it will at least answer your most direct question, how to read an int or a char using scanf().
This will demonstrate that:
#include <stdio.h>
int main(int argc, char** argv)
{
int aNumber;
char aChar;
printf("\nEnter a number:");
scanf("%d", &aNumber);
printf("\nEnter a character:");
scanf("%c", &aChar);
printf("\nThe number entered is %d\n", aNumber);
printf("\nThe character entered is %c\n", aChar);
return 0;
}
You can also simply have all the values in a string such as
char cards[]={"Ad Js 10c 2c Qh"};
Then parse it using strtok(), then test each token for its ascii content, using functions like isdigit() or isalpha()
Note: you will have to map each card to a value to keep them straight, something like this abbreviated enum may work:
enum {
AD = 1, //start enum values at 1 for the diamonds suit
2D,
3D,
...//fill in rest of cards here
JC,
QC,
KC, // last card == 52, with the clubs suit
};
The reason your output from _val1 is 0 when entering a letter lies in the fact that you've declared _val1 as an short int. You should be using a char. Then you can assign and compare their ascii values.
char card;
int value;
scanf("%c", card);
if(card < 58 && card > 49)
value = card - 48;
else {
switch(card) {
case 'a': value = 1;
case '0': value = 10;
case 'j': value = 11;
case 'q': value = 12;
case 'k': value = 13;
default: printf("Must enter 0-9 (0 for 10 card), or a, j, q, k\n");
}
}
To read in "A", "2", "3", ... "10", "J",... "K", use fgetc() and strchr().
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
short GetCardRank(void) {
static const char rank[] = "A234567891JQK";
short val = -1;
int ch = fgetc(stdin);
while (isspace(ch)) ch = fgetc(stdin); // Skip leading white-space
char *p = strchr(rank, toupper(ch)); // Use toupper() to make case insensitive
if (ch != EOF && p != NULL && *p != '\0') {
short val = (short) (p - rank + 1);
if (val != 10) return val;
ch = fgetc(stdin);
if (ch == '0') return val;
val = 1; // Allow a lone '1' to act like an 'A'
}
ungetc(ch, stdin); // Put back unused char for next IO function
return val;
}
I'm trying to put it in an integer variable called "_val1". This work for any number from 0 to 10. I expected that if I typed a letter, _val1 would get the ASCII value of that character (wich I could use later for my pourposes). But instead _val1 geta value '0' and the letter is automatically passed to my next variable call (wich is _naipe1)
The problem is that the %d conversion specifier only recognizes strings of decimal digits (with an optional leading + or -) and will stop reading at the first non-digit character; if you type in something other than a digit, then the input operation will fail and that character will be left in the input stream.
Your best bet is to read your input as text, then convert it to a numerical value manually, something like the following:
#include <ctype.h>
#include <stdlib.h>
/**
* Reads a card's face value (2-10,J,Q,K,A) from standard input
* Returns 0 on error
*/
short get_card_value( void )
{
char buf[4]; // large enough to hold a 2-digit string plus newline plus 0 terminator
short val = 0;
if ( fgets( buf, sizeof buf, stdin ) != NULL )
{
char *chk;
short tmp = (short) strtol( buf, &chk, 0 );
if ( isspace( *chk ) || *chk == 0 )
{
if ( tmp >= 2 && tmp <= 10 )
val = tmp;
}
else
{
switch( tolower( *chk ) )
{
case 'j': val = 11; break;
case 'q': val = 12; break;
case 'k': val = 13; break;
case 'a': val = 11; break;
default: break;
}
}
}
// else read error
return val;
}
You'd call this as
val1 = get_card_value();
if ( val1 == 0 )
// error on input
This code doesn't do any length checking on input, so if you enter a card value of 1234567890, that won't be handled gracefully.
Don't use leading underscores in your variable names; names with leading underscores are reserved for the implementation.
I'm obviously new to the forums and need some help. I'm writing a program that shows the number of vowels, words, and palindromes within a sentence. I'm at the end of my rope and am completely lost.
I'm using C and I'm trying to loop through the words within an input and then determine how many palindromes are in the sentence, which are then stored within a counter and printed later within the main method, but I require assistance on creating said loop in order properly store the values in the counter.
Here is what I have so far(I'm specifically looking at int is_palindrome(char my_sen[]))
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SENTENCE 256
int main(void){
char my_sen[SENTENCE],*s; //String that containts at most 256 as well as a pointer
int words = 1, count = 0, pal_count= 0; //Integer variables being defined
int i,vowel = 0, length; //More definitions
printf("Enter a sentence: ");//Input sentence
gets(my_sen);//Receives and processes input
length = strlen(my_sen); //Stores the length of the input within length
for(i=0;my_sen[i] != '\0'; i++){
if(my_sen[i]=='a' || my_sen[i]=='e' || my_sen[i]=='i' || my_sen[i]=='o' || my_sen[i]=='u' || //Loop that states if the input contains any of the following
my_sen[i]=='A' || my_sen[i]=='E' || my_sen[i]=='I' || my_sen[i]=='O' || my_sen[i]=='U') //characters(in this case, vowels), then it shall be
{ //stored to be later printed
vowel++;
}
if(my_sen[i]==' ' || my_sen[i]=='!' || my_sen[i]=='.' || my_sen[i]==',' || my_sen[i]==';' || //Similar to the vowel loop, but this time
my_sen[i]=='?') //if the following characters are scanned within the input
{ //then the length of the characters within the input is
length--; //subtracted
}
}
for(s = my_sen; *s != '\0'; s++){ //Loop that stores the number of words typed after
if(*s == ' '){ //each following space
count++;
}
}
printf("The sentence entered is %u characters long.\n", length); //Simply prints the number of characters within the input
printf("Number of words in the sentence: %d\n", count + 1); // Adding 1 to the count to keep track of the last word
printf("Average length of a word in the input: %d\n", length/count);//Prints the average length of words in the input
printf("Total Number of Vowels: %d\n", vowel);//Prints the number of vowels in the input
printf("Average number of vowels: %d\n", vowel/count);//Prints the average number of vowels within the input
printf("Number of words that contain at least 3 vowels: %d\n",vowel_count(my_sen));//Prints number of words that contain at least 3 vowels
printf("Number of words that are palindomes: %d\n", is_palindrome(my_sen));
return 0;
}
int vowel_count(char my_sen[])
{
int wcount = 0;
int vcount = 0;
int i = 0;
int ch;
while ((ch = my_sen[i++]) != '\0')
{
if (isspace(ch) || !isalpha(ch))
{
wcount += vcount >= 3;
vcount = 0;
continue;
if (strchr("aeiouAEIOU", ch) != NULL)
{
++vcount;
}
}
wcount += vcount >= 3; // add 1 to wcount if vcount >= 3
return wcount;
}
int is_palindrome(char my_sen[]){
int begin, middle, end, length = 0, result = 0, pal = 0; //variables representing the string length, beginning, middle, and end of string
while ( my_sen[length] != '\0' ) //loop to define and initialize variables
length++;
end = length - 1; //end is the end of the length
middle = length/2;//middle is half the length
for( begin = 0 ; begin < middle ; begin++ )
{
if ( my_sen[begin] != my_sen[end] ) //if the beginning isn't equal to the end, then it's not a palindrome
{
result += pal;
pal = 0;
continue;
}
end--;
}
if( begin == middle ) //if the beginning is the same as the middle, its a palindrome
pal++;
result += pal;
return result;
}
Code below has been tested. Please correct or downvote as needed. Apologies if formatting for code is invalid.
I am going to give you an example that I just put together, off the top of my head.
It might not be exactly in line with your requirements, but it should get you started.
I will then explain how my code works, and give you some pointers to modify your code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i,vowels,pals,words;
vowels=words=pals=i=0;
long max=1024;
char *sentence=malloc(sizeof(char)*max);
printf("sentence:");
fgets(sentence,max,stdin);
if (sentence[strlen(sentence)-1]=='\n')
{
sentence[strlen(sentence)-1]='\0';
}
for (i=0;i<=strlen(sentence);i++)
{
char x;
x=sentence[i];
switch (x)
{
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
vowels+=1;
}
if ((x==' '||x=='\0') && i>0 && sentence[i-1]!=' ')
{
words+=1;
}
if (i>0 && (x=='\0'||x==' '))
{
char *lastchar,*pos,*word;
lastchar=sentence+i;
pos=(sentence+i)-1;
while (*pos!=' ' && pos!=sentence)
{
pos--;
if (*pos==' ')
{
pos++;
break;
}
}
word=strndup(pos,lastchar-pos);
if (isSameStringReversed(word)==0)
{
pals+=1;
}
free(word);
} //if on space for pal
} //for
printf("vowels:%d words:%d pals:%d\n",vowels,words,pals);
free(sentence);
}
int isSameStringReversed(char *word)
{
int i;
char destword[strlen(word)+1];
int j;
for (i=strlen(word)-1,j=0;i>=0;i--,j++)
{
destword[j]=word[i];
}
return strncmp(word,destword,strlen(word));
}
</pre>
Now some code descriptions.
//here are our includes. nothing special.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
//defines
int i,vowels,pals,words;
long max;
//set all to zero. (an empty sentence has no words.)
vowels=words=pals=i=0;
//max is the largest sentence you can enter
max=1024;
//allocate space for the sentence in memory.
char *sentence=malloc(sizeof(char)*max);
//prompt for sentence
printf("sentence:");
//read characters from stdin, making sure that only the first 1023 characters are read. (fgets removes the last character(s) if it is greater or equal to the provided limit. e.g. providing 1024 means that all characters past character 1023 are removed, and a \0 is appended to sentence.)
fgets(sentence,max,stdin);
//check last character of sentence for \n character, as some calls leave newlines attached.
if (sentence[strlen(sentence)-1]=='\n')
{
//set the last character to \0 if newline found. \0 terminates strings in c.
sentence[strlen(sentence)-1]='\0';
}
//move through every character in the sentence, including the terminating \0 character. This way, we make sure we pass every word and character provided, and we don't have to check at the end of loops for remaining characters.
for (i=0;i<=strlen(sentence);i++)
{
//defines for this for loop
char x;
//pull the current character from sentence. this way, we don't ahve to do sentence[i] each time.
x=sentence[i];
//switch is like an extended if statement with lots of possible branches.
switch (x)
{
//if x, the current character, equals 'a'
case 'a':
//if x, the current character, equals uppercase 'A'
case 'A':
//etc for the rest of the variables (excluding the sometimes cases of 'y')
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
//if x equals any of the above letters, then
//we add one to vowels, since our current letter is a vowel.
vowels+=1;
}
//if our current character is a space character, or a \0, meaning the end of our sentence string,
//and we are not on our first character, (because our sentence is not empty), and the character before our current character is not a space (because we don't count double spaces as words)
if ((x==' '||x=='\0') && i>0 && sentence[i-1]!=' ')
{
//it's a word, so add one to the words count
words+=1;
}
//again, if we are on a space or at the end of our string,
if (i>0 && (x=='\0'||x==' '))
{
//defines
char *lastchar,*pos,*word;
//lastchar is a pointer to where we are currently sitting (on the space or end character of the string)
lastchar=sentence+i;
//pos is a pointer to the previous character
//say we have
//A bunny likes racecar races.
//if we are on the space just after racecar, then lastchar points to the space, and pos points to the r in racecar
pos=(sentence+i)-1;
//while the character that pos points to isn't a space, and we aren't at the beginning of the string
while (*pos!=' ' && pos!=sentence)
{
//move the pointer pos back one character
pos--;
//if we're on a space, we've moved back before the previous word.
if (*pos==' ')
{
//we want to move pos to the first character of the preceding word.
pos++;
break;
}
}
//make a new copy of the current word, which we do by using strndup, analagus to (duplicate string with only n number of characters).
//we take the value of pos, and subtract it from lastchar, which gives us the length of the preceeding word.
//we used racecar as our example, so the space after racecar, minus the position of the r, gives us 7, which is the amount that strndup copys.
word=strndup(pos,lastchar-pos);
//if the function below returns 0
if (isSameStringReversed(word)==0)
{
//we've found a palindrome
pals+=1;
}
//free word, a.k.a. the chunk of memory we created for checking the last word as a palindrome.
free(word);
} //endif palindrome boundary check
} //endfor character in sentence loop
//print the character vowel and palindrome counts
printf("vowels:%d words:%d pals:%d\n",vowels,words,pals);
//free the sentence, as we're done with it.
free(sentence);
}
//function
//word is a pointer to char, or an array of characters. In this case word points to "word" defined above,
//or "racecar" from our example.
int isSameStringReversed(char *word)
{
//defines
//take the length of the provided word, and add a character to it for the \0, or ending character.
char destword[strlen(word)+1];
int i;
int j;
//set i to the number of the last character in word, and j to 0.
//move through the string, subtracting one from i and adding one to j.
for (i=strlen(word)-1,j=0;i>=0;i--,j++)
{
//move from right to left, assigning word to destword in reverse order.
//racecar would take the last r, assign it to the first slot in destword, the second to last a to the second position, and so on.
destword[j]=word[i];
//continue the loop
}
//see if the two reversed strings match, with strncmp.
return strncmp(word,destword,strlen(word));
}
Explanations.
Notice that we used pointers everywhere except in the last function.
This is for good reason.
Pointers are flexible, understandable, and allow mathmatical operations.
They are also quick and lend to code readability.
If you notice, we use these mathmatical properties when we subtract pos from lastchar.
This isn't as important when using chars, but when you get into other datatypes, moving from element to element will be quite helpful.
Also, if you notice, all of my variables are clearly labeled.
Again, this will help with code readability and maintainability.
If the code above was not enough, feel free to let me know, and I will do my best to elaborate further on a specific issue.