Finding the index of a char in C using pointers - c

I'm having difficulties with a program I've been instructed to write. The program should search a word for the first vowel that appears, it then should print out the index of that vowel. If there are no vowel's, it should return -1.
This is my code so far:
int firstVowel(char* string){
//Variable for case with no vowels
int notInString = -1;
int length = strlen(string);
int i;
for(i = 0; i <= length; i+=1){
if(*string == 'a' || *string == 'e' || *string == 'i' ||
*string == 'o' || *string == 'u'){
return i;
}
else if(*string != 'a' || *string != 'e' || *string != 'i' || *string != 'o' ||
*string != 'u') {
return notInString;
}
}
}
When I run it with the input "abced" it returns 0 correctly. However, when I run it as fsed it returns -1 incorrectly.

You loop does not increment string and always returns after doing the first comparison, you want
int firstVowel(char* string) {
//Variable for case with no vowels
int notInString = -1;
int length = strlen(string);
int i;
for (i = 0; i <= length; i += 1) {
if (*string == 'a' || *string == 'e' || *string == 'i' ||
*string == 'o' || *string == 'u') {
return i;
} else {
string++;
}
}
return notInString;
}
This will search the entire array, returning the index of the first vowel it sees. It cannot return notInString until it has processed the entire string.

Related

Is there a way to delete a repeated character in a string using pointers in C?

