LINUX.ORG.RU

[C++]strcoll, strcpy - копирование и сравнение строк.

 


0

1

В общем задали задачу. Вроде бы легко, но вот застряла программа в раёне условия (оно здесь одно), выводит пустоту :( Подскажите в чём ошибся :)

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



int main(int argc, char **argv)
{
	typedef char byte;
	char str[7];
	char tmp[7];
	char res[36][7];
	int x;
	byte cnt;
	const byte d [] = {	1, 2, 3,
						1, 3, 2,
						2, 1, 3,
						2, 3, 1,
						3, 1, 2,
						3, 2, 1 };
	
	const byte l [] = {	0, 4, 5,
						0, 5, 4,
						4, 0, 5,
						4, 5, 0,
						5, 0, 4,
						5, 4, 0 };
	FILE *fi, *fo;
	fi = fopen("input.txt", "r");
	fo = fopen("output.txt", "w");
	fscanf(fi, "%s", str);
	for(int i=0; i<6; i++)
		for(int j=0; j<6; j++)
		{
			tmp[0] = str[l[3*i]];
			tmp[1] = str[d[3*j]];
			tmp[2] = str[d[3*j+1]];
			tmp[3] = str[d[3*j+2]];
			tmp[4] = str[l[3*i+1]];
			tmp[5] = str[l[3*i+2]];
			tmp[6] = '\0';
			//fprintf(fo, "%s %s", tmp, "\n");
			for(int k=0; k<cnt; k++)
				if( strcoll(tmp, (const char *)&res[]) || cnt == 0)
				{
					strcpy((char *)&res[cnt], (const char *)&tmp);
					cnt++;
				}
		}
	
	for(int i=0; i<cnt; i++)
		fprintf(fo, "%s %s", res[i], "\n");
	fclose(fi);
	fclose(fo);
	return 0;
}



Последнее исправление: NaViKotE (всего исправлений: 1)

s/C++/C/

Т.е. это - не плюсы.

застряла программа в раёне условия

Где?

И нафига использовать strcoll для сравнения цифр? И кто будет заполнять res? И почему второй аргумент strcoll - адрес массива строк, а не строка?

Eddy_Em ☆☆☆☆☆
()

Навскидку так:

<code> if( strcoll(tmp, (const char *)&res[????]) || cnt == 0) { strcpy((char *)&res[cnt], (const char *)&tmp); cnt++; } </code>

а то ты 1мерный массив с 2хмерным сравниваешь, кроме этого у тебя не инициализирована cnt

Rubbiroid
()
Ответ на: комментарий от Eddy_Em

Где?

if( strcoll(tmp, (const char *)&res[k]) || cnt == 0)
            {
               strcpy((char *)&res[cnt], (const char *)&tmp);
               cnt++;
            }

И нафига использовать strcoll для сравнения цифр?

Где цифры? В массивах буквы из файла.

И кто будет заполнять res?

Цикл. каждый раз tmp, при отличии от других res будет копироваться туда.

И почему второй аргумент strcoll - адрес массива строк, а не строка?

Да это ошибка, но исправив её на res[k] толку больше не стало.

NaViKotE
() автор топика
Ответ на: комментарий от NaViKotE

Где цифры? В массивах буквы из файла.

А, точно. Ну вы, батенька, и извращенец... :)

каждый раз tmp, при отличии от других res будет копироваться туда.

А первый раз сравниваем с неинициализированным массивом :)

исправив её на res[k] толку больше не стало.

Амперсанд тоже убрать надо: strcoll(tmp, res[k])

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Reset

Хм, почитал - действительно, strlcpy удобнее, т.к. после нее не приходится самому записывать в конец буфера ноль или делать буфер на 1 символ больше, чем n в аргументе...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Reset

Да ладно, меня не напрягает вот так делать:

char *buf = calloc(BUFSIZ+1, 1);
...
strncpy(buf, src, BUFSIZ);
В конце buf всегда гарантированно будет 0 =)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Reset

А если буфер статический?

Стараюсь такого не допускать никогда. Либо сразу выделяю буфер на 1 символ больше, чем надо, и заполняю нулями.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Стараюсь такого не допускать никогда.

Всмысле? malloc и new это второе матерное слово в программировании на Си и Си++. Поэтому всегда когда можно надо создавать объекты на стеке. В Си это не всегда удается, а в Си++ это возможно в 99.99% случаев.

