Интервью Вопрос-Конкатенация двух строк без использования strcat в C - PullRequest
6 голосов
/ 26 сентября 2010

Недавно я посетил интервью, где меня попросили написать C-программу для объединения двух строк без использования strcat(), strlen() и strcmp(), и эта функция не должна превышать две (2) строки.

Я знаю, как объединить две строки без использования strcat(). Но мой метод имеет почти 15 строк. Я не знаю, как написать это в две строки.

Ответы [ 10 ]

20 голосов
/ 26 сентября 2010

Я ожидаю, что они хотели что-то вроде этого:

void mystrcat(char * dest, const char * src)
{
    //advance dest until we find the terminating null
    while (*dest) ++dest;

    //copy src to dest including terminating null, until we hit the end of src
    //Edit: originally this: 
    //for (; *dest = *src, *src; ++dest, ++src);
    //...which is the same as this
    for (; *dest = *src; ++dest, ++src);
}

Он не возвращает конец объединенной строки, как настоящий strcat, но это не требуется.

Я не обязательно знаю, является ли такая вещь хорошим вопросом для собеседования - это показывает, что вы можете кратко писать код и что вы знаете, что делает strcat, но это все.

Редактировать: как пишет aib, заявление

while (*dest++ = *src++);

... возможно, является более обычным способом написания второго цикла (вместо использования for).

17 голосов
/ 26 сентября 2010

Учитывая, что задача состояла в том, чтобы объединить две строки, а не создавать дубликат strcat, я бы выбрал простой вариант создания совершенно новой строки, которая является комбинацией этих двух.

char buffer[REASONABLE_MAX] = {0};
snprintf(buffer, REASONABLE_MAX - 1, "%s%s", string1, string2);
6 голосов
/ 26 сентября 2010

Правильный ответ на этот вопрос заключается в том, что этот вопрос продемонстрирует навык, которым плохо обладать.Они хотят, чтобы вы продемонстрировали способность писать хакерский код.Они хотят, чтобы вы изобрели собственную реализацию вещей, предоставляемых уже каждым компилятором C, что является пустой тратой времени.Они хотят, чтобы вы написали оптимизированный код, который по определению не читается.Реализация в 15 строк, вероятно, будет лучше, если она будет более читабельной.Большинство проектов не терпят неудачу, потому что разработчики потратили 150 тактов.Некоторые терпят неудачу, потому что кто-то написал не поддерживаемый код.Если бы вам пришлось написать это, вам понадобится 15-строчный комментарий.Таким образом, мой ответ на этот вопрос будет таким: покажите мне показатели производительности, которые защищают от необходимости не использовать стандартные библиотеки и требующие наиболее оптимального решения.Намного лучше потратить время на разработку и сбор этих показателей производительности.

Никогда не забывайте - вы также проводите собеседование с ними.

 //assuming szA contains "first string" and szB contains "second string"
 //and both are null terminated
 //  iterate over A until you get to null, then iterate over B and add to the end of A
 //  and then add null termination to A
 //  WARNING:  memory corruption likely if either string is not NULL terminated
 //  WARNING:  memory corruption likely if the storage buffer for A was not allocated large
 //            enough for A to store all of B's data
 //  Justification:  Performance metric XXX has shown this optimization is needed
 for(int i=0; szA[i]!='\0'; i++); 
 for(int j=0; (j==0)||(szB[j-1]!='\0'); j++) szA[i+j] = szB[j];

* edit, 9/27/2010

После прочтения некоторых других решений этой проблемы, я думаю, что следующий ответ, вероятно, является лучшим ответом на код:

 //Posted by Doug in answer below this one
 void my_strcat(char * dest, const char * src)
 {    
      while (*dest) ++dest;    
      while (*dest++ = *src++);     
 }

Но я хотел бы дополнить его безопасной версией:

 void my_safe_strcat(char * dest, const unsigned int max_size, const char * src)
 {
      int characters_used=0;
      while (*dest) { ++dest; characters_used++; }
      while ( (characters_used < (max_size-1) ) && (*dest++ = *src++) ) characters_used++;
      *dest = 0; //ensure we end with a null
 }

И добавьте (полный ответ, какой компилятор будет оптимизирован так, как указано выше, вместе с приложением, которое было реальным вопросом):

void my_readable_safe_strcat(char * dest, const unsigned int max_size, const char * src)
{
    unsigned int characters_used = 0;
    while (*dest != '\0') 
    { 
        ++dest; 
        characters_used++;   
    }
    while ( (characters_used < (max_size-1) ) && (*dest = *src) ) 
    {
        dest++;
        src++;
        characters_used++;
    }
    *dest = 0; //ensure we end with a null
}



