2010-07-02 3 views
0

Я сам выполнил функцию strcat(), но после добавления строки он печатает дополнительный символ ascii. Пожалуйста, скажите почему?strcat(); печать дополнительных символов

#include<stdio.h> 
    #include<conio.h> 
    #include<string.h> 
    void xstrcat(char string1[],char string2[]); 
    void main(void) 
{ char x[100]; 
    char string1[40],string2[40]; 
    printf("Enter a string:"); 
    gets(string1); 
    puts("Enter another string:"); 
    gets(string2); 
    xstrcat(string1,string2); 
    printf("%s",string1); 
    getch(); 
} 
    void xstrcat(char string1[],char string2[]) 
{ 
    int i,x,y; 
    x=strlen(string1); 
    y=strlen(string2); 
    for(i=0;i<y;i++) 
    { string1[i+x]=string2[i]; 
    }//for ends 
} 
+2

@fahad: в верхней части окна есть небольшая кнопка, где вы пишете свой вопрос, который выглядит как '101' \ n' 010'. Пожалуйста, используйте его в своем коде в будущем. Кажется, что каждый вопрос, который вы просите, должен быть переформатирован кем-то другим. – Cogwheel

+4

Tangential на ваш вопрос, но не используйте 'gets': http://stackoverflow.com/questions/2843073/warninggets-function-is-dangerous. Даже в собственной документации говорится, что не использовать его. –

+0

Может быть 'void main', он, как известно, провоцирует * неопределенное поведение *. Лучше переключитесь на правильный 'int main' в ближайшее время. –

ответ

4

Ваша xstrcat() функция не помещая нулевой терминатор символ в конце результирующей строки.

Одним из возможных решений может быть поставить следующий раз, прежде чем функция xstrcat() возвращает:

string1[x+y] = '\0'; 
+0

Я не добавляю \ 0 сам, потому что мой учитель сказал мне, что он добавлен в его дополнение, вам не нужно его добавлять. Любое предложение для этого? Я сделал, как вы сказали, теперь программа отлично работает :) –

+0

Добавил себя при выполнении чего? Строковый литерал в C автоматически включает 0 завершение, а функции библиотеки, такие как strcpy, strcat и т. Д., Будут писать 0 байт. Но здесь вы сами манипулируете байтом для байта памяти. Как язык может изменить следующий байт на 0, не будучи ужасно неправильным в общем случае? –

2

В C, строки оканчиваются байт NUL (символ со значением 0). strlen расскажет вам, сколько символов есть от начала строки до NUL-байта, не считая самого байта NUL.

Итак, когда вы выполняете эту петлю:

for(i=0;i<y;i++) 
    { string1[i+x]=string2[i]; 
    } 

Вы никогда не копировать завершающий NUL байт из string2 в string1 и так string1 больше не имеет завершения NUL (вы перезаписали его NUL в начале цикла с первый символ string2). Когда строка пропускает свой завершающий NUL, функции, которые ее читают (например, printf), продолжат чтение за конечной точкой строки, пока они, в конце концов, не найдут нулевой байт где-то еще в памяти. Это может привести к печати дополнительных символов и/или сбою.

Либо изменение y к y+1 или явно вставить '\0' в положении x+y в string1.

+1

... или изменить '<' на '<=' – caf

1
void xstrcat(char string1[],char string2[]) 
{ 
    //int i,x,y; 
    size_t i, x, y; 
    // They could also be unsigned, but size_t is an unsigned big enough to hold the 
    // biggest in memory index possible 

    x=strlen(string1); 
    y=strlen(string2); 

    //for(i=0;i<y;i++) 
    for (i=0; i<=y; i++) // This picks up the null at the end 
    { string1[i+x]=string2[i]; 
    }//for ends 
} 

В качестве альтернативы вы могли бы сделать это так:

void xstrcat(char * string1, const char * string2) 
{ 
    while(*string1) { 
     string1++; 
    } 
    strcpy(string1, string2); 
} 

Это должно быть немного быстрее, потому что он не должен проходить либо строку, но один раз. Он также не требует столько дополнительных переменных.

+0

Ваша альтернативная версия не лучше; ни одна версия не чередуется ни одной строки более одного раза. Другая альтернативная версия - это просто 'strcpy (string1 + = strlen (string1), string2);' но я думаю, что суть вопроса заключалась в том, как реализовать strcat с нуля, а не на основе других функций библиотеки. –

+0

@R: strlen пересекает строку для подсчета символов, а для копирования строки требуется обход. Первая версия прошла через строку 2 один раз для длины и один раз для копирования и string1 только один раз для длины, тогда как вторая только пройденная строка1 для длины (через ее поиск) и string2 проходила только один раз, когда были выполнены как длина, так и копирование (как долго поскольку strcpy была реализована как копия до нуля). – nategoose

0

ваш цикл

for (i = 0; i < y; i++) { 
    string1[i+x]=string2[i]; 
} 

вы читаете строку 2 до его длины-1, которая будет читать только ДО последнего символа до NULL, если вы не знаете, в С или С строк ++ оканчиваются с NULL (0).

Таким образом, ваша строка1 не будет иметь символа NULL в конце.

Итак, теперь, когда вы пытаетесь напечатать свою строку1, в конце концов она обязательно напечатает несколько символов, поскольку ваша строка имеет размер 40, эти символы - мусор.

В основном вы получите натянуть 40 символов печатается за исключением только тогда, когда на этих значений мусора является 0.

Таким образом, вы должны прочитать вторую строку Шифрование до 0, так что ваш цикл

for (i = 0; i <= y; i++) 

или вы можете просто добавить символ NULL в конце строки 1 после добавления в него строки2.

string1[x+y] = 0; 
Смежные вопросы