Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
383 views
in Technique[技术] by (71.8m points)

c - Using while(str[n++]!='') for counting the length of a string

Please ignore the Japanese there.
I attempt to count the length of the string entered from stdin using the following code. But it didn't work expectedly:

#include <stdio.h>

int main(int argc, const char *argv[]) {
    char str[100];

    printf("文字列を入力してください:");  // Please enter a string:
    fgets(str,99,stdin);

    int n = 0;
    while (str[n++] != '');
    printf("文字列の長さは%dです
", n);  // The length of the string is %d

    return 0; 
}

For example, if I enter glacious, I'll get n=10, which I expected to be n=8.
I understand that n++ will increment n after str[n++] != '' gets evaluated, and is the default character appended to every string. But somehow this doesn't make sense to me. 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. Many thanks in advance!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

"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|
||?|...|?|
 0 1 2 3 4 5 6 7 8  9 10    99 

int n = 0;
while(str[n++] != '');

iterations:

    n at start                       n at finish
  • 1st: n==0, str[0] (g) != , n++, n==1
  • 2nd: n==1, str[1] (l) != , n++, n==2
  • 3rd: n==2, str[2] (a) != , n++, n==3
  • 4th: n==3, str[3] (c) != , n++, n==4
  • 5th: n==4, str[4] (i) != , n++, n==5
  • 6th: n==5, str[5] (o) != , n++, n==6
  • 7th: n==6, str[6] (u) != , n++, n==7
  • 8th: n==7, str[7] (s) != , n++, n==8
  • 9th: n==8, str[8] ( ) != , n++, n==9
  • 10th: n==9, str[9] () == , 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 and the final post-increment ( for ) 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 "//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, "
")] = 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++] != '');
printf("文字列の長さは%dです
", n);
return 0; 

With this one which will break the loop upon seeing (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 != '
') && (c != EOF))
{
    count++; //only increments when c meets criteria
    fputc(c, stdout);
    c = fgetc(stdin);
}
printf("

The length of the string is: %d
", count);
return 0; 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
...