I want to write a program that when I am on terminal and write prog.exe -u word
will transform word
to uppercase otherwise skip the process. but when I compile the code below, I get nothing on screen and I couldn't figure out why the error occurs.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char u[] = "-u";
void upper(const char *src, char *dest);
int main(int argc, char const *argv[]) {
if (argc < 3) {
printf("Input at least 3 argument!\n");
} else
if (!(strcmp(argv[1], u))) {
char *output;
upper(argv[2], output);
printf("%s\n", output);
} else {
printf("No option\n");
}
return 0;
}
void upper(const char *src, char *dest) {
while (*src) {
if (*src >= 97 && *src <= 122) {
*dest = *src - 32;
} else {
*dest = *src;
}
src ;
dest ;
}
*dest = *src;
}
CodePudding user response:
The pointer output
declared like
char * output;
is uninitialized and has an indeterminate value.
So using it in the function upper
invokes undefined behavior.
Instead of the pointer you should use a character array large enough to store the passed string to the function.
If the compiler supports variable length arrays then you can write
char output[ strlen( argv[2] ) 1 ];
And this if statement
else if( strcmp(argv[1],u) == 0 ){
will be more readable than this if statement
else if(!(strcmp(argv[1],u))){
Within the function it will be at least better to use character symbols 'a'
and 'z'
instead of the magic numbers 97
and 122
in the if statement
if(*src >= 97 && *src <= 122){
*dest = *src - 32;
}
Though it is even better to use standard function islower
and toupper
declared in the header <ctype.h>
.
The function can be declared and defined the following way
#include <ctype.h>
//...
char * upper( char *dest, const char *src )
{
char *result = dest;
do
{
if ( islower( ( unsigned char )*src ) )
{
*dest = toupper( ( unsigned char )*src );
}
else
{
*dest = *src;
}
} while ( *src );
return result;
}
CodePudding user response:
void upper(const char *src, char *dest) {
char *tmp = dest; // hold pointer
while(*src) {
*dest = (*src >= 97 && *src <= 122) ? *src - 32 : src;
src; dest;
}
*dest = '\0'; // end of string
dest = tmp;
}
CodePudding user response:
The program has undefined behavior because you attempt to store the converted string to an uninitialized pointer output
.
Note that using hard coded constants such as 97
, 122
and 32
is both confusing and non portable to non-ASCII environments. You should use the macros and functions from <ctype.h>
for readability and portability.
You could simply modify the argument string in place this way:
#include <ctype.h>
#include <stdio.h>
void upper(char *str);
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Input at least 3 arguments!\n");
} else
if (!(strcmp(argv[1], "-u"))) {
printf("%s\n", upper(argv[2]));
} else {
printf("No option\n");
}
return 0;
}
char *upper(char *str) {
for (char *p = str; *p; p ) {
*p = toupper((unsigned char)*p);
}
return str;
}