程序:使用变量arugment函数的概念进行字符串连接

时间:2016-12-31 16:00:39

标签: c string concatenation

嗨,我在初学者级别,我正在使用变量参数函数的概念来连接字符串。对不同数量的字符串调用相同的函数。

我无法计算连接字符串的长度,这反过来意味着我没有正确分配内存。亲爱的同行们,请帮忙!

/* Program to do string concatenation using the concept of variable arguments */

/********************************************************************************
*                               REQUIRED HEADER FILES
*********************************************************************************/

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

/********************************************************************************
*                               REQUIRED MACROS DEFINED
*********************************************************************************/

#define ERROR_CHECKER(result)\
    if(result == FAILURE)\
    {\
        printf("\n CONCATENATION FAILED");\
    }
typedef enum {SUCCESS = 0, FAILURE = 1} return_type;

/********************************************************************************
*                               REQUIRED FUNCTION PROTOTYPES
*********************************************************************************/
return_type string_concat(char* string_pointer, ...);

/********************************************************************************
*
*    FUNCTION_NAME  :  STRING_CONCAT
*
*    DESCRIPTION    :  concatenates incoming strings and displays the result
*
*    RETURNS        :  SUCCESS OR FAILURE 
*
*********************************************************************************/
return_type string_concat(
    char* string_pointer, 
    ...)
{

/********************************************************************************
*                               REQUIRED DECLARATIONS
*********************************************************************************/
// 1. arg_list that will point to variable number of arguments 
va_list arg_list;

// 2. pointer to concatenated string 
char* concatenated_string;

// 3. character pointer to point to an individual element in the argument list
char* individual_string_pointer;

// 4. amount of memory required to be allocated 
int length;
/*********************************************************************************
*                               REQUIRED INITIALIZATIONS
*********************************************************************************/
va_start(arg_list, string_pointer);
concatenated_string = NULL;
individual_string_pointer = string_pointer;
length = 0;
/*********************************************************************************
*                               PERFORMING REQUIRED TASKS
**********************************************************************************/

// 1. calculate length till you reach quit
while(strcmp(individual_string_pointer,"quit") == 0)
{
    individual_string_pointer = va_arg(arg_list, char*);
    length = length + strlen(individual_string_pointer);
}

// individual_string_pointer reinitialized to be used for concatenation
individual_string_pointer = string_pointer;

printf("\nlength of concatenated string : %d", length);

// 2. allocate memory for the concatenated string
concatenated_string = (char*) malloc(sizeof(char) * length + 1);

// 3. use strncpy to copy first string and then use strncat to concatenate others

strncpy(concatenated_string, string_pointer, sizeof(*(string_pointer)));

while(strcmp(individual_string_pointer, "quit") == 0)
{
    individual_string_pointer = va_arg(arg_list, char*);
    strncat(concatenated_string, individual_string_pointer, sizeof(*(individual_string_pointer)));
}

printf("\n concatenated string : %s",concatenated_string);

va_end(arg_list);
return SUCCESS;
}

/********************************************************************************
*
*   FUNCTION_NAME   :   MAIN
*
*   DESCRIPTION     :   CALLS STRING_CONCAT FUNCTION
*
*   RETURNS         : SUCCESS 
*********************************************************************************/
int main(void)
{

/********************************************************************************
*                               REQUIRED DECLARATIONS
*********************************************************************************/
// 1. character array as the first argument
char string_one[5] = "hello" ;

// 2. variable to store result from the string_concat function.
int result;

/*********************************************************************************
*                               REQUIRED INITIALIZATIONS
**********************************************************************************/

result = 0;

/*********************************************************************************
*                               PERFORMING REQUIRED TASKS
**********************************************************************************/
// 1. call string_concat function with 2 arguments
   result = string_concat(string_one, "my", "name","is","amninder","quit");
    // handle error from string_concat
    ERROR_CHECKER(result);

// 2. call string_concat function with 3 arguments
   result = string_concat(string_one, "I", "Like","fruits","quit");
    // handle error from string_concat
    ERROR_CHECKER(result);  

// 3. call string_concat function with 4 arguments 
   result = string_concat(string_one, "awesome","quit");
    // handle error from string_concat
    ERROR_CHECKER(result);
/* doubt: do I need to send my first argument as same always " */
return SUCCESS;
}

4 个答案:

答案 0 :(得分:2)

除了其他问题:此sizeof(*(individual_string_pointer)));会返回individual_string_pointer指向的大小,即char,因此返回1.

使用strlen(ndividual_string_pointer)代替,或者只是切换到使用strcat(),如下所示:

strcat(concatenated_string, individual_string_pointer)

答案 1 :(得分:0)

