こんばんは。
Cを勉強中の者なのですが
前に配列についての内容で自分も分からない事があったので投稿しました。

キーで文字列を入力して関数に渡し、
関数側で引数(文字列データ分)のメモリを確保する事は
出来るのでしょうか。


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

void test(char *hiki);

int main(void){
char inp[256];

scanf("%s",&inp);
printf("%s\n",inp);
test(inp);

return 0;
}

void test(char *hiki){

char *i;
i = (char*)malloc( );

/* 「hiki」をつかって出来るの
でしょうか? */



全然急ぎとかではなく、ちょっと疑問に思った事なのですが教えていただけるとうれしいです。
(考え方がおかしかったらスミマセン)

このQ&Aに関連する最新のQ&A

A 回答 (2件)

以下のような形になりますね。



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

void test(char* hiki);

void main(void)
{
  char inp[256];

  scanf("%s", inp); /* ←&は要らない */
  printf("%s\n", inp);

  test(inp);

  /* 適当な処理 */

  /* return; ←省略可(関数の型はvoidなので、戻り値も要らない return 0ではコンパイルが通らない) */
}

void test(char* hiki)
{
  char* i;
  i = (char*)malloc(sizeof(char) * strlen(hiki));
  /* i = (char*)malloc(strlen(hiki)); でも動きますが、 */
  /* sizeof(char)を入れておいたほうが個人的には良いと思います */

  /* 適当な処理 */

  free(i);
}
    • good
    • 0
この回答へのお礼

回答下さりありがとうございました。
細かなとこまで教えていただき、とても勉強になりました。
ありがとうございました。

お礼日時:2001/10/23 12:24

補足です。



void test(char* hiki)
{
  char* i;
  i = (char*)malloc(sizeof(char) * (strlen(hiki)+1));

  strcpy(i, hiki);

  free(i);
}

のように、iに割り当てる配列の大きさは、strlen(hiki)よりも
最低でも1だけ大きくないといけません。お持ちのCのテキストの
どこかに書いてあると思いますが、文字列には終端記号が最後につきます。
例えば、"ABC"という文字列は、配列内では
  65 66 67 0
という形で4バイトの領域を使って保存されています。
また、strlen("ABC")は、4ではなく3を返す(終端文字は考慮しない)
ので、strlen()を使ってmalloc()する時には注意が必要です。

あと、細かいことですが、文字列を読み込むだけなら、
scanf()よりもfgets()がお勧めです。scanf("%s", inp)は、
inpが何バイトの領域を持った配列かを考慮しないので、
256バイト以上読み込んでしまって、セグメントエラーに
なる可能性があります。

  fgets(inp, 256, stdin);

とやることで、fgets()は256バイトよりも1バイトだけ
少ない(終端文字の分)文字をstdin(標準入力)から受け取って、
inpに格納し、最後に終端文字0をつけてくれます。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QC言語のプログラムで#includeを使わず#includeだけで

C言語のプログラムで#include<math.h>を使わず#include<stdio.h>だけで√(sqrt)を表現することは可能でしょうか?

Aベストアンサー

ご自分で sqrt 関数を作れば可能です。
こんな感じでしょうか。

#include <stdio.h>

static double
sqrt (double s)
{
 double x = s / 2.0;
 double last_x = 0.0;

 while (x != last_x)
 {
  last_x = x;
  x = (x + s / x) / 2.0;
 }

 return (x);
}

int
main (int argc, char * argv[])
{
 printf ("sqrt (%f) = %f\n", 3.0, sqrt (3.0));
}

Qchar *str; と char* str;

char *str; と char* str;
どっちも同じことを意味しているんですか?

Aベストアンサー

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染むのでしょう。ちなみにそういう風な人たちは

char *str1, *str2;

とは、書けない体になっています。

char* str1;
char* str2;


変数の宣言だと、C に慣れていれば、char* str というのはちょっと違和感があるのは
私も分かりますが、関数のプロトタイプ宣言だと、どちらの方がすっきりしますか?

extern char *memcpy(char *, const char *);

extern char* memcpy(char*, const char*);


# まあ、どっちが正しい、っていうんじゃ無いんですよね

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染む...続きを読む

QC言語でgetchar();が上手く使えずに困っています‼ void input(char *cx,

C言語でgetchar();が上手く使えずに困っています‼

void input(char *cx, char *cy){
int i,x,y;
printf("x=");
*cx = getchar();
if(*cx != 'q'){
for(i = 0; i < 5; i++)
if(*cx == '0' + i)x = i;
}

printf("¥ny=");
*cy = getchar();
if(*cy != 'q'){
for(i = 0; i < 5; i++)
if(*cy == '5' + i)y = i;
}
}

という関数で、一度目は上手く行くのですが、二度目の実行で*cy = getchar();が行われません。
cx,cyは、関数を呼び出す前に'9'を代入しています。

実行されない原因と改善策を教えて下さい‼

C言語でgetchar();が上手く使えずに困っています‼

void input(char *cx, char *cy){
int i,x,y;
printf("x=");
*cx = getchar();
if(*cx != 'q'){
for(i = 0; i < 5; i++)
if(*cx == '0' + i)x = i;
}

printf("¥ny=");
*cy = getchar();
if(*cy != 'q'){
for(i = 0; i < 5; i++)
if(*cy == '5' + i)y = i;
}
}

という関数で、一度目は上手く行くのですが...続きを読む

Aベストアンサー

ついでに言うと、
printf("x=")
のあとで
*cx = getchar();
がキー入力待ちになって見えるのは、たまたまこの時点で標準入力が空だからです。

例えば 432(エンター) と入力したなら、標準入力には
「4」 「3」「2」 「改行」
の4文字が入力され、
*cx = getchar(); で 「4」
*cy = getchar(); で(キー入力待ちにはならずに) 「3」
次に inputが呼ばれたときの
*cx = getchar(); で(キー入力待ちにはならずに) 「2」
*cy = getchar(); で(キー入力待ちにはならずに) 「改行」
となります。

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。

Q#include

#include <stdio.h>の <> の意味と
#include "xxxxx.h"の "" の意味を教えてください。

Aベストアンサー

厳密な定義を、「JIS X3010:2003 - 6.10.2 ソースファイル取り込み」から引用します。

---- 引用ここから ----
制約 #include指令は, 処理系で処理可能なヘッダ又はソースファイルを識別しなければならない。
意味規則 次の形式の前処理指令
    # include <h文字列> 改行
は, 処理系定義の場所を順に探索して, <区切り記号と>区切り記号の間で指定した文字列で一意に決まるヘッダを見つけ, そのヘッダの内容全体でこの指令を置き換える。どのようにして探索の場所を指定するか, またどのようにしてヘッダを識別するかは, 処理系定義とする。
 次の形式
    # include "q文字列" 改行
は, 二つの"区切り文字の間で指定した文字列で一意に決まるソースファイルの内容全体で, この指令を置き換える。指定したソースファイルの探索順序は処理系定義とする。この探索をサポートしていない場合, 又は探索が失敗した場合, 同じ文字列(もしあれば>文字を含めて)を含む次の知れに読み替えたのと同じ規則で再処理する。
    # include <h文字列> 改行
---- 引用ここまで ----

要するに、<xxx>の場合は処理系定義のヘッダ(ファイルとは限らない)を取り込み、"xxx"の場合はソースファイルを取り込むということです。いずれも探索場所やその順序は処理系定義です。

よくある誤解は、
・ヘッダは必ずファイルである。
・"xxx"ではカレントディレクトリや取り込もうとしたファイルと同じディレクトリから探索を始める。
といったものです。このように実装されている処理系が多いことは確かですが、標準規格ではそのような規定はありません。
使用している処理系がどのような実装になっているかは、マニュアルに記載があるかと思います。

厳密な定義を、「JIS X3010:2003 - 6.10.2 ソースファイル取り込み」から引用します。

---- 引用ここから ----
制約 #include指令は, 処理系で処理可能なヘッダ又はソースファイルを識別しなければならない。
意味規則 次の形式の前処理指令
    # include <h文字列> 改行
は, 処理系定義の場所を順に探索して, <区切り記号と>区切り記号の間で指定した文字列で一意に決まるヘッダを見つけ, そのヘッダの内容全体でこの指令を置き換える。どのようにして探索の場所を指定するか, またどのようにして...続きを読む


人気Q&Aランキング

おすすめ情報