Что не так с этим кодом? - PullRequest
       18

Что не так с этим кодом?

0 голосов
/ 14 сентября 2011

Как вы можете видеть ниже, я создал небольшую программу для конкатенации 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);
 }

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

Любая помощьс благодарностью.

Ответы [ 4 ]

2 голосов
/ 14 сентября 2011

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

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

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

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

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

Это то же самое снова после цикла для 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);
 }
1 голос
/ 14 сентября 2011

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

#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
}
0 голосов
/ 14 сентября 2011

Количество ошибок в вашем коде приводит в уныние. Вы, вероятно, должны взять хорошую книгу 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 голосов
/ 14 сентября 2011
strAux = (char *)(malloc(strlen(str1) + strlen(str2)+2));

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

*(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.
...