エラーが出て困っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ルート

エラーが出て困っています。

#1

投稿記事 by ルート » 12年前

初、投稿のルートです。以後よろしくお願いします。

 只今、ノベル風の文字表示のプログラムを作っているのですが(当サイトのサンプルプログラム参考)、エラーが出て困っています。どなたかわかるかたお願いします。
メインプログラム↓
ーーーーーーーーーーー
#include "DxLib.h"
#include "style1.h"

int i=0,j,ch_i=0,counter=0,White;
char Key[256],oldKey[256]={},disp[80]="",ch[5][80];

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;
SetDrawScreen( DX_SCREEN_BACK ) ;

White=GetColor(255,255,255);

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

style1_up();
for(j=0;j<256;j++){
if(oldKey[j]==0 && Key[j]==1)
Key[j]=2;
oldKey[j]=Key[j];
}

if(Key[KEY_INPUT_RETURN]==2){ // 前回押されてなくて、今回押されていたら
i=0; // iを初期値に戻し
ch_i++; // 表示する配列を1つずらす
if(ch_i==5) // これ以上表示する配列がなくなったらbreak;
break;
}

// 配列の終端-2以下で、今回コピーするiまでの配列要素のi番目が\0じゃなくカウンターが5の倍数なら
if(i<=80-2 && ch[ch_i]!='\0' && counter%5==0){
i+=2; // 全角文字なので配列要素2つずつカウントアップ
strncpy_s(disp,ch[ch_i],i);// iバイトまでの配列要素をdisp配列にコピー
disp='\0'; // 終端記号を代入
}

DrawFormatString(10,420,White,"%s",disp);//disp配列の文字データを表示

counter++;
ScreenFlip() ;

}

DxLib_End() ;
return 0 ;
}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
//style1.h↓

#ifndef DEF_style1_h //二重include防止
#define DEF_style1_h

void style1_up();

#endif
ーーーーーーーーーーーーーーーーーーーー
//style1.cpp
#include "DxLib.h"
char ch[5][80];
void style1_up()
{

ch[5][80]=(
"プログラムを習得するには、実際に自分で書いてみることが大事。",
"参考書を読むことも重要だが、数学のように演習を通して、",
"体に身につけるようにしよう。",
"きっと、よりはっきりと、関数の使い方、",
"プログラムの書き方がわかるだろう。"
);
}

style1.cppの部分で文を書いて、メインのほうに表示したいのですが・・・・

以下のようなエラーが出ます。
・c:\users\ユーザ名\documents\visual studio 2010\projects\samplex\style1.cpp(12): error C2440: '=' : 'const char *' から 'char' に変換できません。
1> この変換が可能なコンテキストはありません。

開発環境はVisual Studio Professionalを使用しています。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#2

投稿記事 by beatle » 12年前

ソースコードはcodeタグで囲みましょう。
2次元配列chはstyle1.cppの2行目で定義されていますので、初期化はそこでやらねばなりません。
どうしてもstyle1_up関数内部で文字列を代入したいなら、strcpy関数を使ったり、1文字ずつ代入したりしなければなりません。

ルート

Re: エラーが出て困っています。

#3

投稿記事 by ルート » 12年前

別に関数ないじゃなくてもいいんですが、
ようは、文章表示の処理をメイン関数以外で、できないかなということなのですが、
ないでしょうか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#4

投稿記事 by beatle » 12年前

とりあえず整形したソースを貼ります。本来ならルートさんがやるべき作業です。

main.cpp

コード:

#include "DxLib.h"
#include "style1.h"

