when I use while(scanf("%s",s)==1) to input strings word by word, the expected output seemed coincidental

104 views Asked by At
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
    char s[1001];
    char str[1001][1001];
    int j=0;
    while(scanf("%s",s)==1)
    {
        for (int i = 0; i < strlen(s); i++)
        {
            if(islower(s[i]))
            s[i]=toupper(s[i]);
            else if(isupper(s[i]))
            s[i]=tolower(s[i]);
            
        }
       
        strcpy(str[j],s);
        j++;
    }
    for (int x = j-1; x>=0; x--)
    {
        printf("%s ",str[x]);
    }
    
   
    return 0;
    
}

for this one, I need to ctrl+z twice and enter to get the answer; but for the one below, I just need an enter to get expected anser.

#include <stdio.h>
#include <string.h>
 
int main() {
    char s[100];
    int flag = 1; // 使用 1 表示第一个单词
    while (scanf("%s", s) == 1) {
        if (flag) {
            flag = 0;
            printf("%lu", strlen(s));
        } else {
            printf(",%lu", strlen(s));
        }
    }
    return 0;
}

I have no idea when I can use this kind of input way. And when it comes to word problem, I think it's easier than fgets, so I do not want to give it up.

2

There are 2 answers

1
xing On

%s discards leading whitespace and scans non-whitespace. It can't detect a newline.
One solution would be to use a . to signal the end of input. Use strchr to check for a ..
Another solution would be to use a specific string to signal the end of input. -end- for example. Use strcmp to check for the string. strcmp returns 0 when the comparison is an exact match.
There are other solutions.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define SIZE 50
#define FS(x) SFS(x)
#define SFS(x) #x

void swapcase ( char *input) {
    unsigned char *check = ( unsigned char *)input;
    while ( *check) { // not the terminating zero
        if ( isupper ( *check)) {
            *check = tolower ( *check);
        }
        else {
            *check = toupper ( *check);
        }
        ++check;
    }
}

int main ( void) {
    char word[SIZE + 1] = ""; //+1 for terminating zero
    char inputs[SIZE][SIZE + 1] = { ""};
    int count = 0;

    printf ( "enter words (end with a .)\n");
    while ( 1 == scanf ( "%"FS(SIZE)"s", word)) { // scan up to SIZE characters
        swapcase ( word);
        strcpy ( inputs[count], word);
        ++count;
        if ( count >= SIZE || strchr ( word, '.')) {
            break;
        }
    }
    for ( int each = 0; each < count; ++each) {
        printf ( "%s ", inputs[each]);
    }
    printf ( "\n");
}
0
Clifford On

The scanf() call will always return 1 (except on EOF signalled by ctrl-z in this case) because even an empty string is a string.

You might include a test for empty string:

while( scanf("%s", s) == 1 &&
       *s != 0 )

However in the first case, since you are iterating the string character by character in the loop, you may as well read the whole string character by character in a single loop thus:

for( int i = 0, ch = 0; 
     ch = getchar() && ch > 0 && ch != `\n` ;
     i++)
{
    s[i] = islower( ch ) ? toupper( ch ) :
                           tolower( ch ) ;
}
   
strcpy(str[j],s);
j++;

Noting that there is no need for a isupper() test after islower(), if the character is not alphabetic, tolower() has no effect.

Further, the s array is redundant, since you only copy it to str[j], you could write directly to str[j]:

for( int i = 0, ch = 0; 
     ch = getchar() && ch > 0 && ch != `\n` ;
     i++)
{
    str[j][i] = islower( ch ) ? toupper( ch ) :
                                tolower( ch ) ;
}
   
j++;