Reset ★★★★★
()
Ответ на: комментарий от Reset

А по мне, так лучше malloc'ом буфер нужного размера выделить, чем загадывать заранее, какой же размер понадобится...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

malloc во-первых это медленно, а во-вторых это потенциальные утечки.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Кстати, можно вообще свой strcpy написать, с гимназистками и преферансом: на основе memcpy, memmove, calloc и realloc. Чтобы не париться о размерах выделяемого буфера.

Ну, а чтобы иметь представление о том, сколько выделено для конкретного указателя, сделать свои обертки к malloc/calloc и free :)

Я уже о таком задумывался. Все достаточно просто: делаем структуру

struct membuf{
int64_t len;
void *buf;
};
malloc заменяем на
void *_malloc(int64_t size){
struct membuf *a = malloc(size + sizeof(struct membuf));
if(!a) return null;
a->len = size;
a->buf = a + sizeof(struct membuf);
return a.buf;
}
Ну, а free заменяем на
void _free(void *ptr){
struct membuf *a = ptr - sizeof(struct membuf);
free(a);
}
Ну и всяких доп. плюшек можно понадобавлять, в т.ч. функции для определения размера выделенной области.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Во-первых это костыли, а во-вторых это не решает по сути проблему. В Си нет деструкторов, поэтому проблема разрешима только если есть возможно выделить всю память на старте программы, а в процессе работы дополнительно выделять на стеке.

Reset ★★★★★
()

> но вот застряла программа в раёне условия

в раёне

раёне


раёне


раёне



Российская академия естественных наук?

drull ★☆☆☆
()

раЙОн.

Я не понял что нужно.
увидев

         tmp[0] = str[l[3*i]];
         tmp[1] = str[d[3*j]];
         tmp[2] = str[d[3*j+1]];
         tmp[3] = str[d[3*j+2]];
         tmp[4] = str[l[3*i+1]];
         tmp[5] = str[l[3*i+2]];
         tmp[6] = '\0';
желание вникать отпало

Tanger ★★★★★
()
Ответ на: комментарий от Eddy_Em

Зачем эта билеберда со структурой? В своем маллоке выделяй size+sizeof(int64) и возвращай указатель на этот буфер с учетом смещения под int64. Но лучше сделать size_t. А еще лучше так вообще не делать :)

staseg ★★★★★
()
Ответ на: комментарий от staseg

Нельзя так делать: буфер может быть поврежден пользователем и вместо сегфолта сразу он получит непонятно что когда-нибудь потом

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

В каких-то компиляторах при каких-то опциях оптимизации это может не сработать. И самое офигенное, что мы не знаем, каких.

Yareg ★★★
()
Ответ на: комментарий от Eddy_Em

Ты абсолютно уверен, что в gcc это будет работать всегда? Ну не знаю, я просто как узнал о strict aliasing, так теперь паранойю по этому поводу.

Yareg ★★★
()
Ответ на: комментарий от Yareg

А я о «strict aliasing» понятия не имею - и не парюсь. Работает - и отлично! =)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

>Нельзя так делать: буфер может быть поврежден пользователем и вместо сегфолта сразу он получит непонятно что когда-нибудь потом

Не вижу разницы. В своей структуре ты хранишь указатель на буфер памяти прямо за структурой. При маллоке ты его возвращаешь, больше нигде не используешь. Так какой смысл его хранить?

staseg ★★★★★
()
Ответ на: комментарий от staseg

Я же не привел других функций: strcpy/memcpy с автопроверкой длины буфера; да и просто функцию для определения размера выделенной памяти...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от staseg

Тьфу. Дошло. Действительно, проще так:

void *_malloc(int64_t size){
 void *a = malloc(size + sizeof(int64_t));
 if(!a) return null;
 int64_t *l = (int64_t*)a;
 *l = size;
 return a + sizeof(int64_t);
}

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

>Я же не привел других функций: strcpy/memcpy с автопроверкой длины буфера; да и просто функцию для определения размера выделенной памяти...

И? Во время маллока ты возвращаешь указатель, по которому, сдвинувшись на несколько байт назад, всегда получишь и размер буфера. В своем free ты это и делаешь. Я к тому веду, что хранить всегда и без того известный адрес - лишняя трата памяти.

staseg ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.