0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プログラミングコンテストとかの標準入力の受け取り方メモ(C言語)

Posted at

プログラミングコンテストとかそういう諸々で標準入力の受け取り方をよく忘れるため、頻繁に使うものをメモしておきます。

paizaラーニングさんの問題集をベースとして一覧化しています。

1つのデータの入力

文字列Sが1行で入力されます。
・Sは1文字以上100文字以下の文字列
・Sの各文字は英小文字または大文字または数字

入力例

abc
1242

取得例

#include <stdio.h>
int main(void){
    char buf[100 + 1];
    fgets(buf, sizeof(buf), stdin);
    printf("%s\n", buf);
    return 0;
}

文字列Sが数値なのであれば、sscanf(buf, "%d", num);で変換します。

1行のデータの入力

文字列Sが1行で入力されます。
・Sは1文字以上100文字以下の文字列
・Sの各文字は英小文字または大文字または数字または半角スペース

入力例

i am alice
3000

取得例

#include <stdio.h>
int main(void){
    char buf[100 + 1];
    fgets(buf, sizeof(buf), stdin);
    printf("%s\n", buf);
    return 0;
}

3行のデータの入力

文字列A, B, Cが各行で入力されます。
・A, B, Cは1文字以上100文字以下の文字列
・A, B, Cの各文字は英小文字または大文字または数字または半角スペース

入力例

alice
bob
curl
this is a pen
that is a watch
and so on

取得例

#include <stdio.h>
int main(void){
    char buf[100 + 1];
    
    for(int i = 0; i < 3; i++) {
        fgets(buf, sizeof(buf), stdin);
        printf("%s", buf);
    }
    return 0;
}

行毎でデータを取得すればよい場合は、楽に処理できました。

N行のデータの入力

1行目でNが与えらます。
続くN行の各行で文字列が与えられます。
・1 <= N <= 10
・入力される各文字列は1文字以上100文字以下の文字列
・入力される各文字列の各文字は英小文字または大文字または数字または半角スペース

入力例

3
good bye
good morning
good evening
4
good
bad
soso
umm

取得例

#include <stdio.h>
int main(void){
    char buf[100 + 1];
    int num;
    
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d", &num);
    
    for(int i = 0; i < num; i++) {
        fgets(buf, sizeof(buf), stdin);
        printf("%s", buf);
    }
    return 0;
}

カウンタ変数に取得した回数を反映させればよいだけなので簡単。

3つのデータの入力

3つの文字列が半角スペース区切りで1行で与えれます。
・入力される各文字列は1文字以上100文字以下の文字列
・入力される各文字列の各文字は英小文字または大文字または数字

入力例

hello hey oi
1 2 3

取得例

#include <string.h>
#include <stdio.h>
int main(void){
    char buf[1000];
    fgets(buf, sizeof(buf), stdin);
    
    char *token;
    int i = 0;
    token = strtok(buf, " ");
    while(token != NULL && i < 3) {
        printf("%s\n", token);
        token = strtok(NULL, " ");
        i++;
    }
    return 0;
}

1行に複数データが格納されている場合は多少厄介というか、調べて出てきた方策をとっています。
strtok()って初めて使いました。

どうやら、strtokはグローバルな状態を保持して、処理をしていくため、複数の文字列に対してstrtokで処理を行うことはできないようです。

たとえば、以下は望んだ動作をしません。

不適切なコード
#include <string.h>
#include <stdio.h>
int main(void){
    char buf1[1000], buf2[1000];
    fgets(buf1, sizeof(buf1), stdin);
    fgets(buf2, sizeof(buf2), stdin);
    
    char *token1, *token2;
    int i = 0;
    token1 = strtok(buf1, " ");
    token2 = strtok(buf2, " ");
    while(token1 != NULL && i < 3) {
        printf("%s\n", token1);
        printf("%s\n", token2);
        token1 = strtok(NULL, " ");
        token2 = strtok(NULL, " ");
        i++;
    }
    return 0;
}

この場合は、strtok_r()を使ってね、ということらしい。

正常に動いた気がするコード

入力は、

a b c
d e f

となっていて、"adbecf"と出力されます。

#define _POSIX_C_SOURCE 200809L
#include <string.h>
#include <stdio.h>

void remove_newline(char *str) {
    char *p = strchr(str, '\n');
    if (p) {
        *p = '\0';
    }
}


int main(void){
    char buf1[1000], buf2[1000];
    fgets(buf1, sizeof(buf1), stdin);
    fgets(buf2, sizeof(buf2), stdin);
    
    remove_newline(buf1);
    remove_newline(buf2);
    
    char *token1, *token2;
    char *save1 = NULL, *save2 = NULL;
    int i = 0;
    token1 = strtok_r(buf1, " ", &save1);
    token2 = strtok_r(buf2, " ", &save2);
    while(token1 != NULL && token2 != NULL && i < 3) {
        printf("%s", token1);
        printf("%s", token2);
        token1 = strtok_r(NULL, " ", &save1);
        token2 = strtok_r(NULL, " ", &save2);
        i++;
    }
    return 0;
}

N個のデータの入力

1行目でNが与えらます。
2行目でN個の文字列が半角スペース区切りで与えれます。
・1 <= N <= 10
・入力される各文字列は1文字以上100文字以下の文字列
・入力される各文字列の各文字は英小文字または大文字または数字

入力例

3
hello hey hi
1
moo

取得例

#include <stdio.h>
#include <string.h>
int main(void){
    char buf[100 + 1];
    int num;
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d", &num);
    
    fgets(buf, sizeof(buf), stdin);
    
    char *token = strtok(buf, " ");
    
    for(int i = 0; i < num; i++) {
        printf("%s\n", token);
        token = strtok(NULL, " ");
    }
    return 0;
}

カンマ区切りの3つのデータの入力

3つの文字列がカンマ区切りで1行で与えられます。
・入力される各文字列は1文字以上100文字以下の文字列
・入力される各文字列の各文字は英小文字または大文字または数字

入力例

abc def ghi
352 fdg 453

取得例

#include <stdio.h>
#include <string.h>
int main(void){
    char buf[100 + 1 * 3];
    fgets(buf, sizeof(buf), stdin);
    
    char *token = strtok(buf, ",");
    int i = 0;
    while(token != NULL && i < 3) {
        printf("%s\n", token);
        token = strtok(NULL, ",");
        i++;
    }
    return 0;
}

カンマ区切りのN個のデータの入力

1行目でNが与えらます。
2行目でN個の文字列がカンマ区切りで与えれます。

入力例

3
hello,bob,alice
5
1 2 alice hello goodbye

取得例

#include <stdio.h>
#include <string.h>
int main(void){
    char buf[100 + 1 * 3];
    int num;
    
    fgets(buf, sizeof(buf), stdin);
    sscanf(buf, "%d", &num);
    
    fgets(buf, sizeof(buf), stdin);

    char *token = strtok(buf, ",");
    int i = 0;
    while(token != NULL && i < num) {
        printf("%s\n", token);
        token = strtok(NULL, ",");
        i++;
    }
    return 0;
}

終わりに

各入力条件の記載は原文ままとなります。
(どうでもいいレベルの誤字脱字がありましたね)

ひとまず、これくらいあれば、簡単な問題であれば入力には困らなそうです。

これから何度も書いていって、少しずつ身につけていきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?