使用变量参数函数连接字符串

时间:2014-09-10 08:16:11

标签: c

我创建了一个程序,它接收2到5个字符串,并使用变量参数函数连接在一起。

到目前为止程序工作正常,但在显示完整字符串之前,它总是在最后显示3个随机字符。

例如:

Please insert number of strings: 3
string 1: car
string 2: bike
string 3: plane

全字符串:

=$>carbikeplane

我已经对程序进行了一些调整,试图找到原因并修复它,但是我总是得到相同的结果。

完整的程序如下所示。 关于该计划的评论很少:

  1. 我正在程序的不同部分打印字符串,因为我试图找出问题的来源。所以一些printf()函数可能没有意义。
  2. 主要功能似乎很好,问题出在后面定义的功能中。
  3. 注意:我还在学习C,所以可能会有一些代码可以/可能会创建未定义的行为,如果有的话,如果你能指出这些,我将不胜感激。

    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    
    char *function(int num, ...);
    
    int main(void)
    {
        char line1[80] = " ", line2[80] = " ", line3[80] = " ", line4[80] = " ", line5[80] = " ";
        int count = 0, count2;
        char *newStr;
        int i;
        int status;
    
        do {
            fflush(stdin);
            printf("\nPlease select the number of strings (max. 5): ");
            scanf("%d", &count);
    
        }while(count < 2 && count > 5);
    
        count2 = count;
        fflush(stdin);
    
        status = 1;
        for( i = 1 ; count > 0; count--, i++)
        {
            switch(status)
            {
                case 1:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line1);
                    status = 2;
                    break;
                }
                case 2:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line2);
                    status = 3;
                    break;
                }
                case 3:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line3);
                    status = 4;
                    break;
                }
                case 4:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line4);
                    status = 5;
                    break;
                }
                case 5:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line5);
                    status = 6;
                    break;
                }
            }
    
        }
            printf("\n%s\n%s\n%s\n%s\n%s\n", line1, line2, line3, line4, line5);
        /*call the function of variable arguments*/
            /*memory allocation of newstr*/
            newStr = (char *)malloc(420*sizeof(char) +1);
        switch(count2)
        {
            case 2:
            {
                newStr = function(2, line1, line2);
                break;
            }
            case 3:
            {
                newStr = function(3, line1, line2, line3);
                break;
            }
            case 4:
            {
                newStr = function(4, line1, line2, line3, line4);
                break;
            }
            case 5:
            {
                newStr = function(5, line1, line2, line3, line4, line5);
            }
        }
    
        printf("\nThe final string is: \n");
        printf("%s", newStr);
    
        return 0;
    
    }
    
    
    char *function(int num, ...)
    {
        va_list arg_ptr;
        int b; 
        char *string;
        char *curstr;
    
        va_start(arg_ptr, num);     /*initialize the arg_ptr*/
    
        string = (char *)malloc(420*sizeof(char) + 1);
        *string = " ";
    
        for(b=0; b < num; b++)
        {
            curstr = va_arg(arg_ptr, char * );
            string = strcat(string,curstr);
        }
    
        printf("\n%s", string);
    
        va_end(arg_ptr);
    
        return string;
    
    } 
    

4 个答案:

答案 0 :(得分:4)

真正的问题是您可以编译该行:*string = " ";这不再有效,不应该编译。假设您将该行放在那里以初始化您的字符串以获得初始值。但是这可以通过像这样分配字符串来轻松解决:

string = calloc(420, sizeof(char));

ie:使用calloc将内存设置为零。这样你就有了一个可以被strcat使用的有效字符串。

我没有告诉您不要使用getsfflush,因为很明显这是家庭作业,建议的fgets在处理时有其自身的问题用输入字符串。当然,如果你在生产代码中使用gets,那么有人会在那个时候踢你。

关于再次施放malloc的返回值,它是一把双面剑。如果您确定您将项目编译为C项目(即:文件名以.c结尾并使用gcc编译),那么是。不要施放。但在其他情况下,例如命名文件.cpp或使用g ++编译....好。您将收到错误:error: invalid conversion from ‘void*’ to ‘char*’没有演员表。而且我觉得在初级阶段,在为学校做家务时,你或多或少会集中精力使你的代码编译和运行,而不是坚持迂腐。但是对于未来,建议您迂腐。

答案 1 :(得分:0)

这是一种快速而又脏的方法来连接用户想要输入的字符串。完成后只需按ctrl+d即可结束输入:

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

char *concat (const char *str1, const char *str2) {

    size_t len1 = strlen (str1);         /* get lenghts */
    size_t len2 = strlen (str2);

    char * s = malloc (len1 + len2 + 2); /* allocate s and concat with ' ' */
    memcpy (s, str1, len1);
    s [len1] = ' ';
    memcpy(s + len1 + 1, str2, len2); /* does not include terminating null */
    s [len1 + len2 + 1] = '\0';       /* force null termination            */

    return s;
}

