Функция, которая объединяет две строки указателя - PullRequest
0 голосов
/ 27 ноября 2018

У меня возникают проблемы при объединении этих двух строк указателей, ниже приведена моя функция объединения, я должен взять строку 1 и добавить ее в строку 2. Также я не могу использовать какие-либо функции в библиотеке строк, этосмысл в том, чтобы помочь нам понять, что код на самом деле в функциях, написав его самостоятельно.

char strconcat(char *user2p, char *user1p) {
    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        *user2p++;
        *user1p++;
    }
    *user2p = '\0';

    printf("test: %c", *user2p);

    return *user2p;
}

И вот часть моего основного, которая имеет отношение к функции.

int main() {
    char userString1[21], userString2[21];
    char *user1p, *user2p;

    user1p = userString1;
    user2p = userString2;

    printf("Please enter the first string: ");
    gets(userString1);

    printf("Please enter the second string: ");
    gets(userString2);

    printf("String 1 after concatenation: ");
    puts(userString1);
    printf("String 2 after concatenation: %c\n", strconcat(user2p, user1p));

Терминал продолжает давать мне это, я не включил код для длиныи в алфавитном порядке.Это дает мне нулевое значение, когда я пытаюсь запустить тест printf в функции, и ничего не дает, когда я возвращаю функцию.Я в растерянности, и любая помощь очень ценится!

 Please enter the first string: jackhammer
 Please enter the second string: jacky
 The length of string 1 is: 10
 The length of string 2 is: 5
 String 1 comes before string 2 alphabetically.
 String 1 after concatenation: jackhammer
 (null)
 String 2 after concatenation:

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Есть ряд вопросов.Во-первых, это.

while (*user1p) {
    *user2p = *user1p;
    *user2p++;
    *user1p++;
}

Это работает случайно.Если у вас есть предупреждения компилятора, вы должны получить предупреждение ...

test.c:13:9: warning: expression result unused [-Wunused-value]
        *user2p++;
        ^~~~~
test.c:14:9: warning: expression result unused [-Wunused-value]
        *user1p++;
        ^~~~~~~

Причина, по которой он не используется, заключается в том, что C интерпретирует его так:

*(user1p++)

Увеличьте указатель, затемразыменовывать это.Вы просто хотите увеличивать указатели, разыменование не требуется.

while (*user1p) {
    *user2p = *user1p;
    user2p++;
    user1p++;
}

Затем здесь.

printf("String 2 after concatenation: %c\n", strconcat(user2p, user1p));

%c печатает человека char.Вы хотите %s, который печатает char *.Это показывает, что у вас неправильная подпись.strconcat должен вернуть char * (то есть то, что C использует для строк) и вернуть user2p (char *).

char *strconcat(char *orig_to, const char *from) {
    ...

    return user2p;
}

И так как вы не меняете from, то этодолжно быть const char *, чтобы сообщить компилятору и предупредить вас, если он случайно изменился.


Наконец, когда вы возвращаете *user2p, он уже перемещен в конец строки.

while (*user1p) {
    *user2p = *user1p;
    user2p++;
    user1p++;
}
*user2p = '\0';

printf("test: %c", *user2p);

// This points to the null byte just set above
return user2p;

Таким образом, печать результата strconcat ничего не напечатает.Чтобы обойти это, сохраните исходный указатель для user2p и верните его.

char *strconcat(char *orig_to, const char *from) {
    char *orig_user2p = user2p;

    ...

    return orig_user2p;
}

И некоторые советы.Проще следовать коду с хорошими именами переменных, которые описывают то, что они делают.

char *strconcat(char *orig_to, const char *from) {
    char *to = orig_to;
    ...
}

char foo[NN] уже делает foo указателем.Нет необходимости объявлять отдельные переменные char * и копировать указатель.

char from[21], to[21];

Никогда не используйте gets.Нет предела тому, сколько памяти он может использовать, и он может легко переполнить ваш буфер.Используйте fgets, который может ограничить объем считываемой информации в доступной памяти.

printf("Please enter the string to concat from: ");
fgets(from, sizeof(from), stdin);

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

printf("Please enter the string to concat from: ");
scanf("%20s", from);

printf("Please enter the string to concat to: ");
scanf("%20s", to);

Наконец, убедитесь, что строка, к которой вы объединяетесь, может содержать свое собственное содержимое иновое содержание.

char from[21], to[41];

printf("Please enter the string to concat to: ");
// Be sure to leave enough room in `to` to fit `from`.
fgets(to, sizeof(to) - sizeof(from), stdin);
0 голосов
/ 27 ноября 2018

Я бы создал более динамическую модель памяти.Этот код является более общим и объединяет строки, создавая новую строку, содержащую обе строки. Бесплатно, когда закончите: -) ...