您的第一个问题是您没有对数据做任何事情。你的第二个是一个循环规则,防止迭代参数列表两次。

将连接的字符串作为malloced内存返回,或者在失败时返回0

class InterfaceController2: WKInterfaceController, WCSessionDelegate{
   var session: WCSession!

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        if (WCSession.isSupported()) {
            session = WCSession.default()
            session.delegate = self
            session.activate()
        }
    }

   func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {

      /// Capture data from ViewContorller 2
      let engineFromPhone = message["engine"] as? String

      // do something with engineFromPhone
    }    
 }

答案 2 :(得分:0)

不是迭代va_list两次,而是考虑realloc()并附加每个子字符串。评论中的其他想法。

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

#define return_type int
#define FAILURE -1
#define SUCCESS 0

//                        use const 
return_type string_concat(const char* string_pointer, ...) {
  va_list arg_list;
  va_start(arg_list, string_pointer);

  char* concatenated_string = NULL;
  size_t length = 0;  // Use type size_t, not int
  const char* individual_string_pointer = string_pointer;

  while (strcmp(individual_string_pointer, "quit")) {
    // Find sub-string length _once_
    size_t individual_length = strlen(individual_string_pointer);
    size_t new_length = length + individual_length;
    char *new_ptr = realloc(concatenated_string, new_length + 1);
    if (new_ptr == NULL) {
      free(concatenated_string);  // do not forget to free old string
      printf("\n MALLOC FALIED");
      return FAILURE;
    }

    concatenated_string = new_ptr;

    // or use memcpy(concatenated_string + length, 
    //            individual_string_pointer, individual_length+1)
    strcpy(concatenated_string + length, individual_string_pointer);

    length = new_length;

    individual_string_pointer = va_arg(arg_list, const char*);
  }
  va_end(arg_list);

  // Add <> to detect leading/trailing white-space
  printf("Concatenated string : <%s>\n", concatenated_string);
  free(concatenated_string);
  return SUCCESS;
}

int main(void) {
  //        not [5], let compiler size it to include the null character
  char string_one[] = "hello";
  string_concat(string_one, "my", "name", "is", "amninder", "quit");
  string_concat(string_one, "I", "Like", "fruits", "quit");
  return 0;
}

输出继电器

Concatenated string : <hellomynameisamninder>
Concatenated string : <helloILikefruits>

答案 3 :(得分:0)

你的方法不错,但可以改进,“退出”标记va_list结束不是很安全,NULL是更好的选择。因为用户可以像“qui”,“qit”或其他什么一样“退出”。以及如何“退出”?如果你使用string_concat而不知道当其中一个字符串“退出”时函数内部可能会提前停止:

char *string1 = "foo";
char *string2 = "quit";
char *string3 = "bar";
string_concat(string1, string2, string3, "quit");

仅使用“foo”。

您不会返回字符串generate,因此您的函数不是很有用。

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

#define END_STRING_CONCAT ((char const *)NULL)

char *string_concat(char const *first, ...);

char *string_concat(char const *first, ...) {
  va_list ap;
  va_start(ap, first);

  va_list cp_ap;
  va_copy(cp_ap, ap); // copy for future use

  size_t size = 1; // need the size of the future string
  for (char const *ptr = first; ptr != NULL; ptr = va_arg(ap, char const *)) {
    size += strlen(ptr);
  }
  va_end(ap);

  char *result = malloc(size);
  if (result == NULL) {
    va_end(cp_ap);
    return NULL;
  }

  size_t used = 0;
  for (char const *ptr = first; ptr != NULL; ptr = va_arg(cp_ap, char const *)) {
    size_t len = strlen(ptr);
    if (size < used || size - used < len) {
      free(result);
      va_end(cp_ap);
      return NULL;
    }
    memcpy(result + used, ptr, len); // use memcpy because it's faster in this case
    used += len;
  }
  va_end(cp_ap);
  if (size < used || size - used != 1) {
    free(result);
    return NULL;
  }
  result[used] = '\0'; // don't forget

  return result;
}

int main(void) {
  char hello[] = "hello, ";

  char *result1 = string_concat(hello, "my ", "name ", "is ", "amninder",
                                END_STRING_CONCAT);
  if (result1 != NULL) {
    printf("%s\n", result1);
    free(result1);
  }

  char *result2 = string_concat(hello, "I ", "Like ", "fruits", END_STRING_CONCAT);
  if (result2 != NULL) {
    printf("%s\n", result2);
    free(result2);
  }

  char *result3 = string_concat(hello, "awesome", END_STRING_CONCAT);
  if (result3 != NULL) {
    printf("%s\n", result3);
    free(result3);
  }

  return 0;
}