-3

私の大学は、プログラマーとして次Cのドキュメントから学ぶようにアドバイスしてくれました。 JavaJ. Maassen 著。

C46 ページ (PDF-page 47) で、Maassen はのstrcpy関数の独自のバージョンを実装しようとしています。my_strcpy

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

この機能を使ってプログラムを書いてみました。
45 ページ (PDF-46 ページ) をご覧ください。ここで、Maassen は a -メソッドの最初のバージョンを紹介しましたstrcpy。彼は を含めstdio.hてコピーstrAしましたstrB

それで、次のプログラムは動くはずですよね?

#include <stdio.h>

char strA[80] = "A string to be used for demonstration purposes";
char strB[80];

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

まあ、実際にはそうではありません。
このプログラムをコンパイルするたびに、次のエラーが発生するためです。

PROGRAM.c:12:7: error: conflicting types for ‘my_strcpy’
 char *my_strcpy(char *destination, char *source)
       ^
PROGRAM.c:8:5: note: previous implicit declaration of ‘my_strcpy’ was here
 mystrcpy(strB, strA);
 ^

このプログラムが機能しないのはなぜですか? つまり、うまくいくはずですよね?
私はここstrcpyで関数の同様の実装を見てきました。そして、その実装も機能していません! 私は同じエラーが発生しています!

どうしたの?

4

3 に答える 3

3

コンパイラがプログラムの 8 行目を確認すると、どの型my_strcpyが取得または返されるかがわかりません。ソース ファイル内のmainとの順序を入れ替えるか、 beforeのプロトタイプを追加します。my_strcpymy_strcpymain

于 2013-12-07T17:20:48.577 に答える
2

テキストで宣言する前にメソッドを使用できる Java とは異なり、C では呼び出す関数ごとにプロトタイプが必要です。プロトタイプを提供しない場合、C はデフォルトの規則を使用し、プロトタイプのない関数が、最初に渡すものの型に一致するパラメーターを取り、int.

これを修正するには、次の行を の前に追加しますmain

char *my_strcpy(char *, char *);

注: realstrcpyでは、定数へのポインターを 2 番目のパラメーターとして渡すことができます。これにより、次のような呼び出しを行うことができます。

my_strcpy(dest, "quick brown fox");

宣言と定義を次のように変更することをお勧めします。

char *my_strcpy(char *, const char *);

char *my_strcpy(char *destination, const char *source)
{
      char* p = destination;
      while (*source != '\0')
      {
          *p++ = *source++;
      }
      *p = '\0';
     return destination;
}

注意すべきもう 1 つのことは、 を避けdestinationて で行ったのと同じことを行うことができるということです。暗黙のゼロ比較を使用することもできます - Java では利用できないもう 1 つのこと:sourcep

char *my_strcpy(char *destination, const char *source)
{
      while (*source) // Removed comparison to zero
      {
          *destination++ = *source++;
      }
      *destination = '\0';
     return destination;
}

最後に、ループの最後にゼロが代入されるのを避けるために、本文のないワンライナー実装を使用できます。

char *my_strcpy(char *destination, const char *source)
{
      while (*destination++ = *source++)
          ;
     return destination;
}
于 2013-12-07T17:22:33.913 に答える
1

初めて使用my_strcpyするとき、コンパイラはまだそれを認識しておらず、プロトタイプもありません。したがって、(おそらく) を返す関数として自動的に定義されますint

呼び出しの前にプロトタイプを提供する必要があります。

char *my_strcpy(char *destination, char *source);

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    ...

または、実際に呼び出す前に呼び出しを定義します (つまり、main() を一番下に配置します)。

大規模なプロジェクトの場合、すべてのプロトタイプを外部ファイルに配置し、次のファイルを含めます。

#include "my_functions.h"

ところで、main通常はコマンドラインから引数が渡されるため、次のように定義します

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


    return 0;
}

有効な戻りコードを返します (たとえば、すべてがうまくいった場合は 0)。*pragma* を使用して、呼び出されたコードで一部の引数が実際には必要ないことをコンパイラーに伝えることができます。

于 2013-12-07T17:21:15.293 に答える