Currently, I'm trying to write a code that replaces the 1st, 3rd, 5th character, ...(odd numbers) in a string with the letter 'A'.
E.x: 'hello world' will be 'AeAlA AoAlD'.
But instead, I'm getting 'hAllA AArld' which is not the result what I wanted.
Can someone help me, please?
Edit: The problem is that I checked the ASCII table, the value of the letter 'e', 'o', 'w' in ASCII table is an odd number and the other letters are not. So my program is checking if the value of the letters is an odd number or not to replace with 'A' and not the 1st, 3rd, 5th character in the string.
Below is the code:
#include <stdio.h>
#include <string.h>
int main() {
char str1[100];
scanf("%[^\n]", str1);
for (int i=0; i<strlen(str1); i ) {
if (str1[i]%2==1) {
str1[i]='A';
}
}
printf("%s", str1);
}
CodePudding user response:
You have a few problems:
strlen
returns asize_t
type, so it's best fori
to match that typei
is uninitialized, and should begin at 0 because arrays in C are 0-based (first elements starts at position 0, not 1).str1[i]%2
is incorrect math.. you want to do modulo on the indexi
, not the actual character in the string.
This is a fixed up version:
for (size_t i=0; i<strlen(str1); i ) {
if (i%2==0) {
str1[i]='A';
}
}
printf("%s", str1);
Update
As recommended in the comments by @chux, it's more efficient to drop strlen
and instead check for the NULL character as the terminating condition in the loop. However, for dixie cup programs like this, I'm dubious much performance gains would be realized, and ultimately recommend using whatever code/method is the most clear to you:
Method 1
for (size_t i=0; str1[i]!='\0'; i ) {
// or simply str1[i]; since 0 will evaluate to false
if (i%2==0) {
str1[i]='A';
}
}
Furthermore, you could bypass the modulus entirely, and just advance i
by 2 each time in the loop, since it's the even array positions (odd character counts) that you want:
Method 2
for (size_t i=0; i<strlen(str1); i=i 2) {
str1[i]='A';
}
Going down the road of efficiency (and knowing that you won't change the length of the string in-loop), you could also
Method 3
size_t len = strlen(str1); // ensure strlen is only called once
for (size_t i=0; i<len; i=i 2) {
str1[i]='A';
}
or, bypassing strlen
entirely:
Method 4
// must have a string of length >= 2 for this to work
for (size_t i=0; str[i] && str[i 1]; i=i 2) {
str1[i]='A';
}
Update 2
After some experimenting on godbolt, @chux is right. Even with optimizations turned up, strlen
is called every time thru the loop for Method 2. It actually looks like to me that Method 3 is the most efficient. I'm no assembly expert, but this bypasses calling strlen
at all, and looks like this has the fewest instructions in the loop. I've created this playground here for anyone interested.