Функция копированя строк
Чем отличается этот код:
void copy(char* to, char* from){
int i;
i = 0;
while((to[i] = from[i]) != '\0')
i++;
}
от этого:
void copy(char* to, char* from){
int i;
for(i = 0; from[i] != '\0'; i++)
to[i] = from[i];
}
Потому что работают они по-разному. Когда я использую второй вариант функции copy, то по нахождению максимальной строки (у которой размер больше предыдущей) -- мне поток вывода выводит самую длинную по размеру строку , но при этом, в конце также пишется мусор. Напротив же, когда использую второй вариант, то никакого мусора не наблюдается, то есть работает все корректно (если мои введенные строки в поток ввода верны по отношению тестирования). Так в чем же дело. Дайте знать, пожалуйста.
Если что, вот полный код по нахождению максимальной длинной строки в потоке (с первым вариантом функции копирования):
#include <stdio.h>
#define MAXLINE 1000
int getline(char* str, int max){
int c, i;
for(i = 0; i < max - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
str[i] = c;
if(c == '\n'){
str[i] = c;
i++;
}
str[i] = '\0';
return i;
}
void copy(char* to, char* from){
int i;
i = 0;
while((to[i] = from[i]) != '\0')
i++;
}
int main(void)
{
int size;
int max = 0;
char in[MAXLINE];
char from[MAXLINE];
while((size = getline(from, MAXLINE)) > 0)
if(size > max){
max = size;
copy(in, from);
}
if(max > 0)
printf("%s",in);
return 0;
}
Ответы (3 шт):
Кажется, что всё-таки цикл с while работает корректней, а второй - с мусором. Причина в том, что в while последний '\0' перекладывается в массив до проверки, а во втором случае при нахождении нуля происходит выход из цикла без перекладывания. Итог - строка не содержит конца.
Можно исправить так:
void copy(char* to, char* from){
int i;
for(i = 0; (to[i] = from[i]) != '\0'; i++);
}
А я бы ещё для надёжности добавил перед выводом in[MAXLINE-1]=0;
Это исключит вероятность доступа к невыделенной памяти.
Строка - это не только текст, но и завершающий нулевой символ. Который тоже надо копировать.
Короче всего так, без всяких индексов:
void copy(char* to, char* from)
{
while(*to++ = *from++);
}
Ну, или, что то же самое,
void copy(char* to, char* from)
{
for(;*to++ = *from++;);
}
Первый код
void copy(char* to, char* from){
int i;
i = 0;
while((to[i] = from[i]) != '\0')
i++;
}
Заменяем равносильным кодом по правилу
while (C) B; → while (true) { if (!(C)) break; B; }:
void copy(char* to, char* from){
int i;
i = 0;
while(true) {
if(!((to[i] = from[i]) != '\0'))
break;
i++;
}
}
Присвоение внутри if выносим перед ним:
void copy(char* to, char* from){
int i;
i = 0;
while(true) {
to[i] = from[i];
if(!(from[i] != '\0'))
break;
i++;
}
}
Второй код
void copy(char* to, char* from){
int i;
for(i = 0; from[i] != '\0'; i++)
to[i] = from[i];
}
Первое выражение из for выносится перед ним, третье выражение в конец цикла:
void copy(char* to, char* from){
int i;
i = 0;
for(; from[i] != '\0';) {
to[i] = from[i];
i++;
}
}
for без первого и третьего выражений равносилен while:
void copy(char* to, char* from){
int i;
i = 0;
while(from[i] != '\0') {
to[i] = from[i];
i++;
}
}
while разбираем в конструкцию while/if, как раньше:
void copy(char* to, char* from){
int i;
i = 0;
while(true) {
if(!(from[i] != '\0'))
break;
to[i] = from[i];
i++;
}
}
Сравнение
Теперь два кода можно сравнить бок о бок. И видно что условие выхода из цикла и копирование символа поменялись местами:
| Первый код | Второй код |
|---|---|
|
|
| Копирует все символы строки и завершающий '\0'. |
Копирует все символы строки без завершающего '\0'. |
Правка
Поправить второй код можно так:
void copy(char* to, char* from){
int i;
for(i = 0; from[i] != '\0'; i++)
to[i] = from[i];
to[i] = '\0'; // дописываем забытый ноль
}