简体   繁体   English

将char添加到C中的char *?

[英]Appending a char to a char* in C?

I'm trying to make a quick function that gets a word/argument in a string by its number: 我正在尝试创建一个快速函数,通过其数字在字符串中获取单词/参数:

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

I can't find a way to put the characters into Return . 我找不到将角色放入Return I have found lots of posts that suggest strcat() or tricks with pointers, but every one segfaults. 我发现很多帖子都提示strcat()或带有指针的技巧,但每一个都是段错误。 I've also seen people saying that malloc() should be used, but I'm not sure of how I'd used it in a loop like this. 我也看到人们说应该使用malloc() ,但我不确定我是如何在这样的循环中使用它的。

I will not claim to understand what it is that you're trying to do, but your code has two problems: 我不会声称你理解你正在尝试做什么,但是你的代码有两个问题:

  • You're assigning a read-only string to Return ; 您正在为Return分配一个只读字符串; that string will be in your binary's data section, which is read-only, and if you try to modify it you will get a segfault. 该字符串将位于二进制文件的数据部分,该部分是只读的,如果您尝试修改它,则会出现段错误。
  • Your for loop is O(n^2), because strlen() is O(n) 你的for循环是O(n ^ 2),因为strlen()是O(n)

There are several different ways of solving the "how to return a string" problem. 解决“如何返回字符串”问题有几种不同的方法。 You can, for example: 你可以,例如:

  • Use malloc() / calloc() to allocate a new string, as has been suggested 正如所建议的那样,使用malloc() / calloc()来分配新字符串
  • Use asprintf() , which is similar but gives you formatting if you need 使用asprintf() ,它类似,但如果需要,可以为您提供格式
  • Pass an output string (and its maximum size) as a parameter to the function 将输出字符串(及其最大大小)作为参数传递给函数

The first two require the calling function to free() the returned value. 前两个需要调用函数来free()返回的值。 The third allows the caller to decide how to allocate the string (stack or heap), but requires some sort of contract about the minumum size needed for the output string. 第三个允许调用者决定如何分配字符串(堆栈或堆),但需要某种关于输出字符串所需的最小大小的契约。

In your code, when the function returns, then Return will be gone as well, so this behavior is undefined. 在您的代码中,当函数返回时, Return也将消失,因此这种行为是未定义的。 It might work, but you should never rely on it. 它可能会奏效,但你永远不应该依赖它。

Typically in C, you'd want to pass the "return" string as an argument instead, so that you don't have to free it all the time. 通常在C中,您希望将“return”字符串作为参数传递,这样您就不必一直free它。 Both require a local variable on the caller's side, but malloc 'ing it will require an additional call to free the allocated memory and is also more expensive than simply passing a pointer to a local variable. 两者都需要调用者端的局部变量,但malloc将它需要额外的调用来释放分配的内存,并且比仅仅将指针传递给局部变量更昂贵。

As for appending to the string, just use array notation (keep track of the current char/index) and don't forget to add a null character at the end. 至于附加到字符串,只需使用数组表示法(跟踪当前的char / index)并且不要忘记在末尾添加空字符。

Example: 例:

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
}

Then invoke it like so: 然后像这样调用它:

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

Just make sure you don't overflow ptr (eg: by passing its size and adding a check in the function). 只要确保你没有溢出ptr (例如:通过传递它的大小并在函数中添加一个检查)。

There are numbers of ways you could improve your code, but let's just start by making it meet the standard. 有许多方法可以改进您的代码,但让我们开始使其符合标准。 ;-) ;-)

PS: Don't malloc unless you need to . PS:除非你需要,否则不要使用malloc And in that case you don't. 在那种情况下,你没有。

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

You can't assign anything to a string literal such as "". 您不能将任何内容分配给字符串文字,例如“”。

You may want to use your loop to determine the offsets of the start of the word in your string that you're looking for. 您可能希望使用循环来确定字符串中您要查找的单词开头的偏移量。 Then find its length by continuing through the string until you encounter the end or another space. 然后通过继续穿过字符串找到它的长度,直到遇到结束或另一个空格。 Then, you can malloc an array of chars with size equal to the size of the offset+1 (For the null terminator.) Finally, copy the substring into this new buffer and return it. 然后,你可以malloc一个大小等于offset + 1大小的字符数组(对于null终止符。)最后,将子字符串复制到这个新的缓冲区并返回它。

Also, as mentioned above, you may want to remove the strlen call from the loop - most compilers will optimize it out but it is indeed a linear operation for every character in the array, making the loop O(n**2). 另外,如上所述,您可能希望从循环中删除strlen调用 - 大多数编译器会对其进行优化,但它确实是数组中每个字符的线性运算,从而形成循环O(n ** 2)。

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM