Je n'ai pas utilisé C depuis plus de 3 ans, je suis assez rouillé sur beaucoup de choses.
Je sais que cela peut sembler stupide mais je ne peux pas renvoyer une chaîne d'une fonction pour le moment. Veuillez supposer que: je ne peux pas utiliser string.h
pour cela.
Voici mon code:
#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;
}
Je peux capturer la chaîne (avec ma fonction getStr
) mais je ne parviens pas à l’afficher correctement (j’ai des ordures).
L'aide est appréciée.
Soit allouez la chaîne sur la pile côté appelant et transmettez-la à votre fonction:
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
Ou rendez la chaîne statique dans getStr
:
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
Ou allouer la chaîne sur le tas:
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
char Word[length];
char *rtnPtr = Word;
...
return rtnPtr;
Ce n'est pas bien. Vous retournez un pointeur sur une variable automatique (étendue), qui sera détruite au retour de la fonction. Le pointeur restera orienté vers une variable détruite, ce qui produira presque certainement des résultats "étranges" (comportement indéfini).
Vous devriez allouer la chaîne avec malloc
(par exemple, char *rtnPtr = malloc(length)
), puis free
et la reporter plus tard dans main
.
Vous allouez votre chaîne sur la pile, puis vous lui renvoyez un pointeur. Lorsque votre fonction revient, toute allocation de pile devient invalide. le pointeur pointe maintenant vers une région de la pile susceptible d'être écrasée lors du prochain appel d'une fonction.
Afin de faire ce que vous essayez de faire, vous devez effectuer l’une des opérations suivantes:
malloc
ou similaire, puis renvoyez ce pointeur. L’appelant devra alors appeler free
lorsque la mémoire sera utilisée.Votre pointeur pointe vers la variable locale de la fonction. Ainsi, dès que vous revenez de la fonction, la mémoire est désallouée. Vous devez affecter de la mémoire sur le tas pour pouvoir l'utiliser dans d'autres fonctions.
Au lieu de cela char *rtnPtr = Word;
faites ceci char *rtnPtr = malloc(length);
Pour qu'il soit disponible dans la fonction principale. Après utilisation, libérez de la mémoire.
Word
est sur la pile et sort de la portée dès le retour de getStr()
. Vous invoquez un comportement indéfini.
Je suis tombé sur ce fil en travaillant sur ma compréhension de Cython. Mon extension à la question initiale pourrait être utile à d’autres personnes travaillant à l’interface C/Cython. Il s’agit donc de l’extension de la question initiale: comment renvoyer une chaîne d’une fonction C en la mettant à la disposition de Cython et donc de Python?
Pour ceux qui ne le connaissent pas, Cython vous permet de taper de manière statique le code Python dont vous avez besoin pour accélérer. Le processus consiste donc à écrire Python :), à le trouver un peu lent quelque part, à le profiler, à supprimer une ou deux fonctions et à les cythoniser. Sensationnel. Vitesse proche de C (compile en C) Fixe. Yay. L'autre utilisation est d'importer des fonctions C ou des bibliothèques dans Python, comme cela est fait ici.
Ceci imprimera une chaîne et renverra la même chaîne ou une autre chaîne à Python. Il y a 3 fichiers, le fichier c_hello.c, le fichier cython sayhello.pyx et le fichier d'installation cython sayhello.pyx. Lorsqu'ils sont compilés à l'aide de python setup.py build_ext --inplace
, ils génèrent un fichier de bibliothèque partagée pouvant être importé dans python ou ipython et la fonction sayhello.hello est exécutée.
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
)
Plus facile encore: renvoie un pointeur sur une chaîne qui a été mallocée avec strdup .
#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;
}