2011-09-14 3 views
0

Как вы можете видеть ниже, я создал небольшую программу для конкатенации 2 строк с использованием C, так как вы можете себе представить, что этот код не работает, я уже исправил его сам, используя нотацию Array вместо указателей, и он отлично работает , однако я все еще не уверен, почему мой код не является почти копией моего исправленного кода.Что не так с этим кодом?

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

void concatena(char *str1, char *str2){ 
char *strAux; 
int mover; 
mover = 0; 
strAux = (char *)(malloc(strlen(str1) + strlen(str2)+2)); 
*(strAux) = '\0'; 
if(str1 == '\0') 
    *strAux = '\0'; 
else 
    while(str1 != '\0'){ 
     *(strAux+mover++)=*(str1++); 
    } 
if(str2 == '\0') 
     *strAux = '\0'; 
else 
    while(str2 != '\0'){ 
     *(strAux+mover++)=*(str2++); 
    } 
strAux='\0'; 
str1=strAux; 
printf("%s", str1); 
free(strAux); 
} 

I'm еще новичок C (И да, я знаю, что есть библиотеки string.h, я спрашиваю это по академическим причинам), и мне сказали, что полукокс указателей и массивы это то же самое, что-то смущает меня.

Любая помощь очень ценится.

+2

Всегда всегда всегда компилируйтесь со всеми предупреждениями и не игнорируйте никаких предупреждений. Это само по себе должно предупредить вас о большинстве ваших ошибок. –

+2

Массив 'depes' to указатель на первый элемент, если вы опустите индекс. Если у вас есть 'char foo [10]' then 'foo == & foo [0]' –

+0

@Kerrek SB: Я скомпилировал свою программу, не получил никаких предупреждений, кроме тех, которые сказали мне, что моя программа не отвечает. Очевидно, потому что сам код неверен. –

ответ

2

Первой проблемой, которую я вижу в этом разделе:

if(str2 == '\0') 
    *strAux = '\0'; 

Как раз перед этим кодом, вы заполненная strAux строки из str1.
Затем, если str2 пуст, вы внезапно положили нуль-терминатор в начале strAux, исключив всю работу, которую вы сделали до сих пор!

Я думаю, что вы собираетесь это:

if(*str2 == '\0') 
    *(strAux+mover) = '\0'; 

Its то же самое еще раз после цикла для str2, у вас есть код:

strAux='\0'; 

Опять же, это ставит нуль-терминатор в начало strAux, эффективно заканчивая вновь созданную строку, прежде чем она даже начнется.


Вот как я бы переписать код:

void concatena(char *str1, char *str2){ 
    char *strAux; 
    int mover = 0; 

    strAux = (char *)(malloc(strlen(str1) + strlen(str2)+1)); // Changed to +1, NOT +2 
    *(strAux) = '\0'; // Start the string as (empty) 

    while(*str1 != '\0'){ // Copy the first string over. 
     *(strAux+mover++)=*(str1++); 
    } 

    while(*str2 != '\0'){ // Copy the second string over. 
     *(strAux+mover++)=*(str2++); 
    } 

    *(strAux+mover)='\0'; // End the new, combined string. 

    printf("%s", strAux); // Show the results. 
    free(strAux); 
} 
+0

Ничего себе, ты действительно сделал это просто, отличный ответ ... Я возвращаюсь к основам. Спасибо за вашу помощь. –

+1

Благодарим вас за то, что вы поставили меня более 10 000! :) – abelenky

+0

@abelenky: Поздравляем! Наслаждайтесь всеми новыми инструментами. – wallyk

0
strAux = (char *)(malloc(strlen(str1) + strlen(str2)+2)); 

не требуется, просто достаточно для символа завершения.

*(strAux) = '\0'; 

Это должно происходить только в конце всех ваших вычислений. Не между конкатенацией, т.е.,

while(*str1 != '\0'){ // This loops copies the first string 
    //^Notice that you need to dereference to check for the termination character. 
    *(strAux+mover++)=*(str1++); 
} 
while(*str2 != '\0'){ // This loop copies the second string 
    *(strAux+mover++)=*(str2++); 
} 
// Finally adding termination character 
*(strAux+mover) = '\0'; // since with mover you are keeping track of locations. 
0

Количество ошибок в коде Удручает. Вероятно, вы должны взять хорошую книгу C и начать все заново.

Во-первых, есть функция библиотеки, которую можно использовать для конкатенации строк:

const unsigned int len = strlen(str1) + strlen(str2) + 1; 
char * dst = malloc(len); 
strncat(dst, str1, len); 
strncat(dst, str2, len); 

Теперь, если вы настаиваете делать это вручную, вы должны получить указатели и разыменования право:

char * d = dst; 
while (*str1 != 0) *dst++ = *str1++; 
while (*str2 != 0) *dst++ = *str2++; 
*dst = 0; 
// d now points to the beginning of the concatenated string 

Две петли проверяют, является ли текущий символ во входной строке отличным от нуля, и если да, то они копируют этот символ в текущий символ в выходной строке, а затем курсор ввода и вывода продвигается.(Все это делается в одной стирке с использованием оператора postfix ++.) Наконец, последний символ установлен на ноль, чтобы создать новый нуль-терминатор.

В процессе мы модифицировали все три указателя dst, str1 и str2. Последние два вошли в качестве аргументов входной функции путем копирования, так что все в порядке. Для возврата конкатенированной строки мы сделали копию dst перед циклом, который мы можем вернуть в конце.

+0

Я думаю, что ОП было довольно ясно, что он не хотел использовать встроенные функции, но хотел написать свои собственные для обучения. Несмотря на то, что ваша версия чрезвычайно компактна, я не виню новичку за то, что у меня возникли проблемы после его написания, и хочу написать более явную, если более подробную версию. – abelenky

+3

Тот факт, что вы говорите кому-либо новому использовать 'strcat', а не' strncat', удручает. ;) –

+2

@Abelenky: Делать вещи вручную для понимания всегда хорошо, но разумное понимание указателей и разыменование является обязательным условием перед любой такой попыткой. Во всяком случае, я добавил некоторое объяснение кода - я думаю, что краткость действительно работает в пользу ясности в этом случае. Представьте себе, что я мог бы сказать 'while (* str1)' :-) –

1

Принимая те же ограничения, вот как я бы (переписал) ваш код. К сожалению, есть недостаток спецификации: должна ли конкатенация проходить до первой строки? Или нужно создать новую строку? Вот два метода:

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

char *concatena (const char *str1, const char *str2) 
{ 
     char *op, *newStr = (char*)malloc (strlen (str1) + strlen (str2) + 1); 
     if (!newStr) 
     { 
       fprintf (stderr, "concatena: error allocating\n"); 
       return; 
     } 

     op = newStr; // set up output pointer 
     while (str1 && *str1) // copy first string 
       *op++ = *str1++; 

     while (str2 && *str2) // concatenate second string 
       *op++ = *str2++; 

     *op = '\000';   // add conventional NUL termination 

     return newStr; 
} 


void concatenb (char *str1, const char *str2) 
{ 
     char *op; 
     if (!str1) 
     { 
       fprintf (stderr, "concatenb: NULL string 1\n"); 
       return; 
     } 

     op = &str1 [strlen (str1)];  // set output pointer at trailing NUL 

     while (str2 && *str2) // concatenate second string 
       *op++ = *str2++; 

     *op = '\000';   // add conventional NUL termination 
} 
Смежные вопросы