char *strconcat(char *string1, char *string2) {
    int lenStr1=0,lenStr2=0;
    char *tmpStr1=string1,*tmpStr2=string2,*returnStr;
    while (*tmpStr1++)lenStr1++;
    while (*tmpStr2++)lenStr2++;
    if((returnStr=(char *)malloc(lenStr1+lenStr2+1))){
        memcpy(returnStr,string1,lenStr1);
        memcpy(&returnStr[lenStr1],string2,lenStr2);
        returnStr[lenStr1+lenStr2]=0;
        return returnStr;
    } else {
        return 0;
    }
}

int main() {
    char *string1="String 1 ",*string2="String 2 ",*result;
    if((result=strconcat(string1, string2))) {
        printf("-> %s \n",result);
        free(result);
    } else {
        printf("Out of memory");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
0 голосов
/ 27 ноября 2018

Ваш алгоритм concat в порядке, но вы должны вернуть указатель на оригинальное [крайнее левое] значение, поэтому ваша функция должна сохранить его перед циклом:

char *
strconcat(char *user2p, char *user1p)
{
    char *orig2p = user2p;

    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        user2p++;
        user1p++;
    }
    *user2p = '\0';

    printf("test: %s\n", orig2p);

    return orig2p;
}

ОБНОВЛЕНИЕ:

Чтобы создать полностью пуленепробиваемую программу тестирования для функции concat, мы можем использовать [чрезмерно] большие входные буферы и обрезать входную длинумаксимум до 1/2 целевого буфера.

gets удаляет перевод строки, но fgets делает не .Итак, я создал функцию xgets, которая похожа на gets, но использует fgets и strchr, чтобы получить [почти] тот же эффект.

Хотя я считаю, что можно использовать стандартныеСтроковые функции как часть кода test , я создал версию strchr, написанную от руки [надеюсь, это не ваше следующее назначение: -)].

В любом случае, вот полныйпрограмма:

#include <stdio.h>

char *
strconcat(char *user2p, char *user1p)
{
    char *orig2p = user2p;

    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        *user2p++;
        *user1p++;
    }
    *user2p = '\0';

    printf("test: %s\n", orig2p);

    return orig2p;
}

char *
xstrchr(char *buf,int chrwant)
{
    int chrcur;
    char *res = NULL;

    for (chrcur = *buf++;  chrcur != 0;  chrcur = *buf++) {
        if (chrcur == chrwant) {
            res = buf - 1;
            break;
        }
    }

    return res;
}

char *
xgets(char *buf,int maxlen)
{
    char *cp;
    char *res;

    res = fgets(buf,maxlen,stdin);

    if (res != NULL) {
        cp = xstrchr(buf,'\n');
        if (cp != NULL)
            *cp = 0;
    }

    return res;
}

#define MAXLEN      800

int
main(void)
{
    char userString1[MAXLEN], userString2[MAXLEN + 1];
    char *user1p, *user2p;

    printf("Please enter the first string: ");
    user1p = xgets(userString1,MAXLEN / 2);

    printf("Please enter the second string: ");
    user2p = xgets(userString2,MAXLEN / 2);

    if ((user2p != NULL) && (user1p != NULL))
        printf("String 2 after concatenation: %s\n",strconcat(user2p, user1p));

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...