int i=0,j,ch_i=0,counter=0,White;
char Key[256],oldKey[256]={},disp[80]="",ch[5][80];

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
	if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;
	SetDrawScreen( DX_SCREEN_BACK ) ;

	White=GetColor(255,255,255);

	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

		style1_up();
		for(j=0;j<256;j++){
			if(oldKey[j]==0 && Key[j]==1)
				Key[j]=2;
			oldKey[j]=Key[j];
		}

		if(Key[KEY_INPUT_RETURN]==2){ // 前回押されてなくて、今回押されていたら
			i=0; // iを初期値に戻し
			ch_i++; // 表示する配列を1つずらす
			if(ch_i==5) // これ以上表示する配列がなくなったらbreak;
				break;
		}

		// 配列の終端-2以下で、今回コピーするiまでの配列要素のi番目が\0じゃなくカウンターが5の倍数なら
		if(i<=80-2 && ch[ch_i][i]!='\0' && counter%5==0){
			i+=2; // 全角文字なので配列要素2つずつカウントアップ
			strncpy_s(disp,ch[ch_i],i);// iバイトまでの配列要素をdisp配列にコピー
			disp[i]='\0'; // 終端記号を代入
		}

		DrawFormatString(10,420,White,"%s",disp);//disp配列の文字データを表示

		counter++; 
		ScreenFlip() ;

	}

	DxLib_End() ;
	return 0 ;
}
//style1.h

コード:

#ifndef DEF_style1_h //二重include防止
#define DEF_style1_h

void style1_up();

#endif
//style1.cpp

コード:

#include "DxLib.h"
char ch[5][80];
void style1_up()
{

	ch[5][80]=(
		"プログラムを習得するには、実際に自分で書いてみることが大事。",
		"参考書を読むことも重要だが、数学のように演習を通して、",
		"体に身につけるようにしよう。",
		"きっと、よりはっきりと、関数の使い方、",
		"プログラムの書き方がわかるだろう。"
		);
}

box
記事: 2002
登録日時: 13年前

Re: エラーが出て困っています。

#5

投稿記事 by box » 12年前

ルート さんが書きました:
main.c

コード:

char Key[256],oldKey[256]={},disp[80]="",ch[5][80];
ここのch[5][80]と
ルート さんが書きました: //style1.cpp

コード:

char ch[5][80];
ここのch[5][80]とは、どういう使い分けをしたいのですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#6

投稿記事 by beatle » 12年前

ch変数に関することでいくつか問題点がありますので指摘します。

まず、ch変数はグローバル変数になっているのに、2つの.cppファイルに定義されていることです。
グローバル変数を複数の場所で定義するのはダメです。

次に、配列の扱いに関する根本的な理解不足です。
例えば

コード:

char a[16];
と定義された変数aが有った場合、この配列の5番目の要素に書きこむには

コード:

a[5] = 'x'; // 1文字をchar型変数に代入
とします。決して

コード:

a[5] = "0123456789abcde"; // 16文字をchar型変数に代入(無理!)
とは書けません。
これは2次元配列でもまったく同じで、添え字が1つ増えるだけです。

ルートさんは

コード:

    ch[5][80]=(
        "プログラムを習得するには、実際に自分で書いてみることが大事。",
        "参考書を読むことも重要だが、数学のように演習を通して、",
        "体に身につけるようにしよう。",
        "きっと、よりはっきりと、関数の使い方、",
        "プログラムの書き方がわかるだろう。"
        );
と書いていますが、これはC++の文法的に誤りです。配列にまとめて値を入れるときは、配列を定義した時点で「初期値」として指定するしかありません。

コード:

    char ch[5][80] = { // これは、変数chの「定義」。括弧の形にも注目。
        "プログラムを習得するには、実際に自分で書いてみることが大事。",
        "参考書を読むことも重要だが、数学のように演習を通して、",
        "体に身につけるようにしよう。",
        "きっと、よりはっきりと、関数の使い方、",
        "プログラムの書き方がわかるだろう。"
        }; // 凄くいい言葉ですね。
この場合は、文字列5つを「初期値」として与えているため、C++の文法的に正しいです。

ルート

Re: エラーが出て困っています。

#7

投稿記事 by ルート » 12年前

style1_upによる文章の格納はできたのですが、
style1_up関数をそのまま、メインのとこに記述しただけでは、文は表示されないのでしょうか?
やはり、strcpy関数とかで、コピーして表示させるのでしょうか・・・・

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#8

投稿記事 by beatle » 12年前

ルート さんが書きました:style1_upによる文章の格納はできたのですが、
style1_up関数をそのまま、メインのとこに記述しただけでは、文は表示されないのでしょうか?
やはり、strcpy関数とかで、コピーして表示させるのでしょうか・・・・
恐らく、No.5のboxさんの質問に答えれば、分かってくるでしょう。

