ページ 11

「 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」というエラーについて

Posted: 2018年5月16日(水) 13:24
by Akatsuki
問題はこちらです!
1. 使用するプログラム言語はC言語とする。
2. プログラムはコンソールプログラムとする。
3. プログラムファイル(ntsSort.exe)の実行時にコマンドライン引数としてnレコードのデータ(商品コードと商   品名)が格納されたファイル(商品ファイル)のファイル名を与える。
4. プログラムは、商品ファイルを読み込み、各レコードの商品コード(先頭から3バイト)をキーとして昇順に  ソートし、ソート結果を標準出力に出力する。
商品ファイルの内容のサンプルとプログラム起動及び実行結果イメージを以下に記す。

 商品ファイル(test.dat)の内容のサンプル

  106 消しゴム
  019 シャープペンシル替え芯
  047 ボールペン(黒)
  085 万年筆
  016 シャープペンシル
  066 ステープラ
  023 ボールペン(赤)

 プログラム起動及び実行結果出力イメージ

  016 シャープペンシル
  019 シャープペンシル替え芯
  023 ボールペン(赤)
  047 ボールペン(黒)
  066 ステープラ
  085 万年筆
  106 消しゴム

5. 商品ファイルのレコード数は、2以上の任意の数とする。
6. 商品ファイルの改行コードはCrLf(0x0d0a)とする。
7. 商品ファイルのレコードは最大1024Byteとする。

コード:


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

/* 構造体 */
typedef struct {
	char name[1021];	//商品名
	int code[3];		//商品コード
	
}strct;

/* 配列のメモリ確保 */
int main(int argc, char *argv[], strct* str)
{


	// 動的メモリの確保。確保したメモリをstrct型ポインタにキャスト。
	str = (strct*)malloc(sizeof(strct));
	memset(str, 0, sizeof(strct));

	return 0;
}

/* ファイルの読み込み */
int add(int argc, char* argv[], strct* str) 
{
	FILE *fp;	// FILE型構造体
	char fname[100];
	char buf[256];
	strcpy_s(fname, 100, argv[1]);
	int Index = 1;
	int *Input = 0;
	
	if (argc != 2) {
		printf_s("引数の個数が異常です");
		return -1;
	}

	
	// ファイルのオープン 
	fopen_s(&fp, fname, "r");
	if (fp == NULL) {
		printf("%sファイルを開けません。\n", fname);
		return 0;
	}
	else {
		printf("%sファイルを開いた!\n", fname);
	}

	

	// ファイルの読み込み 
	while (fgets(buf, sizeof(buf), fp)) {
		printf("%s", buf);
		Index = Index + 1;
	}

	// ファイルの位置を最初に戻す 
	rewind(fp);

	// 配列にデータ格納
	while (fscanf_s(fp, "%3d %1020s", &str[*Input].code[3], &str[*Input].name[1021], 1024) != EOF) {
		*Input = (int)malloc(sizeof(int*));
		Input++;
	}


	// ファイルのクローズ 
	if (fclose(fp) != 0) {
		printf("ファイルのクローズに失敗しました。\n");
	}
	else {
		printf("ファイルをクローズしました\n");
	return 0;
	}

	return 0;
}

/* バブルソート 昇順 */
void bubbleSort(int code[], int Index, strct* str)
{
	int i, j, temp;

	for (i = 0; i < (Index - 1); i++) {
		for (j = (Index - 1); j > i; j--) {
			if (code[j - 1] > code[j]) {
				temp = code[j - 1];
				code[j - 1] = code[j];
				code[j] = temp;
			}
		}
	}
}

/* 標準出力 */
void standard(FILE *fp, int Index, strct* str)
{
	int output = 1;

	while (output < Index) {
		printf("%03d %s", &str[output].code[0], &str[output].name);
		if (output < Index - 1) {
			printf("\n");
		}
		output++;
	}
}

これで実行すると、標準出力の"printf"の所で 「warning C4477: 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」と表示されエラーになります。どこを直せばよいのか解らないので、解決方法を教えてください。
また、ソースで間違えてる部分とか指摘してもらえると嬉しいです。

よろしくお願いします。

Re: 「 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」というエラーについて

Posted: 2018年5月16日(水) 21:55
by box
warning C4477: 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」と表示されエラーになります。
warningと書いてあるとおり、エラーではありません。警告です。
実行ファイルは作成できているはずですので、実行すれば何かが起きるでしょう。喜ばしくない結果が出るかもしれませんが…。
while (fscanf_s(fp, "%3d %1020s", &str[*Input].code[3], &str[*Input].name[1021], 1024) != EOF)
code[3]とかname[1021]とか、定義領域の範囲外の場所にアクセスしていますが、大丈夫ですか?

いくつか関数を作成していますが、mainから呼び出している形跡がありません。
これは、「今は作成途中で、後から作る」という認識でよいですか?
printf("%03d %s", &str[output].code[0], &str[output].name);
これは何をしようとしているか、日本語で説明できますか?

Re: 「 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」というエラーについて

Posted: 2018年5月16日(水) 22:01
by みけCAT
Akatsuki さんが書きました:
6年前
これで実行すると、標準出力の"printf"の所で 「warning C4477: 'printf' : 書式文字列 '%03d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'int *' です」と表示されエラーになります。どこを直せばよいのか解らないので、解決方法を教えてください。
エラーメッセージの通り、printfの書式%dにはint*ではなくintのデータを渡さなければいけません。
同様に、書式%sには(ナル終端の文字列を指す)char*のデータを渡さなければいけません。
従って、該当行のprintfの引数についている&を両方取るといいでしょう。
(配列は、(sizeofに渡すなどの例外を除いて)式中では先頭要素を指すポインタに変換されます)
Akatsuki さんが書きました:
6年前
また、ソースで間違えてる部分とか指摘してもらえると嬉しいです。
  • 第3引数を取るmain関数は標準ではないので、必要なければ使うべきではありません。
  • main関数内でmalloc関数の戻り値がNULLかチェックせずにmemsetに渡しており、万が一mallocが失敗した時に危険です。
  • argc != 2のチェックをする前にargv[1]を使用しており、チェックが効かず危険です。
  • (0から変換される)ヌルポインタを代入したInputをそのままデリファレンスして読み書きしており、危険です。
  • fscanf_sに範囲外の要素を指すポインタを渡しており、危険です。
  • bubbleSort関数の引数strが使われておらず、実装が不適切である可能性があります。
  • standard関数の引数fpが使われておらず、実装が不適切である可能性があります。