2012-07-04 49 views
1

我试图做一个快速的功能,在其数字的字符串得到一个字/参数:将char添加到C中的char *?

char* arg(char* S, int Num) { 
    char* Return = ""; 
    int Spaces = 0; 
    int i = 0; 
    for (i; i<strlen(S); i++) { 
     if (S[i] == ' ') { 
      Spaces++; 
     } 
     else if (Spaces == Num) { 
      //Want to append S[i] to Return here. 
     } 
     else if (Spaces > Num) { 
      return Return; 
     } 
    } 
    printf("%s-\n", Return); 
    return Return; 
} 

我不能找到一个办法把字符转换成Return。我发现了很多帖子,暗示strcat()或技巧与指针,但每一个段错误。我也看到有人说应该使用malloc(),但我不确定我是如何在这样的循环中使用它的。

+2

'Return'是一个临时的。当它超出范围时(例如:返回时),它将会消失,除非你首先使用'malloc'。 – netcoder

+5

@ 0xC0000022L但这个问题被标记为“C”,而不是“C++”。 – cnicutar

+0

+1因为我相信这是一个很好的c学习示例 –

回答

0
char * Return; //by the way horrible name for a variable. 
Return = malloc(<some size>); 
...... 
...... 
*(Return + index) = *(S+i); 
+3

通过增加'Return'你不能再返回它。 – cnicutar

+0

感谢您指出了这一点......我也在做* S ++这可能会导致调用代码受到影响。 – Aftnix

2

我不会要求去理解它是什么,你正在试图做的,但你的代码有两个问题:

  • 你分配一个只读字符串Return;该字符串将位于您的 二进制数据部分,该数据部分是只读的,如果您尝试修改它,则会出现段错误。
  • 您的循环是O(n^2),因为strlen()是O(n)

有解决 “如何返回一个字符串” 问题的几种不同的方式。您可以,例如:

  • 使用malloc()/calloc()分配一个新的字符串,如已提出
  • 使用asprintf(),这是类似的,但为您提供了格式,如果你需要
  • 传递一个输出字符串(及其最大尺寸)作为函数的参数

前两项要求调用函数返回值为free()。第三个允许调用者决定如何分配字符串(堆栈或堆),但需要某种关于输出字符串所需的最小大小的合约。

+0

除非你将该方法包装在一个类中,将'return'字符串作为全局类属性,并在类析构函数中释放资源 –

+0

@TheofanisPantelides您正在谈论C++。在这里没有类属性或析构函数。 –

+0

@DanielFischer http://en.wikipedia.org/wiki/Destructor_(computer_science)#In_C_with_GCC_extensions –

1

在你的代码中,当函数返回时,那么Return也会消失,所以这个行为是不确定的。它可能工作,但你应该从来没有依靠它。

通常在C中,您希望将“return”字符串作为参数传递,以便您始终不需要free。两者都需要调用者端的局部变量,但是它需要额外的调用来释放分配的内存,并且比简单地将指针传递给局部变量更昂贵。至于附加到字符串,只需使用数组符号(跟踪当前的字符/索引),并且不要忘记在末尾添加一个空字符。

例子:

int arg(char* ptr, char* S, int Num) { 
    int i, Spaces = 0, cur = 0; 
    for (i=0; i<strlen(S); i++) { 
     if (S[i] == ' ') { 
      Spaces++; 
     } 
     else if (Spaces == Num) { 
      ptr[cur++] = S[i]; // append char 
     } 
     else if (Spaces > Num) { 
      ptr[cur] = '\0'; // insert null char 
      return 0;   // returns 0 on success 
     } 
    } 

    ptr[cur] = '\0';   // insert null char 
    return (cur > 0 ? 0 : -1); // returns 0 on success, -1 on error 
} 

然后调用它像这样:

char myArg[50]; 
if (arg(myArg, "this is an example", 3) == 0) { 
    printf("arg is %s\n", myArg); 
} else { 
    // arg not found 
} 

只要确保你不会溢出ptr(例如:通过将它的大小和添加的功能检查) 。

有很多方法可以改进您的代码,但让我们开始让它符合标准。 ;-)

P.S .:不要malloc除非你需要。在那种情况下,你不会。

+0

'Return'将会消失,但它现在只是一个指向函数范围之外的字符串的指针。所以在这种特殊情况下,范围界定不是问题。 – vanza

0

您不能将任何内容分配给字符串文字,例如“”。

您可能希望使用循环来确定要查找的字符串中单词开头的偏移量。然后通过继续直到找到它的长度,直到遇到结束或另一个空间。然后,您可以malloc一个大小等于offset + 1(对于空终止符)大小的字符数组。最后,将子字符串复制到此新缓冲区中并将其返回。另外,如上所述,您可能想要从循环中删除strlen调用 - 大多数编译器都会优化它,但对于数组中的每个字符而言,它确实是一个线性操作,从而使得循环O(n ** **) 2)。

0
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char *arg(const char *S, unsigned int Num) { 
    char *Return = ""; 
    const char *top, *p; 
    unsigned int Spaces = 0; 
    int i = 0; 

    Return=(char*)malloc(sizeof(char)); 
    *Return = '\0'; 
    if(S == NULL || *S=='\0') return Return; 
    p=top=S; 
    while(Spaces != Num){ 
     if(NULL!=(p=strchr(top, ' '))){ 
      ++Spaces; 
      top=++p; 
     } else { 
      break; 
     } 
    } 
    if(Spaces < Num) return Return; 
    if(NULL!=(p=strchr(top, ' '))){ 
     int len = p - top; 
     Return=(char*)realloc(Return, sizeof(char)*(len+1)); 
     strncpy(Return, top, len); 
     Return[len]='\0'; 
    } else { 
     free(Return); 
     Return=strdup(top); 
    } 
    //printf("%s-\n", Return); 
    return Return; 
} 

int main(){ 
    char *word; 

    word=arg("make a quick function", 2);//quick 
    printf("\"%s\"\n", word); 

    free(word); 
    return 0; 
}