You are not far off. You can just loop over the strings without calling strlen()
, for example iterating with for (int i = 0; string[i]; i++)
which will increment i
until it points to the nul-terminating character at the end of string
which is ASCII '\0'
and has the value of plain-old 0
. The loop in str2lower()
(below) does the exact same thing except it iterates with a pointer instead of an index.
Your logic in modifyString()
looks fine, but you should not cast (char)
when incrementing the values. There is no need. You can simplify your logic by letting strchr()
check if the current char is one of the characters in vowles
with if (strchr (vowels, string[i]))
eliminating the j
loop altogether.
It's unclear where strlwr(str);
is defined, but you can write a simple string to lower easy enough.
Also in my comment, you never, ever, ever use gets()
or use scanf()
with "%s"
without using the field-width modifier (e.g. "%99s"
) to prevent a string longer than your array from writing beyond the end of your array creating a buffer-overrun.
If you put that together, you can do something like:
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
/** convert string to lowercase.
* returns string with all chars converted to lowercase.
*/
char *str2lower (char *str)
{
if (!str || !*str) /* check string not NULL or empty */
return NULL;
char *p = str; /* user pointer enabling return of str */
for (; *p; p++) { /* loop over each char */
if ('A' <= *p && *p <= 'Z') /* if upper case */
*p ^= ('A' ^ 'a'); /* make lower case */
}
return str; /* return modified string */
}
/* modify vowels +1 and consonants -1 */
void modifystr (const char *vowels, char *string)
{
for (int i = 0; string[i]; i++) { /* loop over each char */
if (strchr (vowels, string[i])) { /* is char in vowels? */
string[i] += 1; /* if so, increment */
}
else if ('a' <= string[i] && string[i] <= 'z') {
string[i] -= 1; /* decrement */
}
}
}
int main (void) {
const char *vowels = "aeiou";
char str[MAXC];
fputs ("enter a string : ", stdout);
if (!fgets (str, MAXC, stdin)) {
puts ("(user canceled input)");
return 0;
}
modifystr (vowels, str2lower(str));
printf ("modified string: %s\n", str);
}
Example Use/Output
$ ./bin/modifystr
enter a string : My DOG has fLEAS and My Cat has nONE!
modified string: lx cpf gbr ekfbr bmc lx bbs gbr mpmf!
Look things over and let me know if you have questions.
Eliminating strchr()
and Using a Loop
You can replace strchr(vowels, string[i])
by adding back your j
loop and looping over each vowel. You need to keep a flag variable (like found
and if a vowel is found, set found = 1
. You want to break;
the loop as soon as a vowel is found.
After the loop you will test if (!found && 'a' <= string[i] && string[i] <= 'z')
to know you need to update a consonant value.
Putting it together, you could rewrite modifystr()
as:
/* modify vowels +1 and consonants -1 */
void modifystr (const char *vowels, char *string)
{
for (int i = 0; string[i]; i++) { /* loop over each char */
int found = 0; /* flag tells if vowel found */
for (int j = 0; vowels[j]; j++) { /* loop over each vowel */
if (vowels[j] == string[i]) { /* if string[i] matches */
string[i] += 1; /* increment string[i] */
found = 1; /* set found flag true */
break; /* break vowel loop */
}
}
/* after loop, if vowel !found and [a-z] */
if (!found && 'a' <= string[i] && string[i] <= 'z') {
string[i] -= 1; /* decrement consonant */
}
}
}
It does the same thing, without strchr()
.