I am trying to write a function that changes all lowercase letters of a string to uppercase. Here is my code:
/**
* string_toupper - This function will replace all lowercase letters in
* the string pointed by str to uppercase
* @str: The string that will be checked for lowercase letters
*
* Return: The resulting string str, where all the letters are uppercase
*/
char *string_toupper(char *str)
{
int i;
for (i = 0; *str != '\0'; i )
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
}
return (str);
}
And I tried it using:
#include <stdio.h>
int main(void)
{
char str[] = "Hello World!\n";
char *ptr;
ptr = string_toupper(str);
printf("%s\n", ptr);
printf("%s\n", str);
return (0);
}
But I get the following output:
Segmentation fault(core dumped)
My approach --> I will check the string if it has a lowercase letter. Then I will subtract 32 from the character if it matches to a lowercase character. I did this to make the character to uppercase, by subtracting 32 I am able to get the uppercase letter of the corresponding lowercase character I have found in the string.
But I am getting a Segmentation fault error, why is it happening?
CodePudding user response:
change the for loop condition to for (i = 0; str[i] != '\0'; i )
since it should check every index.
char *string_toupper(char *str)
{
int i;
for (i = 0; str[i] != '\0'; i )
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] =(int)str[i] - 32;
}
return (str);
}
CodePudding user response:
By request, this is offered for education and debate.
Some workplaces or institutes insist on a particular style wrt curly braces, etc. I freelance...
Notice that the function name is not reproduced in a comment block. Bad habit that leads to satisfying supervisors with copy/paste of comment blocks that are WRONG and certainly misleading. Better to let the code explain itself by using conventional idioms and standard libraries.
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
char *string_toupper( char *str ) {
// Uppercase all lowercase letters found in 'str'.
// Return str after processing.
assert( str != NULL ); // Trust no-one, especially yourself
// Alternative for():: for( int i = 0; str[ i ]; i )
for( int i = 0; str[ i ] != '\0'; i )
str[ i ] = (char)toupper( str[ i ] ); // note casting.
return str;
}
int main( void ) {
char str[] = "Hello World!";
// No further use? Don't store return value; just use it.
printf( "%s\n", string_toupper( str ) );
printf( "%s\n", str );
return 0;
}
CodePudding user response:
OP's key problem is well explained by Prithvish: wrong loop test.
// for (i = 0; *str != '\0'; i )
for (i = 0; str[i] != '\0'; i )
To help OP with How can I make my code work on every environment?, some thoughts for later consideration.
Future names
"Function names that begin with str
, mem
, or wcs
and a lowercase letter may be added to the declarations in the <string.h>
header." C17dr § 7.31.13
So do not code function names that begin str<lowercase>
to avoid future collisions.
Indexing type
int i;
is too narrow a type for long lines. Use size_t
for array indexing.
Alternatively simply increment the pointer.
Test case with classification is...()
functions
str[i] >= 'a' && str[i] <= 'z'
is incorrect on systems where [a...z] are not continuous. (Uncommon these days - example EBCDIC).
Simplify with topper()
To convert any character to its uppercase equivalent:
str[i] = toupper(str[i]);
Use unsigned access
is..(x)
and toupper(x)
functions need unsigned char
character values (or EOF
) for x
.
On soon to be obsolete rare non-2's complement systems, character string should be accessed as unsigned char
to avoid stopping on -0.
Putting this together:
#include <ctype.h>
char *str_toupper(char *str) {
unsigned char *ustr = (unsigned char *) str;
while (*ustr) {
*ustr = toupper(*ustr);
ustr ;
}
return str;
}