vectorの並び替え

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
luc
記事: 32
登録日時: 8年前

vectorの並び替え

#1

投稿記事 by luc » 8年前

C++,Win32APIを使用しています。タイムランキングを作成しております。

pairのsecondだけをソートがしたいです。

ですがsortの第三引数をどう書けばいいか分かりません。

現在動かすと、最新タイムに全て上書きされてしまい。

1位 名前 30.0
2位 名前 30.0
...と全部名前もタイムも上書きされてしまいます。
またタイムは小数点が切り捨てられ?30.5秒なのに30.0になってしまいます。


hファイル

コード:

#pragma once
#include <windows.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <locale>
#include <algorithm>
#include <functional>
#include <winnls.h>
#include"timer.h"
#include"debugmsg.h"

using namespace std;

class Ranking_Name
{
private:

	vector<string>data;

	typedef pair<string,double> rank_pair;

	vector<rank_pair>m_ranking;

	struct sort_less {
		bool operator()(const std::pair<string, double> &left, const std::pair<string,double> &right) {
			return left.second < right.second;
		}
	};

public:
	Ranking_Name();
	~Ranking_Name();

	bool Reading();	//ランキング読み込み
	TCHAR name[30];
	
	void Sort_Asc();	//Rankingを昇順にソート
	
	void AddRanking(HDC);	//ランキング登録

	int NameInput(HWND hWnd1);

};
cppファイル

コード:

#include "Ranking_Name.h"


Ranking_Name::Ranking_Name()
{
}

Ranking_Name::~Ranking_Name()
{
}

bool Ranking_Name::Reading()
{
	int num = 0;
	int i = 0;
	string str;
	ifstream ifs("ranking.txt");

	if (ifs.fail()) {			//ランキングファイルが無かったら
		
		for (i = 0; i < 5; i++){
			m_ranking.push_back(make_pair("あいうえお", 999.0-i));
		}
	}

	while (getline(ifs, str))			//ランキングファイルがある場合
	{
		string tmp;
		istringstream stream(str);
		num += 1;

		while (getline(stream, tmp, ','))
		{
			data.push_back(tmp);	//カンマだったらtmpに一時的にデータを入れる
		}
		m_ranking.resize(num);
		m_ranking[i].first = data[0];
		m_ranking[i].second = atoi(data[1].c_str());
		++i;
		data.clear();
	}
	ifs.close();
	return true;
}

void Ranking_Name::Sort_Asc()
{
	sort(m_ranking.begin(), m_ranking.end(),sort_less());   //昇順ソート
}


void Ranking_Name::AddRanking(HDC hdc){

	int i = 0;
	char str[30];		//変換用
	TCHAR buf[30];		//変換用	
	char cstr[30];		
	ofstream ofs("ranking.txt");

	WideCharToMultiByte(CP_ACP, 0, name, -1, cstr, sizeof(cstr), NULL, NULL);	//TCHAR からCHAR

	m_ranking.push_back(make_pair(cstr, S_time));		//ランキング最後に入れる

	Sort_Asc();   //昇順ソート

	for (i = 0; i < 5; i++){
		ofs << m_ranking[i].first <<  "," << m_ranking[i].second << "," << endl;		//テキストファイルに書き込み
			
		strcpy(str, m_ranking[i].first.c_str());			//stringからcharに変換(コピー)

		MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, str, strlen(str), buf, (sizeof buf) / 2);	//charからTCHAR

		DebugStringColor("%d位", i + 1, hdc, 300, 65 * (4.5 + i), 27, 0, 0, 0);			//描画
		DebugStringColor("%.1lf秒", m_ranking[i].second, hdc, 600, 65 * (4.5 + i), 27, 0, 0, 0);			//描画
		DebugStringColor("名前 %s", buf, hdc, 400, 65 * (4.5 + i), 27, 0, 0, 0);							//描画
	}
	m_ranking.pop_back();
	m_ranking.resize(5);
}

int Ranking_Name:: NameInput(HWND hWnd1)
{
	SYSTEMTIME st;
	int age;
	
	TCHAR str[256];
	TCHAR *str_org = TEXT("%s");

	MessageBox(hWnd1, name, TEXT("名前"), MB_OK);

	return 0;
}

djann
記事: 27
登録日時: 11年前

Re: vectorの並び替え

#2

投稿記事 by djann » 8年前

luc さんが書きました:pairのsecondだけをソートがしたいです。

