質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

3902閲覧

ループ内のsscanfの使い方がわかりません

wagon

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/06/17 16:27

前提・実現したいこと

 C言語でデータ文字列を変換し、構造体の配列に格納する関数を作ろうとしています。
プログラムを実行すると、ヘッダファイル内のsscanf関数の実行で動作が停止してしまいます。
正しく読み取りたいのですがどうすれば実現できるでしょうか?

発生している問題・エラーメッセージ

ヘッダファイル内のvoid set_data_studentの関数内にあるsscanfを実行中に問題が起きていることだけわかりました。

エラーメッセージ
Microsoft Visual C++ 2010 Express
Run-Time Check Failure #3 - The variable 'e' is being used without being initialized.
中断 継続 無視

該当のソースコード

C

1ソースコード

//mystack ヘッダファイルの一部
#ifndef MYSTACK_H
#define MYSTACK_H

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

struct student
{
char name[12];
int math;
int eng;
};
//struct student構造体オブジェクトのメンバに値を格納する関数
struct student set_student(char n, int m, int e)
{
struct student ps = NULL;
ps = (struct student
)malloc(1 * sizeof(struct student));
if(ps == NULL)
{
puts("記憶域の確保に失敗しました");
return NULL;
}
strcpy(ps->name, n);
ps->math = m;
ps->eng = e;
return ps;
}
/
--データ文字列から数値や文字列にデータ変換をし構造体にまとめて管理する関数--
/
void set_data_student(char *data[100], struct student *seito[100],int length)
{
char *n;
int m,e,i;
for(i=0;i<length;i++)
{
sscanf(data[i],"%s%d%d",&n[0],m,e);//<-ここでエラーとなりました
seito[i] = set_student(&n[0],m,e);
}
}
#endif

試したこと

ソースファイル内でset_data_student関数の引数には問題はないようでした。

補足情報(FW/ツールのバージョンなど)

Microsoft Visual C++ 2010 Express を使用しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こうですかね

c

1void set_data_student(char *data[100], struct student *seito[100], int length) 2{ 3 char n[12]; 4 int m, e; 5 6 for (int i = 0; i < length; i++) 7 { 8 sscanf(data[i], "%s%d%d", n, &m, &e); 9 seito[i] = set_student(n, m, e); 10 } 11}
  • The variable 'e' is being used without being initialized. と指摘されているとおり,変数 e の値は初期化されておらず,このまま実行しても値は不定です。「値を渡す」のではなく「変数に値をセットする」という使い方をしたいのであれば,修正例のように &e として変数へのポインタとして渡す必要があります。 m に関しても同様です。
  • &n[0]n で十分です。
  • データ格納領域を実際に作らずに sscanf で文字列を格納することはできないので,char *n; ではなく char n[12]; として宣言してください。

【蛇足】

  • バッファオーバーランの危険性があります。文字列が12文字以上入力されてもプログラムが落ちないようにしたいのであれば, 標準入力から安全に文字列を受け取る方法いろいろ - Qiita を参考に改良してください。
  • 設計上の問題ですが,実際に実用的なプログラムをもし作るのであれば,「malloc した領域へのポインタに構造体を書き込んでそのポインタを返す関数」ではなく「引数で受け取ったポインタが指す領域に構造体を書き込む関数」というデザインにすべきです。構造体に含まれる文字列が固定長であれば,そもそもメモリを動的に確保せずとも使えます。

投稿2018/06/17 16:51

編集2018/06/17 17:04
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mpyw

2018/06/17 17:16 編集

Microsoftの独自拡張ですが,scanf_s / sscanf_s などのよりメモリまわりを安全にした関数も存在します。 scanf_s() で文字列を入力 http://www.eonet.ne.jp/~maeda/cpp/scanf.htm 標準を意識せずにとりあえず Windows 上でコンパイルできればいいのであれば,書式部分にごちゃごちゃかくよりも引数としてサイズを指定できるこちらを使ったほうがいいかもしれません。
wagon

2018/06/17 18:03

丁寧な回答をありがとうございます。無事、問題は解決しました。 プログラミング自体まだ始めたばかりで、補足説明もとてもいい勉強になりました! 今回のプログラムも実用的なものに改良していけたらと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問