ルート

Re: エラーが出て困っています。

#9

投稿記事 by ルート » 12年前

なんとか、できました。
みなさん、ありがとうございました。!

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#10

投稿記事 by beatle » 12年前

その、完成したソースコードを貼って下さい。後の人の参考になるように。お願いします。
これはフォーラムルールでもありますから、義務です。
また、解決した時は、「解決しました」とだけ言って去らず、ソースコードや解決した方法を明記して下さい。
同じ事で困っている人の為に過去ログに有用な情報を残すようお願いします。

ルート

Re: エラーが出て困っています。

#11

投稿記事 by ルート » 12年前

解決したかと、思ったら操作みすでした・・・・・
もう少し頑張ってみます。

ルート

Re: エラーが出て困っています。

#12

投稿記事 by ルート » 12年前

boxさんが言ってたことは、こういうのとは、また別のことですよね・・・
ーーーーーーメインプログラムだけ載せました↓ーーーーーーーー
#include "DxLib.h"
#include "style1.h"

int i=0,j,ch_i=0,counter=0,White;
char Key[256],oldKey[256]={},disp[80]="", style1_up();

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;
SetDrawScreen( DX_SCREEN_BACK ) ;

White=GetColor(255,255,255);



while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){


for(j=0;j<256;j++){
if(oldKey[j]==0 && Key[j]==1)
Key[j]=2;
oldKey[j]=Key[j];
}

if(Key[KEY_INPUT_RETURN]==2){ // 前回押されてなくて、今回押されていたら
i=0; // iを初期値に戻し
ch_i++; // 表示する配列を1つずらす
if(ch_i==5) // これ以上表示する配列がなくなったらbreak;
break;
}

// 配列の終端-2以下で、今回コピーするiまでの配列要素のi番目が\0じゃなくカウンターが5の倍数なら
if(i<=80-2 && ch[ch_i]!='\0' && counter%5==0){
i+=2; // 全角文字なので配列要素2つずつカウントアップ
strncpy_s(disp,ch[ch_i],i);// iバイトまでの配列要素をdisp配列にコピー
disp='\0'; // 終端記号を代入
}

DrawFormatString(10,420,White,"%s",disp);//disp配列の文字データを表示

counter++;
ScreenFlip() ;

}

DxLib_End() ;
return 0 ;
}
ーーーーーーーーーーーーーーーーーーーーーー

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#13

投稿記事 by beatle » 12年前

boxさんの質問は、2つのch変数について、「どういう使い分けをしたいのか」ですから、日本語で答えたらいいと思います。

ルート

Re: エラーが出て困っています。

#14

投稿記事 by ルート » 12年前

boxさんが言いたいのは、グローバル関数を二回も定義しなくてもいい。
みたいなことでしょうか・・・・(確証がなく・・・)

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: エラーが出て困っています。

#15

投稿記事 by bitter_fox » 12年前

最初に、ソースコードを載せる場合はcodeタグを使ってください。
http://dixq.net/board/board.html#k10
このことは既にbeatleさんからも指摘されていますが、codeタグの使い方が分からないのでしょうか?
もしそうであれば使い方を説明しますのでおっしゃってください。
ルート さんが書きました:boxさんが言いたいのは、グローバル関数を二回も定義しなくてもいい。
みたいなことでしょうか・・・・(確証がなく・・・)
最初のプログラムの問題を簡潔に説明すると、
A地区(ファイルA)にch君がいて、B地区(ファイルB)に同姓同名のch君がいると考えてください。
B地区に居るstyle1_upさんがch君に荷物S(文字列)を預けました。このch君はB地区にいるch君です。
そのあとA地区のWinMainさんがch君から荷物S(文字列)を受け取ろうとします。この時のch君はA地区のch君です。
・・・荷物SはB地区のch君が持っていて、A地区のch君は持っていないのでWinMainさんが行った行動は失敗します。

boxさんの言いたいことはおそらく、A地区のch君とB地区のch君は本当は同じ人であってほしいのではないですか?という事だと思います。

ちなみにこの状況だとリンクに失敗します。

もしstyle1.cppが次のようになっていたら事態はより複雑です。

