2014-09-12 3 views
19

저는 C를 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 기능) 문자열을 캡처 할 수 있지만, 나는 (내가 쓰레기를 얻을) 올바르게 표시 할 수 없습니다.

도움을 주시면 감사하겠습니다.

+1

당신은'ncurses.h' 사용할 수 있지만'string.h'을 sayhello.pyx? 이상한 환경 ... – nneonneo

+2

가변 길이 배열'char word [length];'(** 보안 문제 **)를 만든 다음 그 주소를'rtnPtr'에 할당하십시오 - 함수는 로컬 char 배열' 단어 [길이]'. 존재하지 않는 것을 가리키는 포인터를 반환하고 있습니다. –

+0

@nneonneo : 그것은이 과제를 수행하기위한 선결 조건입니다. 나는 이것을 위해 이것을 사용하지 않아도된다. – MrWolf

답변

34

어느 발신자 측의 스택에 문자열을 할당하고 함수에 전달 :

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; 
} 
+1

malloc을 사용하는 경우 호출자가 메모리를 해제하기 위해 포인터를 자유롭게 호출해야합니다. – Ahmed

+0

이것은 바보 같은 질문이지만 호출자가 전달한 문자열을 반환해야합니까? 나는 그것을 직접 수정하고 있는데, 왜 나는 그것을 반환해야하는지 알지 못한다. – MarcusJ

+1

두 번째 접근법의 단점을 지적해야합니다. 즉, 다음 호출에서 정적 버퍼가 덮어 쓰여지므로 메서드가 스레드로부터 안전하지 않으며 사용자가 종료되면 단일 스레드 코드에서도 예기치 않은 결과가 발생합니다 첫 번째 문자열에 대한 참조를 가지고있는 동안 메서드를 다시 호출합니다. – BeeOnRope

7
char word[length]; 
char *rtnPtr = word; 
... 
return rtnPtr; 

이것은 좋지 않습니다. 함수가 리턴 할 때 소멸 될 자동 변수 (범위가 지정된 변수)에 대한 포인터를 리턴합니다. 포인터는 파괴 된 변수를 가리키며, "이상한"결과를 생성합니다 (정의되지 않은 동작).

당신은 main에 나중에 보내고 다음 free, malloc (예를 들어, char *rtnPtr = malloc(length))로 문자열을 할당해야합니다.

1

word은 스택에 있으며 getStr()이 반환되는 즉시 범위를 벗어납니다. 정의되지 않은 동작을 호출하고 있습니다.

2

문자열을 스택에 할당 한 다음 포인터를 반환합니다. 함수가 반환되면 스택 할당은 유효하지 않게됩니다. 포인터는 이제 다음에 함수가 호출 될 때 덮어 쓰기 될 가능성이있는 스택상의 영역을 가리 킵니다. 당신이하려는 일을하기 위해

, 당신은 다음 중 하나를 수행해야합니다

  1. 는 그 포인터를 반환, malloc 또는 유사한을 사용하여 힙에 메모리를 할당합니다. 호출자는 메모리가 완료되면 free으로 전화해야합니다.
  2. 호출 함수 (문자열을 사용할 문자열)에 스택에 문자열을 할당하고 함수에 포인터를 전달하여 문자열을 넣습니다. 호출 함수에 대한 전체 호출 중에 해당 스택의 데이터가 유효합니다. 그 스택을 돌려 주면 할당 된 공간은 다른 것에 의해 사용됩니다.
2

포인터가 함수의 지역 변수를 가리키고 있습니다. 따라서 함수에서 돌아 오면 메모리가 할당 해제됩니다. 다른 기능에서 사용하려면 힙에 메모리를 할당해야합니다.

대신 char *rtnPtr = word;

는 메인 함수에서 사용할 수 있도록이 char *rtnPtr = malloc(length);

을한다. 사용 후 메모리를 해제합니다.

0

쉽게 말해서 : 쇼핑몰이었던 문자열에 대한 포인터를 반환합니다. oc'd와 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; 
} 
+0

일반적으로 이것은 잘 작동하지만이 사용자는'string.h'를 사용할 수 없으며'strdup'는 헤더 파일의 일부입니다. –

0

Cython을 이해하는 동안이 스레드를 발견했습니다. 원래 질문에 대한 나의 확장은 C/Cython 인터페이스에서 일하는 다른 사람들에게 유용 할 수 있습니다. 그래서 이것은 원래 질문의 연장입니다 : C 함수에서 문자열을 반환하여 파이썬에서 Cython &을 사용할 수 있도록 만드는 방법은 무엇입니까?

익숙하지 않은 사람들을 위해 Cython에서는 속도를 높이기 위해 정적으로 Python 코드를 입력 할 수 있습니다. 따라서 프로세스는 Python을 작성하는 즐거움이 있습니다. 어딘가에서 느린 것을 찾아 프로파일 링하고 함수 또는 두 가지 기능을 해소하고이를 cythonize하십시오. 와우. C 속도에 가깝습니다 (C로 컴파일 됨). 예. 다른 용도는 C 함수 또는 라이브러리를 여기 에서처럼 Python으로 가져 오는 것입니다.

문자열을 출력하고 동일하거나 다른 문자열을 파이썬에 반환합니다. 세 파일, c 파일 c_hello.c, cython 파일 sayhello.pyx 및 cython 설치 파일 sayhello.pyx가 있습니다. 그들은 python setup.py build_ext --inplace을 사용하여 컴파일 될 때 파이썬이나 ipython으로 가져올 수있는 공유 라이브러리 파일과 sayhello.hello 함수를 생성합니다.

c_hello.c

#include <stdio.h> 

char *c_hello() { 
    char *mystr = "Hello World!\n"; 
    return mystr; 
    // return "this string"; // alterative 
} 

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 
)