Find vowels in a string - c

Given below is my code for finding vowels in a given string:
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
int i, str_length;
//scanf("%[^\n]%*c", &str[100]);
fgets(str, sizeof(str), stdin);
str_length = strlen(str);
for (i = 0; i < str_length; i++) {
if (str[i] == 'a' || str[i] == 'e' ||
str[i] == 'i' || str[i] == 'o' ||
str[i] == 'u' || str[i] == 'A' ||
str[i] == 'E' || str[i] == 'I' ||
str[i] == 'O' || str[i] == 'U')
{
printf("Vowels in the string are: %c \n", str[i]);
}
}
return 0;
}
I just wanna know, why scanf("%[^\n]%*c",&str[100]) is not working in my code?
cause I tried executing my program multiple times using scanf but it didn't worked.
And after using fgets I got the desired output.
So, can anyone help me to understand, where I am wrong!!

In the scanf function call, this &str[100] takes a pointer to str, makes it point to the element with the index 100 (which is past the end of the array), dereferences it and then takes the address of that (non-existing) element. This, most likely, leads to an attempt to an invalid write, which is probably caught by the operating system which terminates your program. In any case, the string is not written to the correct location.
Instead, you want the argument to point to the memory location of the first element of str, i.e.:
scanf("%[^\n]%*c", str);
That said, using fgets is better as it accepts an argument for the size which prevents buffer overflows. A size can also be given to scanf, but since it is part of the format specifier it cannot be a variable; only a hardcoded constant:
scanf("%99[^\n]%*c", str);
Note that this is for 99 elements, as there needs to be room for the null-terminator (\0) as well. See here for more info on scanf. But again, using fgets is less error prone and to be preferred.
Some additional advice:
The typical signature of the main function, using no parameters, is int main(void).
The scanf version fails if the input is a single newline character. Both versions fail on no input. It is always a good idea the check the return values of input (and output) functions.
Inside of the for-loop, you could create a copy of the current character converted to lowercase using the tolower function, and then perform only the lowercase comparisons. I.e.:
for (i = 0; i < str_length; i++) {
char ch = tolower(str[i]);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
printf("Vowels in the string are: %c \n", str[i]);
}
Another option is to replace the comparisons in the if-statement with a call to strchr, which makes the program a bit more generic and scalable (one string is more easily changed than multiple comparisons):
char ch = tolower(str[i]);
if (strchr("aeiou", ch) != NULL)
printf("Vowels in the string are: %c \n", str[i]);

Related

Only first char of user input used in array

