I am trying to use the following code to append a right parenthesis to the end of a string took from the user
int main( void )
{
char charArray[ 20 ];
fgets( charArray, 20, stdin );
charArray[ sizeof( charArray ) / sizeof( charArray[ 0 ] ) ] = ')';
printf( "%s", charArray );
}
but if I enter: 4+5 the output is just: 4+5 rather then: 4+5)
I tried even the following variant, just in case
int main( void )
{
char charArray[ 20 ];
int n;
fgets( charArray, 20, stdin );
n = sizeof( charArray ) / sizeof( charArray[ 0 ] );
charArray[ n ] = ')';
printf( "%s", charArray );
}
but it doesn't work. So I obviated the need for a sizeof by doing
int main( void )
{
char charArray[ 20 ];
int i = 0;
do{
scanf( "%c", &charArray[ i ] );
++i;
} while( charArray[ i - 1 ] != '\n' );
charArray[ i - 1 ] = ')';
printf( "%s", charArray );
}
However I could need sizeof in the future so I would like to know what I am doing wrong. Also the use of fgets and sizeof seems more direct and concise than that of scanf and do while with the mysterious [ i - 1 ] subscript. Just enlighten me about the sizeof approach please: what's wrong with my piece of code?
First, the size of char
is always 1
, it's defined in the specification.
Second, the size of an array is the size of the array itself, in "bytes".
That means
sizeof( charArray ) / sizeof( charArray[ 0 ] )
is equal to
20 / 1
which is equal to 20
.
That is, you will always write to the twenty-first element of the array, which is out of bounds and lead to undefined behavior.
If you want to append a character to the string either use strcat
to append the characters as a string (making sure you don't write out of bounds):
// Check to make sure there's space in the array, the -1 is for the terminator
if (strlen(charArray) < (sizeof charArray - 1))
{
strcat(charArray, ")");
}
Or use strlen
to get the position of the string null-terminator and overwrite it with your char (but remember to add a new null-terminator, as well as check so you don't go out of bounds):
// Get the index of the current null-terminator in the string
size_t terminator_index = strlen(charArray);
// Check to make sure there's space in the array, the -1 is for the terminator
if (terminator_index < (sizeof charArray - 1))
{
// Can append new character
charArray[terminator_index] = ')';
// Add terminator
charArray[terminator_index + 1] = '\0';
}
What you're doing wrong here is not knowing the difference between an array and a string. You have declared an array with size 20. That size will never change.
What you are looking for is the length of the string, and you get that with strlen(charArray)
.
A string is a sequence of printable characters terminated with the \0
character. The length of a string is the number of characters before the terminator.
This code will print 5, 20
:
char arr[20] = "Hello";
printf("%zu, %zu\n", strlen(arr), sizeof(arr));
Note that this will print 3
:
char arr[20] = "Hello";
printf("%zu\n", strlen(&arr[2]));
Also note that you can do things like this:
char arr[20] = "Hello\0World!\n";
printf("%zu, %zu\n",
strlen(&arr[0]), // Hello
strlen(arr[strlen(&arr[0]) + 1]) // World!\n
);
This will print 5, 7
. The second has a length of seven because the newline also counts. Also note that when you initialize an array, a '\0'
is always appended, unless the size of the array is to small. This will declare a string without terminator:
char no_terminator[5] = "Hello";
Avoid that. It could cause you a lot of problems.
So in your case, you could do like this:
fgets( charArray, 20, stdin );
// Standard way of removing newline from a string. It's a very useful
// trick since fgets saves the newline in the string.
charArray[strcspn(charArray, "\n")] = '\0';
size_t len = strlen(charArray);
charArray[len] = ')';
charArray[len+1] = '\0';
But be careful so that len+1
never exceeds 20. If it does, you're invoking undefined behavior, which can be a real mess to debug. Also, it is wise to check if fgets
returned NULL. If that's the case, you should handle the error.
If you handle this kind of input a lot, I could recommend this wrapper:
void my_readline(char *str, int n)
{
if(fgets(str, n, stdin) == NULL) {
perror("Error reading string");
exit(EXIT_FAILURE);
}
str[strcspn(charArray, "\n")] = '\0';
}
Of course, you can customize the error handling in whatever way you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With