int main (void) {

    char *line = NULL;  /* pointer to use with getline ()  */
    ssize_t read = 0;
    size_t n = 0;
    int cnt = 0;
    char *str;

    printf ("\nEnter a line of text to concatenate (or ctrl+d to quit)\n\n");

    while (printf (" input: ") && (read = getline (&line, &n, stdin)) != -1) {

        if (line[read-1] == '\n') {     /* strip newline */
            line[read-1] = 0;
            read--;
        }

        if (cnt == 0)                   /* if more than 1 word, concat */
            str = strdup (line);
        else
            str = concat (str, line);

        cnt++;
    }

    printf ("\n\n  Concatenated string: %s\n\n", str);

    return 0;

}

<强>输出:

$ ./bin/concat

Enter a line of text to concatenate (or ctrl+d to quit)

  input: my dog
  input: has lots of fleas
  input: my cat
  input: has some too.
  input:

    Concatenated string: my dog has lots of fleas my cat has some too.

答案 2 :(得分:-1)

您的代码长度与用户可以输入的最大字符串成比例。这听起来不太好,对吧? (如果将来某人要求你改变它以允许用户输入10个字符串怎么办?20?100 ????。

在这种情况下,通常在帮助来到数组 - 而不是只有5个不同的变量使用它们的数组:

所以改变:

char line1[80], line2[80], line3[80], line4[80], line5[80];

为:

char lines[5][80];

因此,当需要为例如第二个字符串,你可以通过:

char* line2 = lines[1]; \\ remember about indexes starting from 0, 
                        \\ so second element has index 1

现在,您可以选择使用以下5个开关案例:

for( i = 1 ; count > 0; count--, i++)
{
    printf("\nInput string[%d]: ", i);
    fgets(lines[i], 80, stdin);
}

此外,您不需要变量参数函数,因为您可以传递数组及其大小:

char *function(int array_elements, char ** array);
//Usage:
concatenated_string = function(5, lines);

将所有const值放入变量也是一种好习惯(因此,当更改字符串用户的最大数量时,可以输入,只需更改一个位置)。

const int MAX_STRINGS = 5;
const int MAX_STRING_LENGTH = 80;

现在出现了真正的问题:

string = (char *)malloc(420*sizeof(char) + 1);
*string = " ";

为什么要分配420个字节?如果用户只输入一个字符串怎么办 - 剩下的340字节需要什么呢?

要获得连接字符串的长度,遍历行(从0到array_size),获取行的长度(使用strlen),将它们加在一起并为尾随&0 39添加1。现在你不会分配任何不必要的内存。

下一步 - *string = " ";不应该编译,因为*stringchar" "是字符串(char *)。请改为*string = '\0'或致电calloc而不是malloc

答案 3 :(得分:-2)

这是修改后的代码正常工作

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

    char *function(int num, ...);

    int main(void)
    {
        char line1[80] = " ", line2[80] = " ", line3[80] = " ", line4[80] = " ", line5[80] = " ";
        int count = 0, count2;
        char *newStr;
        int i;
        int status;

        do {
            fflush(stdin);
            printf("\nPlease select the number of strings (max. 5): ");
            scanf("%d", &count);

        }while(count < 2 && count > 5);

        count2 = count;
        fflush(stdin);

        status = 1;
        for( i = 1 ; count > 0; count--, i++)
        {
            switch(status)
            {
                case 1:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line1);
                    status = 2;
                    break;
                }
                case 2:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line2);
                    status = 3;
                    break;
                }
                case 3:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line3);
                    status = 4;
                    break;
                }
                case 4:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line4);
                    status = 5;
                    break;
                }
                case 5:
                {
                    printf("\nInput string[%d]: ", i);
                    gets(line5);
                    status = 6;
                    break;
                }
            }

        }
            printf("\n%s\n%s\n%s\n%s\n%s\n", line1, line2, line3, line4, line5);
        /*call the function of variable arguments*/
            /*memory allocation of newstr*/
            newStr = (char *)malloc(420*sizeof(char) +1);
        switch(count2)
        {
            case 2:
            {
                newStr = function(2, line1, line2);
                break;
            }
            case 3:
            {
                newStr = function(3, line1, line2, line3);
                break;
            }
            case 4:
            {
                newStr = function(4, line1, line2, line3, line4);
                break;
            }
            case 5:
            {
                newStr = function(5, line1, line2, line3, line4, line5);
            }
        }

        printf("\nThe final string is: \n");
        printf("%s", newStr);

        return 0;

    }


    char *function(int num, ...)
    {
        va_list arg_ptr;
        int b; 
        char *string;
        char *curstr;

        va_start(arg_ptr, num);     /*initialize the arg_ptr*/

        string = (char *)malloc(420*sizeof(char) + 1);
        //*string = " ";

        for(b=0; b < num; b++)
        {
            curstr = va_arg(arg_ptr, char * );
            string = strcat(string,curstr);
        }

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

        va_end(arg_ptr);

        return string;

    } 

刚刚包含stdlib和评论*字符串

度过愉快的一天