"I attempt to count the length of the string entered from stdin"..."I know I can make this work for my purpose by adding n-=2 at the end, but I really want to understand what's going on here. "
Documentation for fgets() includes the following:
"...reads a line from the specified stream and stores it into the string pointed to by str. It stops when either (n-1) characters are
read, the newline character is read, or the end-of-file is reached,
whichever comes first."
This call, without checking the return value of the function, and by passing an incorrect value for the length of the string, limits the potential of detecting errors, and introduces the possibility of undefined behavior. To address these issues, change this:
fgets(str,99,stdin);
To, for example this:
if( fgets (str, sizeof str, stdin) != NULL )
{
...
Dissecting the following: given user input value: "glacious"
, str
looks like this in memory:
|g|l|a|c|i|o|u|s|\n|\0|?|...|?|
0 1 2 3 4 5 6 7 8 9 10 99
int n = 0;
while(str[n++] != '\0');
iterations:
n at start n at finish
- 1st:
n==0
, str[0]
(g
) != \0
, n++
, n==1
- 2nd:
n==1
, str[1]
(l
) != \0
, n++
, n==2
- 3rd:
n==2
, str[2]
(a
) != \0
, n++
, n==3
- 4th:
n==3
, str[3]
(c
) != \0
, n++
, n==4
- 5th:
n==4
, str[4]
(i
) != \0
, n++
, n==5
- 6th:
n==5
, str[5]
(o
) != \0
, n++
, n==6
- 7th:
n==6
, str[6]
(u
) != \0
, n++
, n==7
- 8th:
n==7
, str[7]
(s
) != \0
, n++
, n==8
- 9th:
n==8
, str[8]
(\n
) != \0
, n++
, n==9
- 10th:
n==9
, str[9]
(\0
) == \0
, n++
, n==10
Clearly illustrates the state of all iterations, including the final post-increment of n
, bringing it's total to 10
for a user input assumed to be only 8
characters. The \n
and the final post-increment ( for \0) account for the additional value to
n`. In summary the problem is simply adjusting your expectations to account for all characters in the buffer, including the ones you do not see.
Of interest, counting value of n
does not equate to measuring the string length of str
, for which the idiomatic method ( strlen() ), will yield 9. Given the definition of a C string, the following shows varying results for each corresponding method of looking at str
, assuming initialization:
char str[100] = {0};
And str
contents are: "glacious\n"//null terminator is implied
//method to calculate n in discussion above
// //yields n == 10
int len = strlen(str); //yields n == 9
//after using strcspn()
str[strcspn(str, "\n")] = 0;
len = strlen(str); //yields n == 8
size_t size = sizeof str; //yields size == 100
As an aside, if goal is to count the number of entries, and if an alternative approach is okay, consider simplifying the method...
Replacing this section:
char str[100];
printf("文字列を入力してください:");
fgets(str,99,stdin);
int n = 0;
while(str[n++] != '\0');
printf("文字列の長さは%dです\n", n);
return 0;
With this one which will break the loop upon seeing \n
(newline character), or EOF
(-1
) (#define
in stdio.h
), resulting in a correct count of user inputs (minus newline):
int count = 0;
printf("Please enter a string:");
int c = fgetc(stdin);
while(( c != '\n') && (c != EOF))
{
count++; //only increments when c meets criteria
fputc(c, stdout);
c = fgetc(stdin);
}
printf("\n\nThe length of the string is: %d\n", count);
return 0;