My teacher requested a C function with this characteristics:
int removeVowels(char *s)
{
...
}
Input (Example) : "Estaa e umaa string coom duuuplicadoos"
Output : "Esta e uma string com duplicados"
The program should also output the numbers of letters removed.
All help would be appreciated.
Attempt:
int aux[1000];
int i = 0;
int retiraVogaisRep (char *s){
if (*s == '\0'){
return 0;
}
else{
if ((*s == 'A' || *s == 'E' || *s == 'I' || *s == 'O' || *s == 'U' || *s == 'a' || *s == 'e' || *s == 'i' || *s == 'o' || *s == 'u') && aux[i] != *s){
i++;
aux[i] = *s;
return retiraVogaisRep(s + 1);
}
else if ((*s == 'A' || *s == 'E' || *s == 'I' || *s == 'O' || *s == 'U' || *s == 'a' || *s == 'e' || *s == 'i' || *s == 'o' || *s == 'u') && aux[i] == *s){
i++;
aux[i] = *s;
*s = '';
return 1 + retiraVogaisRep(s + 1);
}
else{
return retiraVogaisRep(s + 1);
}
}
}
Attemp 2 (works but is there a easier way?) :
char final[1000];
char aux[1000];
int k = 0;
int i = 0;
int y = 0;
int retiraVogaisRep (char *s){
if (*s == '\0'){
while (k < y){
*(s - i) = final[k];
i--;
k++;
}
while (i >= 0){
*(s - i) = final[1000];
i--;
}
return 0;
}
else{
if ((*s == 'A' || *s == 'E' || *s == 'I' || *s == 'O' || *s == 'U' || *s == 'a' || *s == 'e' || *s == 'i' || *s == 'o' || *s == 'u') && aux[i] != *s){
i++;
aux[i] = *s;
final[y] = *s;
y++;
return retiraVogaisRep(s + 1);
}
else if ((*s == 'A' || *s == 'E' || *s == 'I' || *s == 'O' || *s == 'U' || *s == 'a' || *s == 'e' || *s == 'i' || *s == 'o' || *s == 'u') && aux[i] == *s){
i++;
aux[i] = *s;
return 1 + retiraVogaisRep(s + 1);
}
else{
final[y] = *s;
y++;
i++;
return retiraVogaisRep(s + 1);
}
}
}
This is a possible solution:
int removeVowels(char *s)
{
char *src = s;
char *dst = s;
while (*dst != '\0')
{
switch (* ++ src)
{
case 'A': case 'a':
case 'E': case 'e':
case 'I': case 'i':
case 'O': case 'o':
case 'U': case 'u':
if (* src != * dst)
* ++ dst = * src;
break;
default:
* ++ dst = * src;
break;
}
}
return src - dst;
}
First, the first character of the input string is the first character of output -- even if it's a vowel, it certainly is not a duplicate yet!
Then we enter a loop. The loop will work until the resulting string is terminated -- so while the character pointed at by the dst pointer is not zero, do iterate.
In every iteration we advance the src pointer and fetch a character pointed at. If it is a vowel we test if it's same as the most recently accepted output character (pointed at by dst); if so, we skip it, otherwise we append it to the result (by advancing the dst pointer and copying the character.
OTOH if the character is not a vowel, we copy it with no more conditions.
Once src pointer reaches the end of the string, the zero byte (a string terminator) is copied, and the loop exits.
At this moment, src points at the end of the source string and dst points at the end of the resulting string (which starts at the same point where the source string was starting, but it can be shorter now than the source).
So the difference of pointers src - dst is exactly the number of characters (vowels) skipped.
Try it here: https://onlinegdb.com/ryNzvTUVu
int isVowel(char ch)
{
if (ch >= 'A' && ch <= 'Z')
ch = (ch - 'A') + 'a';
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u');
}
int removeVowels(char *s)
{
int removed = 0;
if (s)
{
while (*s != '\0')
{
char ch = *s++;
if (isVowel(ch) && (*s == ch))
{
char *src = s, *dst = s;
do {
++src;
++removed;
}
while (*src == ch);
while (*src != '\0') {
*dst++ = *src++;
}
*dst = '\0';
}
}
}
return removed;
}
Demo
The other answers (two at the time of posting this) both give excellent (and efficient) solutions. Here, I offer another – less efficient but, hopefully, simpler and clearer.
First, let's define a function to test if a character is a vowel. Whenever you end up doing something more than once in a program, or if (even though you only do it once) you get long, 'ugly' lines or blocks of code, then you should consider moving that code into a function. You never know when you might need it again and, if you do, then it's already a done deed.
int isVowel(char c)
{
static char* vowels = "AEIOUaeiou"; // Making this "static" cause initialization only once
// static char* vowels = "AEIOUWYaeiouwy"; // Alternative for Welsh people!
for (char* cp = vowels; *cp; ++cp) {
if (c == *cp) return 1; // Matched a vowel, we can return without further loops
}
return 0; // Loop finished without matching, so it's not a vowel
}
Next, the function to remove duplicate vowels. This version just runs a simple loop through the given string, copying the 'source' to the 'destination' if the removal condition isn't met. We can safely do this by overwriting the string itself, as we will never need to 'go back' and look at characters in that original string more than once.
Note, also, that we will be overwriting characters with themselves, until we have found at least one character to skip – but this is a case of sacrificing a modicum of efficiency to maintain code simplicity. There are other places where adding some complexity to the code would also make it more efficient … I'll leave these as the proverbial "exercise for the reader!"
int removeVowels(char* string)
{
int skipped = 0; // Keep a running tally of how many we removed
char *src = string, *dst = string; // Use 2 pointers (source and destination): both start at beginning of string
char previous = '?'; // Keep track of last letter - start with an 'impossible' value
while (*src) // Loop until we find the nul terminator
{
if (!isVowel(*src) || *src != previous) { // Not a vowel or not same as last ...
*dst++ = *src; // ... so copy it to 'new' string and increment destination pointer
}
else { // Otherwise, all we do is incrememnt our removals count.
++skipped;
}
previous = *src++; // Change our saved last letter, then increment the source pointer
}
*dst = '\0'; // Finally, add the nul-terminator to our modified string
return skipped;
}
Finally, a short main program to test the above code with the example input provided:
#include <stdio.h>
int main()
{
char test[] = "Estaa e umaa string coom duuuplicadoos";
int lost = removeVowels(test);
printf("Result: %s (removed %d vowels)\n", test, lost);
return 0;
}

Program keeps printing a zero byte?

I am trying to create a program that removes the vowels from a sentence. However, my program keeps failing because it keeps printing zero byte in the string. Would anyone be able to show me where I am going wrong?
#include <stdio.h>
int remove_all_vowels(int character);
int main(void) {
int character = getchar();
while (character != EOF && character != '\0') {
int new_character = remove_all_vowels(character);
putchar(new_character);
character = getchar();
}
return 0;
}
int remove_all_vowels(int character) {
if (character == 'a' || character == 'e' || character == 'i' || character
== 'o' || character == 'u') {
return 0;
} else {
return character;
}
}
Your issue (outputting null characters) comes from the fact that you unconditionally putchar(3) the result of remove_all_vowels, which returns 0 (null character) when given character is a vowel.
To replace vowels with spaces:
You can simply change return 0; in remove_all_vowels to return ' ';
To completely remove vowels:
I would suggest having a function just to help you check against vowels rather than having it act like a transformation over a char, which is really pythonest.
Example of code:
int is_vowel(int character) {
return (
character == 'a' || character == 'e' || character == 'i'
|| character == 'o' || character == 'u'
);
}
// Then, in your main...
...
if (!is_vowel(character))
putchar(character);
your program works fine here
https://www.onlinegdb.com/online_c_compiler
Can give a screenshot whats the problem of your compiler?
#include <stdio.h>
#include <string.h>
int check_vowel(char);
int main()
{
char s[100], t[100];
int c, d = 0;
printf("Enter a string to delete vowels\n");
gets(s);
for(c = 0; s[c] != '\0'; c++) {
if(check_vowel(s[c]) == 0) { // If not a vowel
t[d] = s[c];
d++;
}
}
t[d] = '\0';
strcpy(s, t); // We are changing initial string. This is optional.
printf("String after deleting vowels: %s\n", s);
return 0;
}
int check_vowel(char ch)
{
if (ch == 'a' || ch == 'A' || ch == 'e' || ch == 'E' || ch == 'i' || ch == 'I' || ch =='o' || ch=='O' || ch == 'u' || ch == 'U')
return 1;
else
return 0;
}