ですがsortの第三引数をどう書けばいいか分かりません。
???
第三引数の書き方は合っているんじゃないですかね?
そのRanking_Name::sort_less構造体さんに定義で特別間違いはないと思いますよ。
(rank_pairをtypedefしているのになぜかここではstd::pair<string, double>であるとか、そもそもusing namespaceをヘッダに書かないようにとか、名前の付け方が一部だけどこかからパクってきたようなものであるとか、std::を付けているところと付けていないところがごっちゃであるとか、TCHARを使用しているのにWCHAR決め打ちのところがあるとか、ファイルがある場合ない場合とコメントでは書いていてもコードがその通りになっていないとか、timer.hとdebugmsg.hはどこからきてどこへ行くのだろうとか、使わないヘッダを無駄に(しかもヘッダで)インクルードするのはどうなのかとか色々思うところはありますが。)

ソートを行わない状態ではどうなりますか?
また、文字列の扱いでコードが大きくなってしまっていますが、そこを省いて試してみたらどうなるでしょう?
一応下記のコードのように、secondのみをキーとしソートが働いていることは確認できますので、Ranking_Name::sort_lessは正しく動いていると考えられますよ。
タイム(rank_pair::second)が切り捨てられてしまうのは、DebugStringColor()とやらの定義がどうなっているのかを見ないことには何とも言えません。

コード:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>



typedef std::pair<std::string, double> rank_pair;

std::vector<rank_pair> rank;

// sort_less::operator()を書き換えない為.
using std::string;

struct sort_less {
	bool operator()( const std::pair<string, double> &left, const std::pair<string, double> &right ) {
		return left.second < right.second;
	}
};

void add( std::string name, double time ){
	rank.push_back( std::make_pair( name, time ) );
}


int main()
{
	add( "a", 30.5 );
	add( "b", 29.1 );
	add( "c", 39.1 );

	std::sort( rank.begin(), rank.end(), sort_less() );

	for ( auto const &v : rank ){
		std::cout << v.first << " : " << v.second << std::endl;
	}
	std::cin.get();
}
そちらの環境で34行目辺りのforがエラーになる場合は、昔ながらのforループに書き換えてください。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: vectorの並び替え

#3

投稿記事 by みけCAT » 8年前

luc さんが書きました:またタイムは小数点が切り捨てられ?30.5秒なのに30.0になってしまいます。
文字列から数値に変換するのにatoiを使っているからですね。
小数点以下の情報も含めて変換するには、代わりにatofを用いると良いでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

luc
記事: 32
登録日時: 8年前

Re: vectorの並び替え

#4

投稿記事 by luc » 8年前

ソートはがない場合だと
あいうえお,999,
あいうえお,998,
あいうえお,997,
あいうえお,996,
あいうえお,995,
と表示されました。
また文字列関係を全て消して動かしたら上書きされてしまい全部最新タイムのままでした。

AddRankingのadd("aaa", S_time)); を消すと
あいうえお,995,
あいうえお,996,
あいうえお,997,
あいうえお,998,
あいうえお,999,
と正常に動きました。

push.backが上手くいってないってことなのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: vectorの並び替え

#5

投稿記事 by みけCAT » 8年前

luc さんが書きました:AddRankingのadd("aaa", S_time)); を消すと
あいうえお,995,
あいうえお,996,
あいうえお,997,
あいうえお,998,
あいうえお,999,
と正常に動きました。
add("aaa", S_time));などというものは最初から見当たらないのですが、どういう意味でしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

luc
記事: 32
登録日時: 8年前

Re: vectorの並び替え

#6

投稿記事 by luc » 8年前

m_ranking.push_back(make_pair(cstr, S_time));を消すと
の間違いです。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: vectorの並び替え

#7

投稿記事 by みけCAT » 8年前

luc さんが書きました:現在動かすと、最新タイムに全て上書きされてしまい。

1位 名前 30.0
2位 名前 30.0
...と全部名前もタイムも上書きされてしまいます。
Wandboxで動かせるように書き換えて動かしてみましたが、再現できませんでした。
http://melpon.org/wandbox/permlink/Qr6YrwkUW7wTOwsA
Ranking_Name::AddRankingを無駄に呼び出しているとかではないでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

luc
記事: 32
登録日時: 8年前

Re: vectorの並び替え

#8

投稿記事 by luc » 8年前

クリア画面の時に一度しか呼んでないですね。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: vectorの並び替え

#9

投稿記事 by みけCAT » 8年前

luc さんが書きました:クリア画面の時に一度しか呼んでないですね。
本当ですね?
MessageBoxなどで確認しましたね?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

luc
記事: 32
登録日時: 8年前

Re: vectorの並び替え

#10

投稿記事 by luc » 8年前

MessageBoxで確認した所無限に呼び出されてました・・・

閉鎖

“C言語何でも質問掲示板” へ戻る