私は3年以上Cを使用していませんが、多くのことでかなり錆びています。
これは愚かに見えるかもしれませんが、現時点では関数から文字列を返すことはできません。次のことを前提にしてください:string.h
は使用できません。
ここに私のコードがあります:
#include <ncurses.h>
char * getStr(int length)
{
char Word[length];
for (int i = 0; i < length; i++)
{
Word[i] = getch();
}
Word[i] = '\0';
return Word;
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}
getStr
関数を使用して文字列をキャプチャできますが、正しく表示できません(ガベージを取得します)。
ヘルプは大歓迎です。
呼び出し側のスタックに文字列を割り当て、関数に渡します。
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
または、getStr
で文字列を静的にします。
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
または、ヒープに文字列を割り当てます。
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
char Word[length];
char *rtnPtr = Word;
...
return rtnPtr;
これは良くない。関数が戻ると破棄される自動(スコープ指定)変数へのポインターを返しています。ポインターは破壊された変数を指したままになり、ほぼ確実に「奇妙な」結果(未定義の動作)を生成します。
malloc
(例:char *rtnPtr = malloc(length)
)で文字列を割り当ててから、free
で後でmain
に割り当てます。
スタックに文字列を割り当てて、それへのポインタを返しています。関数が戻ると、スタック割り当ては無効になります。ポインタは、次に関数が呼び出されたときに上書きされる可能性があるスタック上の領域を指すようになりました。
実行しようとしていることを実行するには、次のいずれかを実行する必要があります。
malloc
などを使用してヒープにメモリを割り当て、そのポインターを返します。呼び出し元は、メモリの処理が完了したら、free
を呼び出す必要があります。ポインターが関数のローカル変数を指している。したがって、関数から戻るとすぐに、メモリの割り当てが解除されます。他の関数で使用するには、ヒープにメモリを割り当てる必要があります。
代わりにchar *rtnPtr = Word;
これを行うchar *rtnPtr = malloc(length);
メイン関数で利用できるように。使用後、メモリを解放します。
Word
はスタック上にあり、getStr()
が返るとすぐに範囲外になります。未定義の動作を呼び出しています。
Cythonの理解に取り組んでいるときに、このスレッドに出会いました。元の質問に対する私の拡張は、C/Cythonインターフェースで働いている他の人に役立つかもしれません。これは元の質問の拡張です:C関数から文字列を返し、CythonとPythonに利用できるようにする方法は?
Cythonでは、慣れていない人のために、高速化する必要があるPythonコードを静的に入力できます。したがって、プロセスはPython :)の作成を楽しみ、どこかで少し遅いことを見つけ、プロファイルを作成し、1つまたは2つの関数を分割して、それらを暗号化します。ワオ。 C速度に近い(Cにコンパイルされる)修正。わーい。もう1つの用途は、ここで行われているように、C関数またはライブラリをPythonにインポートすることです。
これは文字列を出力し、同じまたは別の文字列をPythonに返します。 cファイルc_hello.c、cythonファイルsayhello.pyx、cythonセットアップファイルsayhello.pyxの3つのファイルがあります。 python setup.py build_ext --inplace
を使用してコンパイルすると、pythonまたはipythonにインポートして関数sayhello.helloを実行できる共有ライブラリファイルが生成されます。
c_hello.c
#include <stdio.h>
char *c_hello() {
char *mystr = "Hello World!\n";
return mystr;
// return "this string"; // alterative
}
sayhello.pyx
cdef extern from "c_hello.c":
cdef char* c_hello()
def hello():
return c_hello()
setup.py
from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
ext_modules = cythonize([Extension("sayhello", ["sayhello.pyx"])])
setup(
name = 'Hello world app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
さらに簡単: strdup でmallocされた文字列へのポインターを返します。
#include <ncurses.h>
char * getStr(int length)
{
char Word[length];
for (int i = 0; i < length; i++)
{
Word[i] = getch();
}
Word[i] = '\0';
return strdup(&Word[0]);
}
int main()
{
char wordd[10];
initscr();
*wordd = getStr(10);
printw("The string is:\n");
printw("%s\n",*wordd);
getch();
endwin();
return 0;
}