Test if the input is integer or symbol in fgets in C

I am constructing a program that takes string input from the keyboard then shows the number of consonants as an output. I have managed to do it in a ridiculous way in the function count_consonants. I tested using if statement whether each character in the input is a number or symbol to ignore them during calculations. I originally wanted to check if the string is not a string using fgets but I don't know how. That's not an effective way, so any ideas for this?
#include <stdio.h>
#include <string.h>
//function to calculate the consonants
int count_consonants(char str[]) {
int idx;
for (idx = 0; idx < 100; ++idx) {
if (str[idx] == '\0') {
break;
}
}
int vowl = 0;
for (int i = 0; i < idx; ++i) { //loop to check if the characters are vowels or not
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' || str[i] == ' ') {
vowl += 1;
}
// numbers and symbols are counted here as vowels because if not,
// the compiler will count them the other way around
if (str[i] == '1' || str[i] == '2' || str[i] == '3' || str[i] == '4'
|| str[i] == '5' || str[i] == '6' || str[i] == '7' || str[i] == '8'
|| str[i] == '9') {
vowl += 1;
}
if (str[i] == ':' || str[i] == ',' || str[i] == '.' || str[i] == '$'
|| str[i] == '%' || str[i] == '^' || str[i] == '&' || str[i] == '*'
|| str[i] == '#' || str[i] == '_' || str[i] == '!') {
vowl += 1;
}
}
int cons = idx - vowl; // consonants = whole length of text - vowels
return cons - 1;
}
int main(int argc, char const *argv[]) {
char string[100];
char store[100][100];
int i = 0;
while (string[0] != '\n') {
fgets(string, 100, stdin);
strcpy(store[i], string);
i++;
}
for (int j = 0; j < i - 1; ++j) {
/* code */
printf("Number of consonants=%d\n", count_consonants(store[j]));
}
return 0;
}
shows the number of consonants
A simply way to count consonants, use isalpha(), strchr()
#include <string.h>
#include <ctype.h>
int my_isavowel(char ch) {
const char *p = strchr("aeiouAEIOU", ch); // search for a match
return p && *p; // If p is not NULL, and does not point to \0
}
int count_consonants(const char str[]) {
int count = 0;
while (*str != '\0') { // while not at end of string ...
char ch = *str++; // Get character and advance
count += isalpha((unsigned char) ch) && !my_isvowel(ch);
}
return count;
}
If you look for number of consonants, simply best count consonants instead of other things
#include <stdio.h>
#include <string.h>
int main (int narg,char*args[]){
char cons[ ] = "ZRTPQSDFGHJKLMWXCVBN";
char sentence[ ] = "This is my sentence!";
int i=0;
int sum_cons = 0;
for (i = 0; i < strlen(sentence); ++i)
if (strchr(cons,strupr(sentence)[i])) sum_cons++;
printf ("#CONS>%i\n",sum_cons);
return 0;
}

C function to remove vowels in a string not working?