コード:

#include "DxLib.h"
char ch[5][80];
void style1_up()
{
	char ch[5][80] = {
		"プログラムを習得するには、実際に自分で書いてみることが大事。",
		"参考書を読むことも重要だが、数学のように演習を通して、",
		"体に身につけるようにしよう。",
		"きっと、よりはっきりと、関数の使い方、",
		"プログラムの書き方がわかるだろう。"
	};
}
この場合だと、B地区にいるch君に加え、style1_upさんお抱えの秘書のch君が居るというような感じです。
そしてstyle1_upさんが預けた荷物S(文字列)を持っているのはお抱えの秘書のch君です。

この問題の解決にはexternを使ってchを一つにまとめてください。
http://7ujm.net/C++/extern.html
http://www.geocities.jp/ky_webid/c/032.html

あと、グローバル変数を乱用するのは好ましくないので、グローバル変数を乱用しない書き方をしたほうが良いようにも思います。

[hr][追記]
擬似コードを用いると

コード:


file Main
{
	include header DxLib
	include header style1

	char ch[5][80]

	function WinMain
}

file style1
{
	char ch[5][80]

	function style1_up
}

の様になります。
WinMainからはfile style1のchは見えません、また同様にstyle1_upからはfile Mainのchは見えません。

ルート

Re: エラーが出て困っています。

#16

投稿記事 by ルート » 12年前

コード:

//style.h
#ifndef DEF_style1_h //二重include防止
#define DEF_style1_h
 
 void style1_up();
 
#endif

コード:

//style1.cpp
#include "DxLib.h"

void style1_up()
{
char ch[5][80]={
        "プログラムを習得するには、実際に自分で書いてみることが大事。",
        "参考書を読むことも重要だが、数学のように演習を通して、",
        "体に身につけるようにしよう。",
        "きっと、よりはっきりと、関数の使い方、",
        "プログラムの書き方がわかるだろう。"
 };
}

コード:

//samplex
#include "DxLib.h"
#include "style1.h"
 
int i=0,j,ch_i=0,counter=0,White;
char Key[256],oldKey[256]={},disp[80]="",ch[5][80];


int WINAPI WinMain( HINSTANCE , HINSTANCE , LPSTR , int )
{
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;
    SetDrawScreen( DX_SCREEN_BACK ) ;
	

    White=GetColor(255,255,255);
              
   style1_up();


    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
 
       
        for(j=0;j<256;j++){
            if(oldKey[j]==0 && Key[j]==1)
                Key[j]=2;
            oldKey[j]=Key[j];
        }
 
        if(Key[KEY_INPUT_RETURN]==2){ // 前回押されてなくて、今回押されていたら
            i=0; // iを初期値に戻し
            ch_i++; // 表示する配列を1つずらす
            if(ch_i==5) // これ以上表示する配列がなくなったらbreak;
                break;
        }
 
        // 配列の終端-2以下で、今回コピーするiまでの配列要素のi番目が\0じゃなくカウンターが5の倍数なら
        if(i<=80-2 && ch[ch_i][i]!='\0' && counter%5==0){
            i+=2; // 全角文字なので配列要素2つずつカウントアップ
            strncpy_s(disp,ch[ch_i],i);// iバイトまでの配列要素をdisp配列にコピー
            disp[i]='\0'; // 終端記号を代入
        }
 
        DrawFormatString(10,420,White,"%s",disp);//disp配列の文字データを表示
 
        counter++; 
        ScreenFlip() ;
 
    }
 
    DxLib_End() ;
    return 0 ;
} 
上の三つのようにしたら、windowまでは正常に処理されるようになったのですが、
肝心の文章が表示されません。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#17

投稿記事 by beatle » 12年前

A地区のch君、B地区のch君、style1_upさんお抱えの秘書chさん
の3人のうち、いなくなったのはB地区のch君だけです。
残る2人のうち、荷物S(文字列)を持っているのは
  • A地区のch君
  • style1_upさんお抱えの秘書chさん
のどちらか、分かりますか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: エラーが出て困っています。

#18

投稿記事 by softya(ソフト屋) » 12年前

マルチポストされているのでリンクします。
フォーラムルールに従って相互リンクをお願いします。

