2014-09-10 2 views
0

Я создал программу, которая получает от 2 до 5 строк и объединяет все вместе, используя функцию переменных аргументов.Объединение строк с использованием функции переменных аргументов

Пока программа работает нормально, но она всегда показывает в конце 3 случайных символа перед показом полной строки.

Например:

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

Полная строка:

=$>carbikeplane 

Я сделал несколько настроек в программе, пытаясь найти причину и устранить ее, но я всегда получаю тот же результат.

Полная программа показана ниже. Несколько комментариев о программе:

  1. Я печать строк в разных частях программы, потому что я пытался найти, где эта проблема придет. Поэтому некоторые функции printf() могут не иметь смысла.
  2. Основная функция кажется прекрасной, проблема в функции, определенной позже.

ПРИМЕЧАНИЕ: Я все еще изучаю 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

какой компилятор вы используете? '* string =" ";' недействителен и не должен компилироваться ... – fritzone

+4

Ежедневное напоминание о том, чтобы не выдавать возвращаемое значение 'malloc()'. – Igor

+1

Чтобы завершить заявление @Igor, я рекомендую вам прочитать этот вопрос, потому что я думаю, что это интересная вещь для понимания: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of- malloc – Logar

ответ

4

Реальная проблема заключается в том, что вы можете составить строку: *string = " "; Это не действительно и не должно компилировать. Предположительно, вы помещаете эту строку туда, чтобы инициализировать вашу строку, чтобы иметь начальное значение. Но это легко может быть решена путем выделения строки, как это:

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

т.е. использовать calloc, который устанавливает память до нуля. Таким образом, у вас есть допустимая строка, которую может использовать strcat.

Я не говорю, что вы не используете gets или fflush, потому что очевидно, что это домашнее задание, и предлагаемый fgets имеет свои проблемы при работе со строкой ввода. Конечно, если вы будете использовать gets в производственном коде, кто-то вас ударит в это время.

И о возврате возвращаемого значения malloc, это двухсторонний меч. Если вы точно знаете, что вы скомпилируете свой проект как проект C (то есть: имя файла заканчивается на .c, и вы используете gcc для компиляции), то да. Не бросайте. Однако в других случаях, например, имена файлов .cpp или компиляции с g ++ .... ну. Вы получите ошибку: error: invalid conversion from ‘void*’ to ‘char*’ без приведения в действие. И у меня такое ощущение, что на начальном уровне, выполняя домашние задания для школы, вы более или менее концентрируетесь на том, чтобы ваш код компилироваться и запускаться, а не быть педантичным. Однако для будущего рекомендуется, чтобы вы были педантичными.

+0

BTW: 'sizeof (char) == 1' по спецификации. – datenwolf

+0

@fritzone программа работает теперь благодаря функции calloc и удалению «», спасибо за предложения. Я еще не на C++, но в конце концов. Я не в школе heheheheheheheh, просто учиться один с несколькими книгами. –

-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 int MAX_STRINGS = 5; 
const int MAX_STRING_LENGTH = 80; 

Сейчас идет реальная проблема:

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

Почему бы вы выделить 420 байт? Что делать, если пользователь вводит только одну строку - для чего вам нужны остальные 340 байтов?

Чтобы получить длину строк конкатенации, выполните итерацию по строкам (от 0 до array_size), получите длины строк (с помощью strlen), суммируйте их и добавьте 1 для трейдинга '\ 0'. Теперь у вас не будет выделенной ненужной памяти.

Следующая - *string = " "; не должен составлять, как *string является char и " " I строка (символ *). Сделайте *string = '\0' вместо этого или позвоните calloc вместо malloc.

+0

спасибо, полезная информация. Однако это упражнение было сосредоточено исключительно на использовании функции переменных аргументов. В любом случае, я считаю ваши комментарии очень полезными. –

+0

количество выделенной памяти по-прежнему применяется – zoska

-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 и комментировал * строку

имеют хороший день

+1

этот код совершенно не подходит (да, возможно, он будет работать и компилироваться, но было бы лучше не повторять ошибки, сделанные OP в самом коде) – zoska

+0

Butsince он новый пользователь, это упростит его трудолюбие, так или иначе я не пытался полностью объяснить концепцию – Ashok

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. 
Смежные вопросы