Here is my function to remove the vowels in a string;
char *removeVowels(char *inString) {
int count = 0; //to count the non vowel characters
for (int i = 0; inString[i]; i++)
if (inString[i] != 'a' || inString[i] != 'e' || inString[i] != 'u' || inString[i] != 'o' || inString[i] != 'i')
inString[count++] = inString[i]; //if character is not a vowel placed at count++
inString[count] = '\0';
return inString;
}
The problem is that it is returning the original string inputted. Any ideas?
There is a confusion between the || and && operators. You want to test that the character is different from 'a' AND different from 'e' etc.
Here is a modified version:
char *removeVowels(char *inString) {
int count = 0; // index for preserved characters
for (int i = 0; inString[i]; i++) {
if (inString[i] != 'a' && inString[i] != 'e' && inString[i] != 'i'
&& inString[i] != 'o' && inString[i] != 'u') {
inString[count++] = inString[i]; // copy the non-vowel character
}
}
inString[count] = '\0'; // set the null terminator.
return inString;
}
Note however that uppercase vowels are not removed by this function, and whether y should be considered a vowel remains to be decided.
As stated in another comment, you need to use && instead of || to make sure that the character does not match any vowels. It might be easier to create a new string and add non-vowels to that string as you go. Something like:
char *removeVowels(char *inString, int size){
char newString[size];
int count = 0;
for(int i = 0; i < size; i++){
if(inString[i] != 'a' && inString[i] != 'e' && inString[i] != 'i' && inString[i] != 'o' && inString[i] != 'u'){
newString[count] = inString[i];
count++;
}
}
newString[count] = '\0';
return newString;
}

Trying to randomly generate a string in order to get a conditional to execute

Seems that strings in C are my weak point, need your guys' help again. I should have included this in my first one, so I apologize about that.
So I have this function that I got working correctly, it fills a string with random chars from the set {r, e, s, e, t} and returns it:
char *inputString()
{
static char string[6];
const char *digits = "reset";
int i;
for (i = 0; i < 5; i++)
{
string[i] = digits[ rand() % 4 + 0 ];
}
return string;
}
So the char at string[5] is '\0', correct? And string[1] through string[4] are random combinations of the other characters (r, e, s, e, t).
Now, I have another function that calls this one. These purpose of it is trying to get the printf statement to execute:
other_fxn()
{
char *s;
while (1)
{
s = inputString();
if (s[0] == 'r'&& s[1] == 'e' && s[2] == 's' && s[3] == 'e' && s[4] == 's'
&& s[5] == '\0')
{
printf('worked!\n');
break;
}
}
}
main:
{
srand(time(NULL));
other_fxn();
}
It compiles fine but the loop runs forever, with the if statement never executing. Can somebody help me out why it won't execute. Thanks once again.
while (1)
{
s = inputString();
if (s[0] == 'r'&& s[1] == 'e' && s[2] == 's' && s[3] == 'e' && s[4] == 't'
&& s[5] == '\0')
{
printf('worked!\n');
break;
}
}
First of all, in your example you are looking for word "reses".
And you just don't change a string inside the loop. So you will get out of the loop only if random string is reset after the initial generation. I don't know why do you need this, but code above will get out of the loop. Maybe not so soon, but it will.
Also, what is this one:
string[i] = digits[ rand() % 4 + 0 ];
Why + 0? And why % 4, not % 5?
Better go with this:
char *inputString()
{
static char string[6];
const char *digits = "reset";
for (int i = 0; i < 5; i++)
{
string[i] = digits[ rand() % 5];
}
return string;
}
And try using debugger, it really helps.
You are only running the inputString function once, so you will only ever receive one string. This can be fixed by moving the function call to the while (1) loop:
while (1)
{
s = inputString();
if (s[0] == 'r'&& s[1] == 'e' && s[2] == 's' && s[3] == 'e' && s[4] == 's'
&& s[5] == '\0')
{
printf('worked!\n');
break;
}
}
Also, to make your code slightly cleaner, you can use C's strcmp function to compare the string, rather than checking each individual character:
#include <string.h>
while (1)
{
s = inputString();
if (strcmp(s, "reset") == 0)
{
printf('worked!\n');
break;
}
}
Adding on to what #Pavel said about your random character selection, to make it a bit more reusable, you can use sizeof instead of a hard-coded 5:
string[i] = digits[ rand() % (sizeof(string) - 1)]; // Also removed extraneous 0
I have two changes for you:
You can make sure string[5] is 0. (It should already be because it's static)
char *inputString()
{
static char string[6];
const char *digits = "reset";
int i;
for (i = 0; i < 5; i++)
{
string[i] = digits[ rand() % 4 + 0 ];
}
string[5] = '\0'; // null terminate your string.
return string;
}
you can avoid doing while(1) by just putting the condition inside the while conditional check. and then perform the print after the while loop.
other_fxn()
{
char *s = inputString();
while (s[0] != 'r' || s[1] != 'e' || s[2] != 's' || s[3] != 'e' || s[4] != 's' || s[5] != '\0')
{
s = inputString();
}
printf('worked!\n');
}

Resources