Массив строк

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Sobakaa
Сообщения: 16
Зарегистрирован: 04 сен 2009, 14:36

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

А теперь, вопрос - может кто-то сталкивался или видел, как кто-то сортирует такое? Или может алгоритм есть, а я не знаю?
Otsego
Сообщения: 5
Зарегистрирован: 30 авг 2009, 19:45

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

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

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

#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() откусывает любую первую букву в строке. По другому же организовать ввод до тех пор пока пользователь не введёт некий символ (в идеале пустую строку) у меня не получается :-(
Otsego
Сообщения: 5
Зарегистрирован: 30 авг 2009, 19:45

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

[Расширение txt было запрещено, вложение больше недоступно.]

Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

А чего ты не меняшь указатели местами. Это быстрее.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Airhand, ты не прав.

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

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

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

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

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

char** str = new char* [10];
for (int i = 0; i < 10; str[i++] = new char [10]);
Однако при столь малых размерах самих строки и их количества, затраты на динамическое выделение памяти будут выше, чем затраты на копирование строк в случае выделения памяти на стеке, так что приведённый подход будет работать всё равно быстрее.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Sobakaa
Сообщения: 16
Зарегистрирован: 04 сен 2009, 14:36

Ммм, спасибо. Но всё-таки условие в данном случае необходимо. И, если будете писать ещё код - на анси си пожалуйста, если конечно вас не затруднит.
Вообще какие идеи насчёт условия? Что кроме гетчара может остановить ввод при получении в качестве аргумента пустой строки или другого редкого символа(горизонтальной табуляции например)?
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

Я имел ввиду переделать исходник так, тобы можно было менять местами указатели.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Sobakaa
Сообщения: 16
Зарегистрирован: 04 сен 2009, 14:36

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

#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 для моей Вижуал Студии и работает теперь корректно.
Спасибо всем, кто откликнулся.
_SG
Сообщения: 53
Зарегистрирован: 28 фев 2009, 10:43
Откуда: Севастополь

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