I am writing some code for a nanokernel, which means I can't use the standard library, although I have implemented functions for printing strings and getting chars from the keyboard.
Right now I have the program set up to take chars from the keyboard and put them into an array. The string is then printed out. I expect the string printed out to look exactly like what was inputted by the user.
The issue is that it seems that the only char being put into the string is the first char inputted on the keyboard.
here is the relevant code for putting the chars into an array:
void stringin(char str[]) { // takes a string, puts it in str
int i = 0;
for (i = 0; str[i] != '\n' && str[i] != '\033';) {
str[i] = getch();
if (str[i] != '\n' && str[i] != '\033') {
i++;
}
calctime(1000000); // waits for a bit so that we don't flood the array
}
if (str[i] == '\n') newline(1);
str[i++] = '\0';
}
I have used both a printing function and a strcmp() implementation to test the contents of the string, so nothing seems to be going wrong with printing the string.
Based on the comments, str is passed to stringin with the buffer uninitialized.
Since the following loop terminates based on the value of str[i] before str[i] is actually initialized, the results are undefined.
for (i = 0; str[i] != '\n' && str[i] != '\033';) {
str[i] = getch();
....

Unexpected newline occuring with use of for loops, ternary operators and conditions

I understand that some functions automatically append newlines to their outputs, but I've encountered a scenario where a newline is not expected. I've tried to fix it and understand why it occurs in a multitude of ways, but to no avail. This is an output issue I haven't experienced before.
I am doing a very basic project from C Programming: A Modern Approach by K.N. King, Chapter 8, project 6: "B1FF filter", where certain characters get converted and printed as such. I used ternary operators combined with conditions to get the appropriate output. Here's the program:
/* C Programming: A Modern Approach
Chapter 8: Arrays, Project 5: B1FF filter
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char message[50];
int msg_len;
printf("Enter message: ");
fgets(message, 50, stdin);
msg_len = strlen(message);
printf("In B1FF-speak: ");
for (int i = 0; i < msg_len; i++)
{
message[i] = toupper(message[i]);
if (message[i] == 'A' || message[i] == 'B')
printf("%c", (message[i] == 'A') ? '4' : '8');
else if (message[i] == 'E' || message[i] == 'I')
printf("%c", (message[i] == 'E') ? '3' : '1');
else if (message[i] == 'O' || message[i] == 'S')
printf("%c", (message[i] == 'O') ? '0' : '5');
else
printf("%c", message[i]);
if (i == (msg_len - 1))
{
for (int j = 0; j < 10; j++)
printf("!");
printf("\n");
}
}
return 0;
}
The output isn't expected:
Enter message: C is rilly cool
In B1FF-speak: C 15 R1LLY C00L
!!!!!!!!!!
Why is there a newline between the modified string and the exclamation marks? I've clearly specified for the newline to occur after all text is printed, just before the loop terminates. I've tried alterations, such as printing a newline outside of the loop, not using a for loop for the exclamation marks etc., but it yields the same result. There doesn't seem to be an explicit reason for its occurrence.
fgets includes the newline in what it copies to the destination char buffer. Hence your character-by-character printing routine passes it unaltered.
Result #1 for fgets on Google: http://www.cplusplus.com/reference/cstdio/fgets/
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
Of course, as mentioned in the other answer, you can ignore this when printing, or null it out in advance.
fgets() will save the newline character read to the buffer. If you don't want it, remove it.
Example:
fgets(message, 50, stdin);
/* remove newline character */
{
char* lf = strchr(message, '\n');
if (lf != NULL) *lf = '\0';
}
The meaning is:
fgets(message, 50, stdin); /* read one line from the standard input */
/* remove newline character */
{
char* lf /* declare a variable */
= strchr(message, '\n'); /* and initialize it with the pointer to the first '\n' in the string message */
if (lf != NULL) /* check if '\n' is found */
*lf = '\0'; /* if found, replace '\n' with '\0' and delete the newline character (and string after '\n', which won't usually present) */
}

Vowels not counting correctly

I am trying to write a C program to count the number of vowels, keystrokes, and alpha characters. The keystroke counter is working, but the vowel counter is always off by 1 vowel. The alpha counter is not working.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int keystrokes = 0; //Number of keystrokes.
int letters = 0; //Number of total letters.
int vowels = 0; //Number of vowels.
int i = 0;
char sentence[0]; //Chararacter array specified to users input.
while((sentence[i] = getchar()) != '\n')
{
if(sentence[i] == 'a' || sentence[i] == 'e' || sentence[i] == 'i' || sentence[i] == 'o' ||sentence[i] =='u'|| sentence[i] == 'A' || sentence[i] == 'E' || sentence[i] == 'I' || sentence[i] == 'O' ||sentence[i] == 'U' )
{
++keystrokes;
++letters;
++vowels;
}
else
{
if (isalpha(sentence[i]) == 1) // if character is true
{
++keystrokes;
++letters;
}
else
{
++keystrokes;
i++;
}
}
}
printf("SAMPLE OUTPUT, for EACH sentence above:\n");
printf("Keystrokes %d \n", keystrokes);
printf("Alpha Characters %d \n", letters);
printf("Vowels %d \n", vowels);
return 0;
}
You have a lot of issues here. By saying char sentence[0] you actually say that there is zero bytes of memory to store the input. Accessing sentence[i] will be "out of bounds" and overwrite other parts of memory, leading to undefined behavior.
To start, change char sentence[0] to char sentence[100]. Then look carefully where you increment your counters, i.e. what the if/else flow looks like in your program. To give an example: Currently, when you have a vowel, the check for isalpha() is not reached, nor is the i++.
Your problem is that you have undefined behaviour caused by memory corruption.
char sentence[0];
That declares a 0 character array. Just get rid of the array and the i index. That is, change char sentence[0] to be something like char current_char and then replace all instances of sentence[i] with current_char.
I agree with Alan AU about replacing sentence with get_char. I also changed the (isalpha(sentence[i]) == 1) to (isalpha(sentence[i])).
I admit that I'm still new to programming, but your code did not increment the letters properly until I made that change.

Exceptions in c programming language

