Страница 1 из 2

Массив строк

Добавлено: 09 сен 2009, 16:45
Sobakaa
Имеется строковый двумерный массив. Столкнулся с проблемой - а как отсортировать его по длине строк?
Если через strlen(), то это нужно менять строки местами в массиве, наверное. Это реально?
Если использовать strcpy то я по идее мог бы скопировать одну строку массива в темп, потом из темпа - в другую строку. Ну, пузырьком, в общем. Но то ли я дурак, то ли компилятор - не позволяет.
Есть ещё чудесная strcmp(), но более дву строк я за раз не сравню, так что бесполезно, наверное.

А теперь, вопрос - может кто-то сталкивался или видел, как кто-то сортирует такое? Или может алгоритм есть, а я не знаю?

Re: Массив строк

Добавлено: 09 сен 2009, 22:22
Otsego
Ну разумеется тут не обойтись без другого такого же массива, если не хочется ломать мозг.

Ищешь в основном массиве самую длинную строку (strlen()), заносишь ее в другой массив на "последнее место" (в первой итерации цикла можно назвать "первым местом"), обнуляешь уже ненужную строку в основном. Все это в цикле, необходимые условия не составит труда придумать. И всеу. Если уж строго нужно, чтоб в основном массиве все это было сделано, то копируешь из второго в основной.

Re: Массив строк

Добавлено: 10 сен 2009, 00:17
Sobakaa

Код: Выделить всё

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

int main()
{
	char str[10][10];
	int i=0;
	for(i=0;getchar()!='*' ;)
	{
		fgets(str[i],10,stdin);
		i++;
	}
	int k=i;
	printf("/n%i",k);
	for (i=0;i<k; i++)
		printf("\n%s",str[i]);
	char r[10]={0};
	for (i=0; i<k-1; i++)
	{
		for (int j=i+1; j<k; j++)
		{
			if (strlen(str[i])<strlen(str[j]))
			{
				strcpy(r,str[i]);
				strcpy(str[i],str[j]);
				strcpy(str[j],r);
			}
		}
	}
	for (i=0;i<k; i++)
		printf("%s\n",str[i]);   
}
Сей фрагмент должен бы, в идеале, считывать строки-слова пока их не 10, или пока я не введу * и сортировать по длине. Но что-то оно не так как хочется - getchar() откусывает любую первую букву в строке. По другому же организовать ввод до тех пор пока пользователь не введёт некий символ (в идеале пустую строку) у меня не получается :-(

Re: Массив строк

Добавлено: 10 сен 2009, 10:40
Otsego
Я твою задачу так решил. Вводишь 10 слов, каждое может содержать 10 символов. Я проверки не писал, поэтому вводи придерживаясь этих правил. Причем имея ввиду то, что строка заканчивается нуль-символом, букв нужно вводить не более 9. Разумеется спрашивай, если что не понятно. Код смотри в вложении

Re: Массив строк

Добавлено: 10 сен 2009, 12:11
Airhand
А чего ты не меняшь указатели местами. Это быстрее.

Re: Массив строк

Добавлено: 10 сен 2009, 12:43
Romeo
Airhand, ты не прав.

При задании массива строк в виде:

Код: Выделить всё

char str[10][10];
мы получаем массив константных указателей, так что указатели менять местами нельзя. И дело тут не во вредности компилятора, а в том, что при таком задании массив уже размещён на стеке и менять указатели в нём просто невозможно физически.

Для того, чтобы получилось менять указатели местами следует создавать массив строк динамически:

Код: Выделить всё

char** str = new char* [10];
for (int i = 0; i < 10; str[i++] = new char [10]);
Однако при столь малых размерах самих строки и их количества, затраты на динамическое выделение памяти будут выше, чем затраты на копирование строк в случае выделения памяти на стеке, так что приведённый подход будет работать всё равно быстрее.

Re: Массив строк

Добавлено: 10 сен 2009, 21:25
Sobakaa
Ммм, спасибо. Но всё-таки условие в данном случае необходимо. И, если будете писать ещё код - на анси си пожалуйста, если конечно вас не затруднит.
Вообще какие идеи насчёт условия? Что кроме гетчара может остановить ввод при получении в качестве аргумента пустой строки или другого редкого символа(горизонтальной табуляции например)?

Re: Массив строк

Добавлено: 11 сен 2009, 12:10
Airhand
Я имел ввиду переделать исходник так, тобы можно было менять местами указатели.

Re: Массив строк

Добавлено: 11 сен 2009, 16:12
Sobakaa

Код: Выделить всё

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

int main()
{
	char str[10][10];
	int i=0;
	while(!feof(stdin)&&i<10)
	{
		scanf("%s\n", str[i]);
		i++;
	}
	int k=i;
	printf("\n%i",k);
	for (i=0;i<k; i++)
		printf("\n%s",str[i]);
	printf("\n\n");
	char r[10]={0};
	for (i=0; i<k-1; i++)
	{
		for (int j=i+1; j<k; j++)
		{
			if (strlen(str[i])<strlen(str[j]))
			{
				strcpy(r,str[i]);
				strcpy(str[i],str[j]);
				strcpy(str[j],r);
			}
		}
	}
	for (i=0;i<k; i++)
		printf("\n%s",str[i]);
	printf("\n");
}
Вот до чего в итоге дошёл. Ввод ждёт ^Z для моей Вижуал Студии и работает теперь корректно.
Спасибо всем, кто откликнулся.

Re: Массив строк

Добавлено: 12 сен 2009, 15:44
_SG
Мне кажется при увеличении массива по обеим размерностям код будет медленный. Имхо, для улучшения проще разок пробежаться по нему, построить массив размеров строк, его отсортировать (напрягая память вспоминаю стандартную qsort() чтобы ничего не выдумывать) и потом уж копировать. куча вызовов функций уйдёт.