2017-01-26 12 views
1

2d配列を埋めるためにユーザー入力を使用しています。 1つのラインのユーザ入力番号及びIは、次いで、そうのような配列を埋めるために、ネストされたループを使用:Cでstdinパイプが空であることを確認します

//User inputs: "1 2 3 4 5" 

for(i = 0; i < r; i++){ 
    for(j = 0; j < c; j++){ 
      scanf("%d", &arr[i][j]); 
    } 
} 

6の余地がある場合、ユーザは5 int値を入力した場合しかし、問題は、それだけで別のを待ちます入力。不十分な数字がある場合は、どのように検出できますか?

私はこれを使って試してみましたが、それはうまくいきませんでした:あなたが実際にそれらを消費する前に、ストリームとテスト文字に先行PEEKを使用することができます

for(i = 0; i < r; i++){ 
    for(j = 0; j < c; j++){ 
     if (!feof(stdin)){ 
      scanf("%d", &arr[i][j]); 
     } 
     else{ 
      printf("insufficient datapoints\n"); 
     } 
    } 
} 
+0

(scanfの '場合)'パイプが近くないEOF' '戻りません。 – Stargateur

+0

@ccpghどうすればいいですか? –

+0

'fgets'と' strtok'を使用しますか? – BLUEPIXY

答えて

1

一つの方法は、一度に入力行を読み込むことfgets()代わりのscanf()を使用して伴うだろう下回っ

はラフなコード例を追加しました。その後、strtok()を使用して、入力行をトークンに分割し、strtol()を使用してトークンを数値に解析することができます。 scanf()と比較すると、構造化されていないユーザー入力を処理するのに、fgetsを使用するほうがずっと簡単です。

以下のコードはこれを行います。入力行に要素が多すぎる場合、要素が少なすぎる場合、または要素の1つが有効な数でない場合は、メッセージが出力され、行を再度入力する必要があります。

各行がユーザーによって入力されると、strtok()は、行をトークンに分割するために使用されます。トークン区切り文字のリストはdelims[]に格納されています。トークンはスペースやタブで区切ることができます。区切り文字自体はトークンの一部ではないため、\r\nを含めて、これらの文字が1行の最後のトークンに含まれないようにします。

トークンが見つかった場合は、できるだけstrtol()を使用して整数に変換します。 strtol()への呼び出しの後、ポインタtailは、トークン内の数字の一部ではない最初の文字を指します。 tailNULターミネータを指している場合は、文字列全体が数値として解析されます。そうでない場合、入力は不良とみなされ、再度入力されなければなりません。

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

#define BUF_SIZE 1000 

int main(void) 
{ 
    size_t r = 3; 
    size_t c = 5; 
    size_t i, j; 
    char buffer[BUF_SIZE]; 
    char *token; 
    char *tail; 
    const char delims[] = " \t\r\n"; 
    int arr[r][c]; 
    int temp_val; 

    printf("Enter rows of %zu data elements:\n", c); 

    for(i = 0; i < r; i++){ 
     j = 0; 

     if (fgets(buffer, BUF_SIZE, stdin) == NULL) { 
      perror("Error in fgets()"); 
      exit(EXIT_FAILURE); 
     } 

     token = strtok(buffer, delims); 
     while (token != NULL) { 
      temp_val = strtol(token, &tail, 10); 
      if (*tail == '\0') { 
       arr[i][j] = temp_val; 
       ++j; 
      } else {    // token not a valid number 
       j = 0; 
       break; 
      } 

      if (j > c) {   // too many input values 
       break; 
      } 

      token = strtok(NULL, delims); 
     } 

     if (j != c) { 
      printf("insufficient datapoints\n"); 
      --i;     // enter row again 
     } 
    } 

    for (i = 0; i < r; i++) { 
     for (j = 0; j < c; j++) { 
      printf("%5d", arr[i][j]); 
     } 
     putchar('\n'); 
    } 

    return 0; 
} 

サンプルの相互作用:

Enter rows of 5 data elements: 
1 2 3 4 
insufficient datapoints 
1 2 3 4 5 6 
insufficient datapoints 
1 x 2 3 4 
insufficient datapoints 
1 2 3 4 x 
insufficient datapoints 
1 2 3 4 5 x 
insufficient datapoints 
1 2x 3 4 5 
insufficient datapoints 
1 2 3 4 5 
2 3 4 5 6 
3 4 5 6 7 
    1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
1

。 (まあ、cで並べ替え)。

これを使用して、空白を無視できます(これを行う必要があります)。

また、この覗き見値を使用して、不十分な文字が入力されたことを示すこともできます。

実際の読み取り(scanf)の前にピークを行う必要があります。あなたの目標を達成するために

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

int r=3; 
int c=2; 

int arr[100][100]; // FIX magic 

int main(int argc, char** argv[]) { 

    for(int i=0; i<r; i++) { 
    for(int j=0; j<c; j++) { 

     if (feof(stdin)) { 
     // error check and error/normal exit etc. 
     printf("eof\n"); 
     } 

     char c=getchar(); 

     if (c=='\n') { 
     // error check and error/normal exit here 
     printf("newline\n"); 

     } else if (isspace(c)) { 
     // advance and remove them - watch for end of stream when winding 
     printf("advance and discard whiitespace\n"); 

     } else { // add check for isdigit 
     // push back 
     ungetc(c, stdin); 
     printf("ungetc\n"); 
     } 

     scanf("%d", &arr[i][j]); 
     printf("got %d\n", arr[i][j]); 
    }  
    } 

    return 0; 
} 
関連する問題