0

ねえ、このコードは機能しています。コードは、名前の入力を取り、それを変更することに関するものです。

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

/*
 *  An example of how to use strtol() to read a number
 *  and validate that one was entered correctly.
 *
 */

int main(void)
{
  char buf[BUFSIZ];
  char *p;
  long int i;

  printf ("Enter a number: ");

  if (fgets(buf, sizeof(buf), stdin) != NULL)
  {
    i = strtol(buf, &p, 10);

    /*
     *  If the first character of the buffer is \n, the user
     *  pressed [Enter] with entering any text at all, which
     *  is therefore invalid.
     *
     *  The pointer p has been updated by strtol() to point to
     *  the first invalid character after the number.
     *  If this character is \0 it means we reached the end of
     *    the array successfully, so we received a good number.
     *  If this character is \n it also means we reached the
     *    end of the input successfully.  This is a symptom of
     *    using fgets() to obtain the string, but does not
     *    represent a problem.
     *  If this character is anything else, it means there was
     *    some additional characters entered after the number.
     *    In this sample program, I have deemed this situation
     *    to be invalid, however, in your program it may be
     *    valid, depending on what you're expecting from the user.
     *
     */

    if (buf[0] != '\n' && (*p == '\n' || *p == '\0'))
      printf ("Valid number of %ld entered\n", i);
    else  printf ("Invalid number entered\n");
  }

  return(0);
}

このコードも機能しています!文字列を取り、整数に変換します!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    int m;
    char name[m],rename[m],c=0,j=0;
    puts("enter your name\n");
    gets(name);
    m=strlen(name);
    if(m>20){
        while(m>20){
            puts("shorter name pls\n");
            gets(name);
            m=strlen(name);
        }
    }
    while(name[c]==' '){
        c++;}
    while(c<strlen(name)){
        if(name[c]==' '&& name[c+1]==' ')
            {c++;}
        else{
            rename[j]=name[c];
            j++;
            c++;}
    }
    rename[j]='\0';
    puts(rename);
    return 0;
}

しかし、同じプログラムでそれらを一緒に入力すると、プログラムがクラッシュします!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    int m;
    char name[m],rename[m],c=0,j=0;
    puts("enter your name\n");
    gets(name);
    m=strlen(name);
    if(m>20){
        while(m>20){
            puts("shorter name pls\n");
            gets(name);
            m=strlen(name);
        }
    }
    while(name[c]==' '){
        c++;}
    while(c<strlen(name)){
        if(name[c]==' '&& name[c+1]==' ')
            {c++;}
        else{
            rename[j]=name[c];
            j++;
            c++;}
    }
    rename[j]='\0';
    puts(rename);
      char buf[BUFSIZ];
  char *p;
  long int i;

  printf ("Enter a number: ");

  if (fgets(buf, sizeof(buf), stdin) != NULL)
  {
    i = strtol(buf, &p, 10);

    /*
     *  If the first character of the buffer is \n, the user
     *  pressed [Enter] with entering any text at all, which
     *  is therefore invalid.
     *
     *  The pointer p has been updated by strtol() to point to
     *  the first invalid character after the number.
     *  If this character is \0 it means we reached the end of
     *    the array successfully, so we received a good number.
     *  If this character is \n it also means we reached the
     *    end of the input successfully.  This is a symptom of
     *    using fgets() to obtain the string, but does not
     *    represent a problem.
     *  If this character is anything else, it means there was
     *    some additional characters entered after the number.
     *    In this sample program, I have deemed this situation
     *    to be invalid, however, in your program it may be
     *    valid, depending on what you're expecting from the user.
     *
     */

    if (buf[0] != '\n' && (*p == '\n' || *p == '\0'))
      printf ("Valid number of %ld entered\n", i);
    else  printf ("Invalid number entered\n");
  }
    return 0;
}

どうして??

4

3 に答える 3

2

確かにこれは非常に間違っています:

int m;
char name[m],rename[m],c=0,j=0;

長さが初期化されていない変数である配列を宣言しています。

于 2012-07-20T16:07:25.047 に答える
1

この 2 つをマージする前でも、このプログラムには見栄えがよくないものがいくつかあります。

  • 7 行目: サイズが定義されていない配列を宣言しています。
  • 18 行目: 'name' 添字インデックス c は char です - 0..127 に制限されています。int の方が良いでしょう。
  • 24行目:cとjも同様。

次に、gets() 関数は、受け入れる準備ができているよりも多くのデータをフィードしてプログラムをクラッシュさせる可能性があるため、避ける必要があります。m がゼロに初期化された場合、任意の長さの入力がクラッシュを引き起こす可能性があります。

最初の行を変更すると機能します。

int m = 100;
char name[m],rename[m];
int c=0,j=0;

...しかし、m よりも長い名前を入力すると、再びクラッシュします。

m の値を設定するだけでは、名前が m と 127 の小さい方よりも長い場合にクラッシュが発生します。たとえば、m = 200 で、130 個のスペースを含む名前を入力すると、次の行になります。

while(name[c]==' '){ c++;}

c が 126 になるまで増加し、次に 127 になると、name[127] がスペースであることがわかり、c が再び増加します。しかし、c は char なので、c+1 は 128 ではなく -128 です。インデックス 'name' のメモリ アドレスに変換すると、その -128 は宇宙空間のどこかを指し、プログラムは炎上します。

ヒント: プログラムをコンパイルするとき、まだ専門家ではない場合は、すべてのコンパイラ警告を最高の設定に保ちます。あなたが専門家であれば、それらをオフにすることができます-そして、オフにしたくないことを学んだでしょう:-)。

最初のソースで実行された GCC は次のように述べています。

In function ‘main’:
18:5: warning: array subscript has type ‘char’ [-Wchar-subscripts]
20:12: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
21:9: warning: array subscript has type ‘char’ [-Wchar-subscripts]
24:13: warning: array subscript has type ‘char’ [-Wchar-subscripts]
24:13: warning: array subscript has type ‘char’ [-Wchar-subscripts]
28:5: warning: array subscript has type ‘char’ [-Wchar-subscripts]
7:5: warning: ‘m’ is used uninitialized in this function [-Wuninitialized]
warning: the `gets' function is dangerous and should not be used.
于 2012-07-20T16:12:29.887 に答える
0

「クラッシュ」とはどういう意味ですか? 早期終了?何のエラーで?プログラムは何をすることになっていますか?

また、gets() は実際のコードでは絶対に使用しないでください。

于 2012-07-20T16:10:17.580 に答える