retorno - Devolver cadena de la función C
corriente de retorno electrica (7)
No he usado C en más de 3 años, estoy bastante oxidado en muchas cosas.
Sé que esto puede parecer estúpido, pero no puedo devolver una cadena de una función en este momento.
Suponga que: no puedo usar
string.h
para esto.
Aquí está mi código:
#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;
}
Puedo capturar la cadena (con mi función
getStr
) pero no puedo hacer que se muestre correctamente (obtengo basura).
La ayuda es apreciada.
Asigne la cadena en la pila en el lado de la persona que llama y páselo a su función:
void getStr(char *wordd, int length) {
...
}
int main(void) {
char wordd[10 + 1];
getStr(wordd, sizeof(wordd) - 1);
...
}
O haga que la cadena sea estática en
getStr
:
char *getStr(void) {
static char wordd[10 + 1];
...
return wordd;
}
O asigne la cadena en el montón:
char *getStr(int length) {
char *wordd = malloc(length + 1);
...
return wordd;
}
Encontré este hilo mientras trabajaba en mi comprensión de Cython. Mi extensión a la pregunta original podría ser útil para otras personas que trabajan en la interfaz de C / Cython. Entonces esta es la extensión de la pregunta original: ¿cómo devuelvo una cadena de una función C, dejándola disponible para Cython y, por lo tanto, para Python?
Para aquellos que no están familiarizados con él, Cython le permite escribir estáticamente el código Python que necesita para acelerar. Entonces, el proceso es, disfruta escribiendo Python :), encuentra que es un poco lento en alguna parte, perfílalo, deja una función o dos y ciptizalas. Guau. Cerca de la velocidad C (se compila a C) Fijo. Hurra. El otro uso es importar funciones C o bibliotecas en Python como se hace aquí.
Esto imprimirá una cadena y devolverá la misma u otra cadena a Python.
Hay 3 archivos, el archivo c c_hello.c, el archivo cython sayhello.pyx y el archivo de configuración de cython sayhello.pyx.
Cuando se compilan con
python setup.py build_ext --inplace
, generan un archivo de biblioteca compartida que se puede importar a python o ipython y se ejecuta la función 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
)
Está asignando su cadena en la pila y luego le devuelve un puntero. Cuando su función regresa, cualquier asignación de pila se vuelve inválida; el puntero ahora apunta a una región en la pila que probablemente se sobrescribirá la próxima vez que se llame a una función.
Para hacer lo que estás tratando de hacer, debes hacer uno de los siguientes:
-
Asigne memoria en el montón utilizando
malloc
o similar, luego devuelva ese puntero. La persona que llama deberá llamarfree
cargo cuando termine con la memoria. - Asigne la cadena en la pila en la función de llamada (la que usará la cadena) y pase un puntero a la función para colocar la cadena. Durante toda la llamada a la función de llamada, los datos en su pila son válidos; es solo una vez que devuelve esa pila, el espacio asignado se usa por otra cosa.
Más fácil aún: devuelva un puntero a una cadena que ha sido mal colocada con 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;
}
Su puntero apunta a la variable local de la función. Tan pronto como regrese de la función, la memoria se desasigna. Debe asignar memoria en el montón para usarla en otras funciones.
En cambio
char *rtnPtr = word;
hacer esto
char *rtnPtr = malloc(length);
Para que esté disponible en la función principal. Después de que se usa, libera la memoria.
word
está en la pila y queda fuera de alcance en cuanto
getStr()
regresa.
Estás invocando un comportamiento indefinido.
char word[length];
char *rtnPtr = word;
...
return rtnPtr;
Esto no está bien. Está devolviendo un puntero a una variable automática (de ámbito), que se destruirá cuando regrese la función. El puntero se dejará apuntando a una variable destruida, que casi con seguridad producirá resultados "extraños" (comportamiento indefinido).
Debería asignar la cadena con
malloc
(por ejemplo,
char *rtnPtr = malloc(length)
), y luego
free
más tarde en
main
.