2017-10-18 15 views
-1

5文字を入力する代わりに、5文字を要求する代わりに、4文字しか入力できないのはなぜですか? なぜデフォルトで*a+0 = '\n'が保存されますか? 私もscanf("%d %c", &n &ch)を9行目で試しましたが、問題は同じでした。文字列へのポインタの配列

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

int main() 
    { 
     int n; 
     char ch; 
     printf("no of elements\n"); 
     scanf("%d ", &n); //line 9 
     //asking for number of pointer in array 
     char *a[n]; 
     puts("string"); 
     for (int i = 0; i < n; ++i){ 
      gets(a+i); 
     } 
     puts("-----"); 
     for (int j = 0; j < n; ++j){ 
      puts(a+j); 
     } 
     puts("-----"); 
     puts(a); 
     puts("-----"); 
     puts(a+2); 

     return 0; 
    } 
+3

[___DO NOT___は 'gets()'を使用すると危険です。代わりに 'fgets()'を使用してください。](https://stackoverflow.com/a/41383540/2173917) –

+6

'a'のポインタがどこにも指していないので、未定義の動作があります。 – Kevin

+0

@Kevinしかし、それはどうですか、正しく説明してください。 –

答えて

1

を宣言しなければなりません。

あなたのプログラムでは、<string.h>というヘッダからの宣言は使用されていません。ヘッダーを削除することができます。

配列の要素を初期化し、不確定値を持っていなかったしかし、あなたはタイプchar

char *a[n]; 

へのポインタの可変長配列を宣言しました。その結果、プログラムが原因ループ

あなたが入力しようとしている各文字列にメモリを割り当てる必要が
gets(a+i); 

ためで、このステートメントに未定義の動作をしています。

また、関数getsは安全ではなく、もはやC標準ではサポートされていないことも考慮してください。代わりに関数fgetsを使用します。さらに、最後の式の型が必要な型char *ではなくchar **であるため、関数呼び出しの引数はa + iの代わりに*(a + i)でなければなりません。

ので、有効なコードは、例えば

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

int main(void) 
{ 
    size_t n; 
    const size_t SIZE = 20; 

    printf("no of elements: "); 

    if (scanf("%zu%*c", &n) != 1 || n == 0) n = 1; 

    char * a[n]; 

    for (size_t i = 0; i < n; i++) 
    { 
     *(a + i) = malloc(SIZE);  
    } 

    puts("string"); 

    for (size_t i = 0; i < n; ++i) 
    { 
     fgets(*(a + i), SIZE, stdin); 
    } 

    puts("-----"); 

    for (size_t i = 0; i < n; ++i) 
    { 
     printf("%s", *(a + i)); 
    } 

    puts("-----"); 
    printf("%s", *a); 

    puts("-----"); 
    printf("%s", *(a + 2)); 

    for (size_t i = 0; i < n; i++) 
    { 
     free(*(a + i)); 
    } 

    return 0; 
} 

その出力変数を読んだ後、この文

if (scanf("%zu%*c", &n) != 1 || n == 0) n = 1; 

no of elements: 5 
string 
A 
B 
C 
D 
E 
----- 

A 
B 
C 
D 
E 
----- 
A 
----- 
C 

注意を払うようになります。次の方法を見ることができますnフォーマット指定子&zuを使用すると、r入力バッファから、押されたキーに対応する改行文字をemoveします。そうでなければ、fgetsの次の呼び出しは空の文字列を読み込みます。

1

あなたはおそらくこれが欲しい:

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

int main() 
{ 
    int n; 
    printf("no of elements\n"); 
    scanf("%d", &n); // No space after the %d ! 

    char dummy[2];   // these 2 lines are needed for absorbing the leftover 
    fgets(dummy, 2, stdin); // \n from scanf (mixing fgets and scanf is a bad idea) 

    char *a[n];  // here we'll have an array of n pointers to char. For the moment 
        // the array is not initialized and the pointers point nowhere 

    puts("string"); 

    for (int i = 0; i < n; ++i) { 
    a[i] = malloc(100);   // allocate memory for a string of a maximum length of 99. 
           // + one char for the NUL terminator 
           // Allocating a fixed size is awkward, but it will 
           // do here for demonstration purposes 

    fgets(a[i], 100, stdin); // limit the length of string to 100 in order 
           // to avoid buffer overflow 
           // it's basically the same as gets(buffer) 
    } 

    puts("-----"); 
    for (int j = 0; j < n; ++j) { 
    puts(a[j]); 
    } 

    puts("-----"); 
    puts(a[0]); 
    puts("-----"); 
    puts(a[2]); 

    return 0; 
} 

入力および出力:

no of elements 
3 
string 
11 
22 
33 
----- 
11 

22 

33 

----- 
11 

----- 
33 

エラーチェックを簡潔にするために回避されます。この宣言で宣言された変数

char ch; 

は、プログラムで使用されず、除去されるべきである

int main(void) 
ようにパラメータなしでC標準関数mainに係るスタータのため

関連する問題