C programming: Възможно ли е?
Здравейте!
Искам да ви запитам дали следното присвояване е коректно и кога би предизвикало вероятна грешка:
// Това е една от примерните задачи в курса:
// Да се съединят всички низове в масива, разделени чрез даден символ.
int main()
{
char *delim = ", ";
char *to[10] = { "Plovdiv","Sofia" ..., " "};
char *result = join(to,length,delim);
.......
}
char * join(char *to[], site_t size,char *delim)
{
char *p = strcat(to[0],delim);
........
return p;
}
// Идеята ми тук, е да се избегне предварително използване на malloc или calloc, а директно да се използва първия низ от масива.
// В случая примерът сработва!
// Според описанието на strcat, се връща указател към низ. Но дали по посочения начин се работи с копие на този низ (понеже се предава // на функция ) или не! Искам да попитам това не е ли явно задаване на низ от тип char *p = string; (може би без '\0')
Благодаря!
Извинявам се!
Неправилно съм показал примера, сега съм го редактирал!
Според http://www.delorie.com/djgpp/doc/libc-2.02/libc_640.html strcat връща указател.
Дали този указател не може да се използва по посочения начин.
Посочения пример работи, но дали е коректно и дали да се избягва?
Здравей,
Указателя, който връща strcat сочи към първия елемент на първия параметър на strcat. Т.е.
char * ptr = strcat(str1, str2);
Тук ptr и str сочат на едно и също място в паметта. - Функцията не събира str1 и str2 в ptr, а добавя str2 в края на str1.
Дали може да го върнеш като резултат от функция или не зависи от това къде е паметта на str1 - ако е в heap-a няма проблем, но ако е в стека ще се замаже при излизане от функцията:
char * test1() {
char * str1 = malloc(200);
......
return strcat(str1, str2); } е ОК,
но
char * test1() {
char str1[200];
......
return strcat(str1, str2); } не е ОК
Иначе за самия код който си написал, наистина няма как да работи, защото както ти е казал колегата, to[0] е в read only паметта, а strcat се опитва да го модифицира.
Също така имай впредвид, че в str1 трябва да има достатъчно памет за конкатинацията. Тоест ако в примера който съм написала се опитам да конкатинирам стрингове с размери 100 и 150 ще има проблем, защото паметта на str1 е само 200.
В някоя от лекциите бяха казали за valgrind програмката. Много е полезна и ти препоръчвам винаги да се тестваш кода с нея.
Здравейте и благодаря!
Ето целия код, където използвам въпросното присвояване http://tjelev.free.bg/work/zd6.c и макар той да сработва в DJGPP(FREEDOS) и GCC(LINUX), когато проверих с Valgrind се появиха грешките за които писахте.
Явно не може да се избегне malloc и calloc.
Искам да попитам има ли подобна програма на Valgrind и за FREEDOS - не успях да открия в Интернет!
Лека и спокойна!
На практика е същото като предишния код. Проблемът е същия.
Кодът http://tjelev.free.bg/work/zd6.c е доста труден за четене, но изглежда при него се ползва calloc за заделяне на място за съединените низовете и го няма проблема с read-only паметта.
Може Valgrind да има добра причина да се оплаква при този код, но може причината и да не е добра. Макар и някои хора да биха оспорили, част от грешките, които Valgrind дава не са истински грешки. Може би е полезен в някои ситуации, но не може да се разчита сляпо на него, без да се осмисли какво всъщност се случва.
Примерно, Valgrind ще се оплаче, ако не направим
free()
на всичко преди спирането на програмата. Да не се прави <code>free()</code> в края на програмта не е грешка, а по-скоро обратното е грешка. Тази грешка е допусната и в примера, който си дал:Това са абсолютно излишни процесорни операции, които само бавят завършването на програмата и усложняват кода.
Здравей!
Ако е възможно да ми напишеш, защо кодът е труден за четене !
Това е важно за мен! Би ли нахвърлял някои препоръки?
Благодаря, предварително!
Труден ми е да го разбера понеже не се разбира по имената на променливите и на функциите за какво служат те.
Примерно, ако погледна
main
функцията, не знам за какво саbuffer
,str
,token
,np
,i
, нитоsend()
. За да разбера е нужно да проследя цялата логика на кода, влючително това, което се случва и в другите функции.Нека погледнем реда
char *str = getstr (...);
. Името "str
" не ми дава никаква информация. Аз знам, че тези променлива е низ, понеже еchar *
. Много по-полезно щеше да е, ако се казва примерноuser_input
или още по-добреcity_names_input
, ако целта на програмата е да прави нещо конкретно. Но аз и не знам каква е целта на програмата."
np
" дори и като съкращение не знам какво означава, а "size_t i
" е като абсолютно произволна буква без значение.Добре е да се сложи поне едно изречение относно каква е целта на програмата, понеже без някакъв контекст е много пъти по-трудно да се разбере какво се случва в кода. Може да го сложиш най-отгоре във файла. Примерно:
Да, наистина е така!
Прав си във всяко едно отношение, ще имам предвид всичко, което си написал!
Благодаря за отделеното време!