Loading...
agogo avatar agogo 12 Точки

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')

Благодаря!

1
C Programming 26/01/2016 16:22:02
fristgerb avatar fristgerb 50 Точки

Здрасти! :)

кога би предизвикало вероятна грешка

Винаги. Опита ли се поне веднъж да пуснеш кода, който си написал? :)

Програма ти се разваля при strcat (to[0], delim); понеже се опитваш да модифицираш низа "Plovdiv", но той не бива да се променя. Такива низове операционната система ги слага в памет, която е read-only за твоята програма. Когато се опитваш да пишеш по тази read-only памет, получава "Segmentation Fault" и процесът ти бива терминиран.

Паметта на стартираната програма изглежда така:

 

   Process Memory
+-------------------+
|stack:             |
|  char *to[2] = {  |
|    0x01, >--------+-----+
|    0x02, >--------+---+ |
|  };               |   | |
|                   |   | |
+-------------------+   | |
|heap:              |   | |
|                   |   | |
+-------------------+   | |
|read-only:         |   | |
|  "Plovdiv\0" <----+---+-+
|  "Sofia\0" <------+---+
|                   |
+-------------------+
5
26/01/2016 14:02:27
agogo avatar agogo 12 Точки

Извинявам се!

Неправилно съм показал примера, сега съм го редактирал!

Според http://www.delorie.com/djgpp/doc/libc-2.02/libc_640.html strcat връща указател.

Дали този указател не може да се използва по посочения начин.

Посочения пример работи, но дали е коректно и дали да се избягва?

1
26/01/2016 15:10:20
denka avatar denka 52 Точки

Здравей,

Указателя, който връща 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 програмката. Много е полезна и ти препоръчвам винаги да се тестваш кода с нея.

 

 

2
agogo avatar agogo 12 Точки

Здравейте и благодаря!

Ето целия код, където използвам въпросното присвояване http://tjelev.free.bg/work/zd6.c и макар той да сработва в DJGPP(FREEDOS) и GCC(LINUX), когато проверих с Valgrind се появиха грешките за които писахте.

Явно не може да се избегне malloc и calloc.

Искам да попитам има ли подобна програма на Valgrind и за FREEDOS - не успях да открия в Интернет!

Лека и спокойна!

 

1
26/01/2016 18:48:29
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.