int _tmain(int argc, _TCHAR* argv[])
{
    char szTooShort[15] = "First String";
    char szLongEnough[50] = "First String";
    char szClean[] = "Second String";
    char szDirty[5] = {'f','g','h','i','j'};

    my_readable_safe_strcat(szTooShort,15,szClean);
    printf("This string should be cut off:\n%s\n\n",szTooShort);

    my_readable_safe_strcat(szLongEnough,50,szClean);
    printf("This string should be complete:\n%s\n\n",szLongEnough);

    my_readable_safe_strcat(szLongEnough,50,szDirty);
    printf("This string probably has junk data in it, but shouldn't crash the app:\n%s\n\n",szLongEnough);

}
5 голосов
/ 27 сентября 2010

Две строки?Вау ...

void another_strcat(char* str1, const char* str2)
{
    strcpy(strchr(str1, '\0'), str2);
}

РЕДАКТИРОВАТЬ: Я очень расстроен, что люди так против strcpy и strchr.Waah!Итак, я думал, что я буду играть в духе правил:

char thing(char* p, const char* s)
{
    return *p ? thing(&p[1], s) : *s ? (*p++ = *s++, thing(p, s)) : *p = '\0';
}

Я до сих пор не могу понять, как кто-то взял бы 2 целые строки; -P.

3 голосов
/ 28 сентября 2010

Я проверял этот бит в VS2008, и он работал нормально.

void NewStrCat(char* dest, const char* src)
{
    while (*dest) ++dest;
    while (*dest++ = *src++);
}
2 голосов
/ 26 сентября 2010

Любая функция может быть помещена в одну строку, просто удалив все \n.

Однако, я думаю, вы ищете этот ответ:

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

int main(void)
{
    char string1[32] = "Hello";
    char string2[] = ", World!";

    char *dst = string1 + strlen(string1);
    char *src = string2;

    while (*dst++ = *src++); //single statement

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

    return EXIT_SUCCESS;
}

Объяснение довольно простое:

src++ возвращает указатель на текущий символ, который копируется перед увеличением, чтобы указать на следующий.* разыменовывает этот указатель, и аналогичное выражение на LHS копирует его в dst.Результатом всего выражения = является скопированный символ, поэтому простой while повторяет его до тех пор, пока не встретится и не скопируется \0.

Однако:

strcat()легче читать и, возможно, гораздо быстрее.Любое другое решение возможно только тогда, когда strcat() недоступно.(Или, очевидно, когда вы на собеседовании.) И замените strcat() выше на strncat(), если вы действительно не уверены, что строка назначения достаточно велика.

Редактировать: Я пропустил часть оstrlen() запрещено.Вот функция двух операторов:

void my_strcat(char * restrict dst, const char * restrict src)
{
    while (*dst) ++dst;      //move dst to the end of the string
    while (*dst++ = *src++); //copy src to dst
}

Обратите внимание, что стандартная функция strcat() возвращает исходное значение dst.

1 голос
/ 28 сентября 2010

Одна строка:

sprintf(string1, "%s%s", string1, string2);

(обратите внимание, что это может вызвать неопределенное поведение.)

Добавление

Стандарт ISO C99 гласиттот: Если копирование происходит между объектами, которые перекрываются, поведение не определено.

При этом, приведенный выше код, вероятно, все еще будет работать правильно.Работает с MS VC 2010.

0 голосов
/ 16 января 2016
void my_strcat(char* dest, const char* src)
{
    while (*dest) ++dest;
    while (*dest++ = *src++);
    *dest = '\0';
}

Строка назначения должна заканчиваться символом NULL.

0 голосов
/ 28 сентября 2010

У меня такое чувство, что такие вопросы предназначены для исключения, а не для отбора. Для них легче отбирать кандидатов на основе таких запутанных вопросов, чем отбирать кандидатов, задавая им более реальные вопросы. Просто напыщенная речь от меня, так как я также ищу работу и сталкиваюсь с такими вопросами и ответил на довольно многие из них благодаря SO!

0 голосов
/ 28 сентября 2010
void StringCatenation(char *str1,char *str2)
        {
          int len1,i=0;
          for(len1=0;*(str1+len1);len1++);
          do{
            str1[len1+i]=str2[i];
            i++;
            }
            while(*(str2+i);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...