http://detail.chiebukuro.yahoo.co.jp/qa ... 1175937056
http://detail.chiebukuro.yahoo.co.jp/qa ... 1275938002

回答者の皆さんの意図が伝わっていない様ですね・・・。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

Re: エラーが出て困っています。

#19

投稿記事 by naohiro19 » 12年前

関数の外で宣言された変数は「グローバル変数」といって関数の中に入っても使えます。
しかし、関数の中で宣言された変数は「ローカル変数」といってその関数の中でしか使えないという制限があります。

ルート

Re: サウンドノベル風の文表示プログラム

#20

投稿記事 by ルート » 12年前

 サウンドノベル風の文表示プログラムを作っているのですが、
文章だけ、違うソースに書いて、それを読み込んで、表示したいと考えているのですが、
なかなかうまくいきません。
 何か方法は、ないでしょうか・・・

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: エラーが出て困っています。

#21

投稿記事 by beatle » 12年前

ファイル分割した場合の基本的なやり方がよく分かっていらっしゃらないようですので、単純な例を示します。
main.cppにあるmain関数から、message.cppにあるmsg変数を利用する、という場面を考えます。

コード:

// message.hpp
#ifndef MESSAGE_HPP_
#define MESSAGE_HPP_
extern char msg[];
void SetMessage(int message_id);
#endif // MESSAGE_HPP_
ルートさんはC++でソースコードを書いているみたいですので、僕もC++で書きました。C++のヘッダファイルは.hppにすることがあります。
ここでのポイントは、グローバル変数msgをextern付きで宣言していることです。externを付けることによって、
「変数msgは、どこか他の場所で実体が定義されていますよー」ということになります。
externで宣言した場所には実体が生成されず、「実体はどこかにある」、という情報だけを表します。

コード:

// message.cpp
#include "message.hpp"
#include <cstring>

char msg[128];

void SetMessage(int message_id)
{
    switch (message_id)
    {
    case 0: strcpy(msg, "msg0: hello"); break;
	case 1: strcpy(msg, "msg1: world"); break;
	}
}
変数msgの実体を定義しているのがmessage.cppです。extern無しでグローバル変数を宣言(これを定義といいます)すると、
実際にその場所に変数の実体が生成されます。

message.cppでは、#includeでmessage.hppを読み込んでいるため、実際には

コード:

extern char msg[];
char msg[128];
と書いたことと同じになります。
extern付きの宣言とextern無しの宣言が同じファイルに入っていた場合はextern無しの宣言が優先され
実体が生成されることになっていますので、心配要りません。

コード:

// main.cpp
#include "message.hpp"
#include <cstdio>

int main()
{
	SetMessage(0);
	puts(msg);
	SetMessage(1);
	puts(msg);
}
main.cppからmessage.cppにあるSetMessage関数とmsg変数を使っています。
message.hppを#includeすることによって、main.cppファイルに

コード:

extern char msg[];
という宣言が取り込まれ、msg変数の実体がどこかにあるんだな、ということが分かるため、msg変数を利用することができるのです。

以上をまとめると
  • あるグローバル変数の実体を置くファイルは、どれか1つの.cppファイルにする。今回の例ではmain.cpp
  • そのグローバル変数を、ヘッダファイルでextern宣言する。
  • そのグローバル変数を使うすべての.cppファイルで、extern宣言が入ったヘッダファイルを#includeする。
となります。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: サウンドノベル風の文表示プログラム

#22

投稿記事 by ISLe » 12年前

ルート さんが書きました: サウンドノベル風の文表示プログラムを作っているのですが、
文章だけ、違うソースに書いて、それを読み込んで、表示したいと考えているのですが、
なかなかうまくいきません。
 何か方法は、ないでしょうか・・・
この掲示板の下の方にある検索ボックスに「サウンドノベル風」と入力して検索すると幸せになれるかもしれません。

ルート

Re: エラーが出て困っています。

#23

投稿記事 by ルート » 12年前

ルートさんはC++でソースコードを書いているみたいですので、僕もC++で書きました。

自分はCの方はまだわかりますが、C++の方は勉強してないので全然です・・・・

閉鎖

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