在main via函数参数中添加一个数组

时间:2017-07-07 00:53:28

标签: c arrays string

我不确定我是否正确地说了这个标题,但基本上。我想知道是否有一种方法可以使用参数中的指针从hey函数添加到buff数组中,为什么它会起作用呢?

BUF [100]。 例如:

int main(){
  char buf[100];
  hey("320244",buf);
  printf("%s", buf);
}
  void hey(char* s, char* result){
  /*
  some code that appends to result using pointers
  do some stuff with s and get the result back in buf without using return.
  */
}

3 个答案:

答案 0 :(得分:2)

我已经修改了一些评论代码: -

#define LEN 100 //Use a macro instead of error prone digits in code

void hey(char* s, char* result); //Fwd declaration 

int main(){
  char buf[LEN] = {0}; //This will initialize the buffer on stack
  hey("320244",buf);
  printf("%s", buf);
  hey("abc", buf); //Possible future invocation
  printf("%s", buf);
}

void hey(char* s, char* result){
  if(strlen(result) + strlen(s) < LEN ) //This will check buffer overflow
    strcat(result, s); //This will concatenate s into result
  else
    //Do some error handling here
}

答案 1 :(得分:2)

让我们做正确的事情,并使用结构来描述动态分配的,按需增长的字符串:

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

struct mystring {
    char   *ptr;  /* The actual string */
    size_t  len;  /* The length of the string */
    size_t  max;  /* Maximum number of chars allocated for */
};
#define MYSTRING_INIT { NULL, 0, 0 }

如果我们想要向struct mystring追加一些东西,我们定义一个函数,该函数接受一个指向函数可以修改的结构的指针。 (如果它只需要一个char指针而不是一个结构,那么它需要一个char **;一个指向char指针的指针。)

void mystring_append(struct mystring *ms, const char *s)
{
    const size_t slen = (s) ? strlen(s) : 0;

    /* Make sure ms points to a struct mystring; is not NULL */
    if (!ms) {
        fprintf(stderr, "mystring_append(): No struct mystring specified; ms == NULL!\n");
        exit(EXIT_FAILURE);
    }

    /* Make sure we have enough memory allocated for the data */
    if (ms->len + slen >= ms->max) {
        const size_t  max = ms->len + slen + 1;
        char         *ptr;

        ptr = realloc(ms->ptr, max);
        if (!ptr) {
            fprintf(stderr, "mystring_append(): Out of memory!\n");
            exit(EXIT_FAILURE);
        }

        ms->max = max;
        ms->ptr = ptr;
    }

    /* Append. */
    if (slen > 0) {
        memmove(ms->ptr + ms->len, s, slen);
        ms->len += slen;
    }

    /* We allocated one char extra for the
       string-terminating nul byte, '\0'. */
    ms->ptr[ms->len] = '\0';

    /* Done! */
}

(s) ? strlen(s) : 0;表达式使用?:条件运算符。实质上,如果s为非NULL,则表达式的计算结果为strlen(s),否则计算结果为0。你可以用

size_t slen;

if (s != NULL)
    slen = strlen(s);
else
    slen = 0;

代替;我更喜欢简洁的const size_t slen = (s) ? strlen(s) : 0形式。 (const告诉编译器slen变量不会被修改。虽然它可能有助于编译器生成更好的代码,但它主要是对其他程序员slen的暗示通过这个函数具有这个特殊的值,所以他们不需要检查它是否可以在某处修改。它有助于长期编码维护,所以这是一个非常好的习惯。)

通常,函数会返回成功或错误。为了便于使用,mystring_append()不会返回任何内容。如果有错误,它会向标准输出打印一条错误消息,并停止该程序。

最好创建一个释放此类结构所使用的动态内存的函数。例如,

void mystring_free(struct mystring *ms)
{
    if (ms) {
        free(ms->ptr);
        ms->ptr = NULL;
        ms->len  = 0;
        ms->max  = 0;
    }
}

通常,您也会看到初始化函数,例如

void mystring_init(struct mystring *ms)
{
    ms->ptr = NULL;
    ms->len = 0;
    ms->max = 0;
}

但我更喜欢先前定义的MYSTRING_INIT之类的初始化宏。

您可以在以下程序中使用上述内容:

int main(void)
{
    struct mystring  message = MYSTRING_INIT;

    mystring_append(&message, "Hello, ");
    mystring_append(&message, "world!");

    printf("message = '%s'.\n", message.ptr);

    mystring_free(&message);

    return EXIT_SUCCESS;
}

注意:

  • 当我们声明结构类型的变量(而不是指向结构的指针,即没有*)时,我们在变量名和字段名之间使用.。在main()中,我们有struct mystring message;,因此我们使用message.ptr来引用message结构中的字符指针。

  • 当我们将变量声明为指向结构类型的指针时(如在函数中,在变量名称之前使用*),我们在变量名和字段之间使用->名称。例如,在mystring_append()中我们有struct mystring *ms,因此我们使用ms->ptr来引用ms变量指向的结构中的char指针。

  • 动态内存管理并不困难。 realloc(NULL, size)相当于malloc(size)free(NULL)是安全的(什么都不做)。

    在上面的函数中,我们只需要跟踪当前长度,以及为字段ptr指向的动态缓冲区分配的字符数,并记住字符串需要终止nul字节, '\0',不计入其长度。

    上面的函数只为附加字符串重新分配了足够的内存。实际上,通常会分配额外的内存,以便将所需的重新分配数量保持在最低水平。 (这是因为与其他操作相比,内存分配/重新分配功能被认为是昂贵的,或者速度很慢。)但这是另一个场合的主题。

  • 如果我们希望函数能够修改调用者范围中的变量(即任何类型,甚至是结构) - 上例中struct mystring message;中的main() - - ,该函数需要获取指向该类型变量的指针,并通过指针修改该值。

  • address-of运算符&获取某个变量的地址。特别是,上面示例中的&message计算为指向struct mystring的指针。

    如果我们使用struct mystring *ref = &message;撰写struct mystring message;,则messagestruct mystring类型的变量,而ref是指向message的指针}; ref属于struct mystring *类型。

答案 2 :(得分:0)

如果我理解正确你的意思是以下

#include <string.h>

//...

void hey(char* s, char* result)
{
    strcpy( result, s );
}

这是一个示范程序

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

void hey( const char* s, char* result);

int main(void) 
{
    char buf[100];

    hey( "320244", buf );

    printf( "%s\n", buf );

    return 0;
}

void hey( const char* s, char* result )
{
    strcpy( result, s );
}

它的输出是

320244

如果数组buf已经存储了一个字符串,那么你可以向它添加一个新的字符串。例如

#include <string.h>

//...

char buf[100] = "ABC";

strcat( buf, "320244" );

考虑到函数hey应该在使用之前声明,并且根据C标准,函数main应声明为

int main( void )