I'm learning c language and I hit a wall, if you would like to help me I appreciate (here is the ex: "Write a program that reads characters from the standard input to end-of-file. For each character, have the program report whether it is a letter. If it is a letter, also report its numerical location in the alphabet and -1 otherwise." btw is not homework).The problem is with the \n i don't know how to make it an exception. I'm new around here please let me know if I omitted something. Thank you for your help.
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z')
{
order = ch - 'A' + 1;
printf(" %d \n", order);
}
if (ch >= 'a' && ch <= 'z')
{
order = ch - 'a' + 1;
printf(" %d \n", order);
}
if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
{
if (ch == '\n');
else if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
printf(" -1 \n");
}
}
system("pause");
}
You are talking about an "exception" which can be interpreted in other ways in programming.
I understand that you want that '\n' be "excepted" in the set of nonalphabetical characters, that is, that it doesn't generate the error value -1.
Since you are using console to run the program, a sequence of character is going to be read till ENTER key is pressed, which generates the character \n. So, I'm not pretty sure that the while() condition you used, that compares against EOF, it's a good decision of yours.
I would put there directly the comparisson against '\n'.
while ((ch = getchar()) != '\n')
To inform if ch is a letter or not, we could use string literals. The following use of string assignment would deserve more explanation, but I will omit it. It's valid with string literals:
char *info;
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
You are assuming an encoding where the letters are in contiguous increasing order (as in ASCII).
By assuming that, it's enough to work with uppercase or lowercase letters, since you are only interested in the position that the letter occupy in the alphabet. So, you can choose to work with uppercase, for example, in this way:
if (ch >= 'a' && ch <= 'z')
ch = (ch - 'a' + 'A');
The effect of that line of code is that ch is converted to uppercase, only if ch is a lowercase letter. Another kind of character is not affected.
As a consequence, from now on, you only have uppercase letters, or nonalphabetical characters.
Then it's easy to code the remaining part:
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; // It brings no. position of letter in alphabet
else
order = -1; // This is the erroneous case
A printf() at the end of the loop could bring all the information about the character:
printf(" %16s: %4d \n", info, order);
The resulting code is shorter in more clear:
#include <stdio.h>
int main(void) {
char ch;
int order;
char *info;
while ((ch = getchar()) != '\n') {
printf("%c",ch);
if (ch >= 'a' && ch <= 'z') /* Converting all to uppercase */
ch = (ch - 'a' + 'A');
if (ch >= 'A' && ch <= 'Z')
order = ch - 'A' + 1; /* Position of letter in alphabet */
else
order = -1; /* Not in alphabet */
if (order != -1)
info = "is a letter";
else
info = "is not a letter";
printf(" %16s: %4d \n", info, order);
}
}
If you need to end the input by comparing against EOF, then the type of ch has to be changed to int instead of char, so you can be sure that the EOF value (that is an int) is properly held in ch.
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\n'.
Finally, just for fun, I add my super-short version:
#include <stdio.h>
int main(void) {
int ch, order;
while ((ch = getchar()) != '\n') {
order = (ch>='a' && ch<='z')? ch-'a'+1:((ch>='A' && ch<='Z')? ch-'A'+1: -1);
printf("%c %8s a letter: %4d \n", ch, (order != -1)? "is":"is not", order);
}
}
The C language does not have exceptions. Exceptions were first introduced into programming in C++. You can do it manually in C using setjmp() and longjmp(), but it really isn't worth it.
The two most popular of doing error handling in C are:
Invalid return value. If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. This of course doesn't work for all situations. If all possible return values are valid, such as in a function which multiplies two numbers, you cannot use this method. This is what you want to do here - simply return -1.
Set some global error flag, and remember to check it later. Avoid this when possible. This method ends up resulting in code that looks similar to exception code, but has some serious problems. With exceptions, you must explicitly ignore them if you don't want to handle the error (by swallowing the exception). Otherwise, your program will crash and you can figure out what is wrong. With a global error flag, however, you must remember to check for them; and if you don't, your program will do the wrong thing and you will have no idea why.
First of all, you need to define what you mean by "exception"; do you want your program to actually throw an exception when it sees a newline, or do you simply want to handle a newline as a special case? C does not provide structured exception handling (you can kind-of sort-of fake it with with setjmp/longjmp and signal/raise, but it's messy and a pain in the ass).
Secondly, you will want to read up on the following library functions:
isalpha
tolower
as they will make this a lot simpler; your code basically becomes:
if ( isalpha( ch ) )
{
// this is an alphabetic character
int lc = tolower( ch ); // convert to lower case (no-op if ch is already lower case)
order = lc - 'a' + 1;
}
else
{
// this is a non-alphabetic character
order = -1;
}
As for handling the newline, do you want to just not count it at all, or treat it like any other non-alphabetic character? If the former, just skip past it:
// non-alphabetic character
if ( ch == '\n' )
continue; // immediately goes back to beginning of loop
order = -1;
If the latter, then you don't really have to do anything special.
If you really want to raise an honest-to-God exception when you see a newline, you can do something like the following (I honestly do not recommend it, though):
#include <setjmp.h>
...
jmp_buf try;
if ( setjmp( try ) == 0 ) // "try" block
{
while ( (ch = getchar() ) != EOF )
{
...
if ( ch == '\n' )
longjmp( try, 1 ); // "throw"
}
}
else
{
// "catch" block
}
I'm having hard time trying to understand why you even try to handle '\n' specifically.
You might be trying to implement something like this:
int main(void)
{
char ch;
int order;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
printf("%c", ch);
if (ch >= 'A' && ch <= 'Z') {
order = ch - 'A' + 1;
printf(" %d \n", order);
} else if (ch >= 'a' && ch <= 'z') {
order = ch - 'a' + 1;
printf(" %d \n", order);
} else if (ch == '\n') { } else {
printf(" -1 \n");
}
}
system("pause");
}
While this is a good solution, I would recommend rewriting it in a more optimal way:
int main(void)
{
char ch;
printf("Enter letters and it will tell you the location in the alphabet.\n");
while ((ch = getchar()) != EOF)
{
int order;
if (ch != '\n'){
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
order = ch & 11111B;
printf("Letter %d\n", order);
} else {
order = -1;
printf("Not letter: %d\n", order);
}
}
}
system("pause");
}
This way the program relies on specific way letters coded in ASCII

Only print words that start with a specified letter out of a string in C language

I need to write a function that will print words that start with specified letter inside a string.. my problem is that once i try to print a words, the function never stop.
Here is the code: (printWords is the functions, printWord is a helper)
#include <stdio.h>
#include <string.h>
typedef char string[50];
void printWord(int *index, string sentence)
{
while (sentence[*index] != ' ' || sentence[*index] != '\0')
{
printf("%c", sentence[*index]);
*index += 1;
}
}
void printWords(char letter, string sentence)
{
int i = 0, *iPtr = &i;
if (sentence[0] == letter || sentence[0] == letter + 32)
printWord(iPtr, sentence);
for (; sentence[i] != '\0'; i++)
if ((sentence[i] == ' ' && sentence[i+1] == letter) || (sentence[i] == ' ' && sentence[i+1] == letter + 32))
printWord(iPtr, sentence);
}
void main()
{
char ex1_letter;
int menu;
string ex1_sentence;
printf("\n\nPlease enter a string: ");
gets(ex1_sentence);
printf("\nPlease enter a letter: ");
scanf("%c", &ex1_letter);
printWords(ex1_letter, ex1_sentence);
}
The condition in the loop never seems to happen and i just don't know why..
Any help would be appreciated!
Your main error is using || insted of && in printWord. With || the condition will always be true since the character will always not be either space or the null character.
Some other points:
It's more portable for main to return an int (and have a return 0; at the end).
Use of gets is discouraged as it allows buffer overruns. fgets is more secure, but beware that it leaves the newline character at the end of the string.
Don't do things like letter + 32. Instead, use the functions in ctype.h. In this case, use tolower or toupper.
Instead of passing i as a pointer, just pass it as an int and return the changed value.
Don't use printf and scanf to print/scan a single character. Instead use putchar and getchar.
Use ++i instead of i += 1.
Your typedef just obscures things. If the declaration of (e.g.) printWords is void printWords(char letter, char *sentence) then a C programmer knows what's going on right away without having to know what string is. The typedef really adds nothing.
In your printWord method:
while (sentence[*index] != ' ' || sentence[*index] != '\0')
This conditions will always be true. Change it to &&: print as long it is not a space AND not the end of string, like this:
while (sentence[*index] != ' ' && sentence[*index] != '\0')

Resources