1

我正在尝试制作一个快速函数,通过其编号获取字符串中的单词/参数:

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()应该使用它,但我不确定我是如何在这样的循环中使用它的。

4

5 回答 5

2

我不会声称理解您正在尝试做什么,但是您的代码有两个问题:

  • 您正在将只读字符串分配给Return; 该字符串将在您的二进制数据部分中,该部分是只读的,如果您尝试修改它,您将得到一个段错误。
  • 你的 for 循环是 O(n^2),因为strlen()是 O(n)

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

  • 使用malloc()/calloc()分配一个新字符串,如已建议的那样
  • 使用asprintf(),这很相似,但如果需要,可以为您提供格式
  • 将输出字符串(及其最大大小)作为参数传递给函数

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

于 2012-07-04T20:06:26.957 回答
1

在您的代码中,当函数返回时, thenReturn也将消失,因此此行为未定义。它可能会起作用,但你永远不应该依赖它。

通常在 C 中,您希望将“return”字符串作为参数传递,这样您就不必一直使用free它。两者都需要调用方的局部变量,但是malloc'ing 它需要额外的调用来释放分配的内存,并且比简单地将指针传递给局部变量更昂贵。

至于附加到字符串,只需使用数组表示法(跟踪当前字符/索引)并且不要忘记在末尾添加一个空字符。

例子:

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(例如:通过传递它的大小并在函数中添加一个检查)。

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

mallocPS:除非你需要,否则不要。在那种情况下,你不会。

于 2012-07-04T20:14:44.643 回答
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;
}
于 2012-07-05T11:17:22.023 回答
0

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

您可能希望使用循环来确定要查找的字符串中单词开头的偏移量。然后通过继续遍历字符串找到它的长度,直到遇到结尾或另一个空格。然后,您可以 malloc 一个大小等于 offset+1 大小的字符数组(对于空终止符)。最后,将子字符串复制到这个新缓冲区中并返回它。

此外,如上所述,您可能希望从循环中删除 strlen 调用 - 大多数编译器会对其进行优化,但它确实是数组中每个字符的线性运算,使得循环 O(n**2)。

于 2012-07-05T00:51:49.737 回答
0
char * Return;   //by the way horrible name for a variable.
Return = malloc(<some size>);
......
......
*(Return + index) = *(S+i); 
于 2012-07-04T20:03:07.707 回答