You are using scanf on a char* without first allocating memory to it. This may lead to segmentation fault. In fact, the following code :
#include<stdio.h>
int main()
{
char* str;
scanf("%s", str);
printf("%s\n", str);
return 0;
}
does give segmentation fault sometimes. Instead you can use a char
array instead of a char*
if you want to avoid malloc
before scanf
. You can use fgets
instead of scanf
to prevent writing out of bounds or you can check with scanf
itself like this:
char s[100];
if(scanf("%99s",s) != 1) { /* error */ }
Also in your code, you have a \n
after %s
in the scanf
statement, that I have removed(assuming you didn't intend this behaviour) . You can see what that does here: Using "\n" in scanf() in C
Secondly, in allocating memory for t
, you are using sizeof(*s)
which is just sizeof(char)
which is defined to be 1
. Instead, you should be using strlen(s)+1
which will allocate one more byte than the length of s which should work fine. Also, checking if t==NULL
is also recommended.
Before calling toupper
the argument must be type-casted into an unsigned char
to avoid the risks of undefined behaviour if the char
type is signed on the platform. More on this can be found on this answer: https://stackoverflow.com/a/21805970/18639286 (Though the question was a C++ question, the answer actually quotes C standard specifications)
I have edited the above changes into your code to get the following:
int main (int argc,char* argv[])
{
char s[100];
if(scanf("%99s",s)!=1)
{
fprintf(stderr, "Invalid or missing input\n");
// scanf should have returned 1 if it successfully read 1 input
}
char *t = malloc(strlen(s) + 1); // to store the letters + '\0' at the end
if(t==NULL)
{
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
strcpy(t, s);
t[0] = toupper((unsigned char)t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
free(t);
return 0;
}
Some extra points:
You can also use fgets
instead of scanf
:
fgets(s, 100, stdin);
as fgets
does bound checking.
Also, fgets reads till end of line/file or till the buffer is full, so it will read past the spaces in input, But scanf
will stop at a space. Or as Ted Lyngmo pointed out in the comments, scanf
with %s
reads a word, while fgets
reads a line.
But, even if you intend to read only a word, you can use fgets
and then use sscanf
to read the first word from the string with which you used fgets
. Example:
char buffer[20];
char str[sizeof buffer]=""; //initialize with an empty string
if(fgets(buffer, sizeof buffer, stdin)==NULL)
{
fprintf(stderr, "Error reading input\n");
exit(1);
}
if(sscanf(buffer, "%s", str)!=1)
{
// if str was not read
fprintf(stderr, "String not read\n");
exit(1);
}
// DO stuff with str
Here, you don't need to use %19s
because we know the size of buffer
.