paizaラーニングレベルアップ問題集の【文字列処理メニュー】をCでやってみた。

paizaラーニングレベルアップ問題集の【文字列処理メニュー】をC言語でやってみました。**但し、最初の18問は、各問題最低1個は`<string.h>`を封印したコードを掲載しています。**
- - -
#### BASIC
##### [文字列の出力](https://paiza.jp/works/mondai/string_primer/basic_step1)
```c
#include <stdio.h>

int main() {
	puts("paiza");
	return 0;
}
```
他の言語は[コチラ](https://qiita.com/anonymously115/items/7b93c7ce4bc12e1582a4)。
- - -
##### [文字列の受け取り](https://paiza.jp/works/mondai/string_primer/basic_step2)
Perlっぽく。
```c
#include <stdio.h>

char* chomp(char *s) {
	char *p = s;
	while (*p) p++;
	while (p-- > s) if (*p == '\n') *p = '\0'; else break;
	return s;
}

int main() {
	char s[102];
	puts(chomp(fgets(s, sizeof(s), stdin)));
	return 0;
}
```
他の言語は[コチラ](https://qiita.com/anonymously115/items/50ed25f7748f1cb1b426)
- - -
##### [i文字目の出力](https://paiza.jp/works/mondai/string_primer/basic_step3)
$S$の文字数の条件がありませんが、仮に100としています。
```c
#include <stdio.h>

int main() {
	char s[101];
	scanf("%s", s);
	int i;
	scanf("%d", &i);
	putchar(s[i-1]);
	return 0;
}
```
- - -
##### [文字列の条件判定](https://paiza.jp/works/mondai/string_primer/basic_step4)
###### `<string.h>`不使用
```c
#include <stdio.h>

const char *str = "paiza";

int main() {
	char s[101];
	scanf("%s", s);
	int i = 0;
	while (s[i] && str[i]) {
		if (s[i] != str[i]) break;
		i++;
	}
	puts(s[i] == str[i] ? "YES" : "NO");
	return 0;
}
```
- - -
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[101];
	scanf("%s", s);
	puts(strcmp(s, "paiza") == 0 ? "YES" : "NO");
	return 0;
}
```
他の言語は[コチラ](https://qiita.com/anonymously115/items/222e07750c4dfae1aa07)
- - -
##### [文字列の文字数](https://paiza.jp/works/mondai/string_primer/basic_step5)
###### `<string.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int len = 0;
	for (char *c = s; *c; c++) {
		len++;
	}
	printf("%d\n", len);
	return 0;
}
```
- - -
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[10001];
	scanf("%s", s);
	printf("%d\n", (int) strlen(s));
	return 0;
}
```
他の言語でも`len`関数や`length`メソッド等があります。
- - -
##### [文字の検索](https://paiza.jp/works/mondai/string_primer/basic_step6)
###### `<string.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s\n", s); // \nを入れないと次で改行コードを拾ってしまう
	char c;
	scanf("%c", &c);
	for (int i = 0; s[i]; i++) {
		if (s[i] == c) {
			printf("%d\n", i + 1);
			break;
		}
	}
	return 0;
}
```
- - -
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[10002];
	fgets(s, sizeof(s), stdin);
	char c = (char) getchar();
	printf("%d\n", (int) (strchr(s, c) - s) + 1);
	return 0;
}
```
- - -
##### [文字列の連結](https://paiza.jp/works/mondai/string_primer/basic_step7)
###### `<string.h>`不使用
```c
#include <stdio.h>

int main() {
	int n;
	scanf("%d", &n);
	char t[1000001] = "";
	char *p = t;
	for (int i = 0; i < n; i++) {
		char s[10001];
		scanf("%s", s);
		char *c = s;
		while (*c) *p++ = *c++;
	}
	puts(t);
	return 0;
}
```
- - -
###### `<string.h>`不使用2
`sprintf`関数の返却値と、アドレス演算を利用して、
他の言語と同様に`+=`を使って連結してみました。
```c
#include <stdio.h>

int main() {
	int n;
	scanf("%d", &n);
	char t[1000001] = "";
	char *p = t;
	for (int i = 0; i < n; i++) {
		char s[10001];
		scanf("%s", s);
		p += sprintf(p, "%s", s);
	}
	puts(t);
	return 0;
}
```
- - -
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	int n;
	scanf("%d", &n);
	char t[1000001] = "";
	for (int i = 0; i < n; i++) {
		char s[10001];
		scanf("%s", s);
		strcat(t, s);
	}
	puts(t);
	return 0;
}
```
他の言語では、`String`クラスの文字列を`+=`演算子で結合するよりも、`stringstream`や`StringBuffer`クラスを用いた方がベターでしょう。
- - -
#### NORMAL
##### [部分文字列](https://paiza.jp/works/mondai/string_primer/normal_step1)
###### `<string.h>`不使用1
1文字ずつ出力します。
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int i, j;
	scanf("%d %d", &i, &j);
	i--;
	for (; i < j; i++) putchar(s[i]);
	puts("");
	return 0;
}
```
- - -
###### `<string.h>`不使用2
ポインタを用います。
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int i, j;
	scanf("%d %d", &i, &j);
	i--;
	char t[j-i+1];
	char *p = t;
	for (; i < j; i++) *p++ = s[i];
	*p = '\0';
	puts(t);
	return 0;
}
```
- - -
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int i, j;
	scanf("%d %d", &i, &j);
	i--;
	char t[j-i+1];
	strncpy(t, s+i, j-i);
	t[j-i] = '\0';
	puts(t);
	return 0;
}
```
他の言語は[コチラ](https://qiita.com/anonymously115/items/f80c559106f6e5fdd1fa)が参考になると思います。
- - -
##### [文字列の挿入](https://paiza.jp/works/mondai/string_primer/normal_step2)
###### `<string.h>`不使用1
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	char t[10001];
	scanf("%s", t);
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) putchar(s[i]);
	printf("%s", t);
	for (char* c = s + n; *c; c++) putchar(*c);
	return 0;
}
```
###### `<string.h>`不使用2
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	char t[10001];
	scanf("%s", t);
	int n;
	scanf("%d", &n);
	char u[20001] = "";
	char *p = u;
	for (int i = 0; i < n; i++) *p++ = s[i];
	char *c = t;
	while (*c) *p++ = *c++;
	c = s + n;
	while (*c) *p++ = *c++;
	*p = '\0';
	puts(u);
	return 0;
}
```
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[10001];
	scanf("%s", s);
	char t[10001];
	scanf("%s", t);
	int n;
	scanf("%d", &n);
	char u[20001] = "";
	strncpy(u, s, n);
	strcat(u, t);
	strcat(u, s + n);
	puts(u);
	return 0;
}
```
- - -
##### [文字列の書き換え](https://paiza.jp/works/mondai/string_primer/normal_step3)
```c
#include <stdio.h>

int main() {
	char s[101];
	scanf("%s", s);
	int i;
	char c;
	scanf("%d %c", &i, &c);
	s[i-1] = c;
	puts(s);
	return 0;
}
```
- - -
- Javaでは受け取った文字列を`toCharArray`する必要があります
```java
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		char[] s = sc.next().toCharArray();
		int i = sc.nextInt() - 1;
		char c = sc.next().charAt(0);
		s[i] = c;
		System.out.println(new String(s));
		sc.close();
	}
}
```
- - -
- Pythonでは受け取った文字列を`list`に変換する必要があります
```py
s = list(input())
i, c = input().split()
i = int(i) - 1
s[i] = c
print(''.join(s))
```
- - -
##### [文字列から数値への変換](https://paiza.jp/works/mondai/string_primer/normal_step4)
###### `<stdlib.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[9];
	scanf("%s", s);
	int n = 0;
	for (char *c = s; *c; c++) n = 10 * n + (*c - '0');
	printf("%d\n", n - 813);
	return 0;
}
```
###### `<stdlib.h>`使用
```c
#include <stdio.h>
#include <stdlib.h>

int main() {
	char s[9];
	scanf("%s", s);
	int n = atoi(s);
	printf("%d\n", n - 813);
	return 0;
}
```
- - -
##### [数値から文字列への変換](https://paiza.jp/works/mondai/string_primer/normal_step5)
```c
#include <stdio.h>

int main() {
	long long x;
	scanf("%lld", &x);
	long long y;
	scanf("%lld", &y);
	int n;
	scanf("%d", &n);
	char s[13];
	sprintf(s, "%lld", x + y);
	putchar(s[n-1]);
	puts("");
	return 0;
}
```
- - -
##### [大文字から小文字への変換](https://paiza.jp/works/mondai/string_primer/normal_step6)
###### `<ctype.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if ('A' <= *c && *c <= 'Z')
			*c = *c - 'A' + 'a';
	puts(s);
	return 0;
}
```
###### `<ctype.h>`使用
```c
#include <stdio.h>
#include <ctype.h>

int main() {
	char s[10001];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if (isupper(*c))
			*c = tolower(*c);
	puts(s);
	return 0;
}
```
- - -
##### [小文字から大文字への変換](https://paiza.jp/works/mondai/string_primer/normal_step7)
###### `<ctype.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[10001];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if ('a' <= *c && *c <= 'z')
			*c = *c - 'a' + 'A';
	puts(s);
	return 0;
}
```
###### `<ctype.h>`使用
```c
#include <stdio.h>
#include <ctype.h>

int main() {
	char s[10001];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if (islower(*c))
			*c = toupper(*c);
	puts(s);
	return 0;
}
```
- - -
##### [大文字小文字の反転](https://paiza.jp/works/mondai/string_primer/normal_step8)
###### `<ctype.h>`不使用
```c
#include <stdio.h>

int main() {
	char s[101];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if ('A' <= *c && *c <= 'Z')
			*c = *c - 'A' + 'a';
		else if ('a' <= *c && *c <= 'z')
			*c = *c - 'a' + 'A';
	puts(s);
	return 0;
}
```
###### `<ctype.h>`使用
```c
#include <stdio.h>
#include <ctype.h>

int main() {
	char s[10001];
	scanf("%s", s);
	for (char *c = s; *c; c++)
		if (isupper(*c))
			*c = tolower(*c);
		else if (islower(*c))
			*c = toupper(*c);
	puts(s);
	return 0;
}
```
- - -
##### [文字列の検索](https://paiza.jp/works/mondai/string_primer/normal_step9)
###### `<string.h>`不使用
```c
#include <stdio.h>

char* find(const char *s, const char *t) {
	for (const char *p = s;; p++) {
		if (*p) {
			for (int i = 0;; i++) {
				if (t[i]) {
					if (!p[i]) return NULL;
					if (p[i] != t[i]) break;
				} else {
					return (char*) p;
				}
			}
		} else {
			return NULL;
		}
	}
}

int main() {
	char s[101];
	scanf("%s", s);
	char t[101];
	scanf("%s", t);
	puts(find(s, t) ? "YES" : "NO");
	return 0;
}
```
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[101];
	scanf("%s", s);
	char t[101];
	scanf("%s", t);
	puts(strstr(s, t) ? "YES" : "NO");
	return 0;
}
```
- - -
##### [文字列の反転](https://paiza.jp/works/mondai/string_primer/normal_step10)
```c
#include <stdio.h>

int main() {
	char s[1001];
	scanf("%s", s);
	char *p = s;
	while (*p) p++;
	char t[1001] = "";
	char *q = t;
	while (p > s) *q++ = *(--p);
	puts(t);
	return 0;
}
```
- - -
##### [回文判定](https://paiza.jp/works/mondai/string_primer/normal_step11)
```c
#include <stdio.h>

int is_palindrome(const char* s) {
	const char *p = s;
	while (*p) p++;
	const char *q = s;
	while(q < --p) if (*q++ != *p) return 0;
	return 1;
}

int main() {
	char s[1001];
	scanf("%s", s);
	puts(is_palindrome(s) ? "YES" : "NO");
	return 0;
}
```
前問の反転文字列を用いて比較する方法もあります。
- - -
#### ADVANCE
##### [文字列の分割](https://paiza.jp/works/mondai/string_primer/advance_step1)
分割した文字列を文字列の配列に格納することは省略します。
###### `<string.h>`不使用1
```c
#include <stdio.h>

int main() {
	char s[101];
	scanf("%s", s);
	char t[101];
	char *q = t;
	for (char *p = s; *p; p++) {
		if (*p == ',') {
			*q = '\0';
			puts(t);
			q = t;
		} else {
			*q++ = *p;
		}
	}
	*q = '\0';
	puts(t);
	return 0;
}
```
###### `<string.h>`不使用2
```c
#include <stdio.h>

int main() {
	char s[101];
	scanf("%s", s);
	for (char *p = s; *p; p++) {
		if (*p == ',') {
			*p = '\n';
		}
	}
	puts(s);
	return 0;
}
```
###### `<string.h>`使用
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[101];
	scanf("%s", s);
	char* t = strtok(s, ",");
	while (t) {
		puts(t);
		t = strtok(NULL, ",");
	}
	return 0;
}
```
- - -
##### [日時データの変換その１](https://paiza.jp/works/mondai/string_primer/advance_step2)
###### 解答例1
```c
#include <stdio.h>

int main() {
	int year, month, day, hour, minute;
	scanf("%d/%d/%d/%d:%d", &year, &month, &day, &hour, &minute);
	printf("%04d\n", year);
	printf("%02d\n", month);
	printf("%02d\n", day);
	printf("%02d\n", hour);
	printf("%02d\n", minute);
	return 0;
}
```
###### 解答例2
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	char datetime[17];
	scanf("%s", datetime);
	printf("%04d\n", atoi(strtok(datetime, "/")));
	printf("%02d\n", atoi(strtok(NULL, "/")));
	printf("%02d\n", atoi(strtok(NULL, "/")));
	printf("%02d\n", atoi(strtok(NULL, ":")));
	printf("%02d\n", atoi(strtok(NULL, "")));
	return 0;
}
```
- - -
##### [日時データの変換その２](https://paiza.jp/works/mondai/string_primer/advance_step3)
###### 解答例1
```c
#include <stdio.h>

int main() {
	int year, month, day, hour, minute;
	scanf("%d/%d/%d %d:%d", &year, &month, &day, &hour, &minute);
	printf("%04d\n", year);
	printf("%02d\n", month);
	printf("%02d\n", day);
	printf("%02d\n", hour);
	printf("%02d\n", minute);
	return 0;
}
```
###### 解答例2
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	char date[11], time[6];
	scanf("%s %s", date, time);
	printf("%04d\n", atoi(strtok(date, "/")));
	printf("%02d\n", atoi(strtok(NULL, "/")));
	printf("%02d\n", atoi(strtok(NULL, "/")));
	printf("%02d\n", atoi(strtok(time, ":")));
	printf("%02d\n", atoi(strtok(NULL, ":")));
	return 0;
}
```
- - -
##### [数値判定](https://paiza.jp/works/mondai/string_primer/advance_step4)
###### `<ctype.h>`不使用
```c
#include <stdio.h>

int is_numeric(const char* s) {
	for (const char *c = s; *c; c++) {
		if (*c < '0' || '9' < *c) return 0;
	}
	return 1;
}

int main() {
	char s[10001];
	scanf("%s", s);
	puts(is_numeric(s) ? "YES" : "NO");
	return 0;
}
```
###### `<ctype.h>`使用
```c
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>

bool is_numeric(const char* s) {
	for (const char *c = s; *c; c++) {
		if (!isdigit(*c)) return false;
	}
	return true;
}

int main() {
	char s[10001];
	scanf("%s", s);
	puts(is_numeric(s) ? "YES" : "NO");
	return 0;
}
```
- - -
##### [重複の削除](https://paiza.jp/works/mondai/string_primer/advance_step5)
###### 解答例1（O(|S|^2)解法）
```c
#include <stdio.h>

int main() {
	char s[1001];
	scanf("%s", s);
	for (int i = 0; s[i]; i++) {
		for (int j = 0; j <= i; j++) {
			if (j == i) putchar(s[i]);
			else if (s[j] == s[i]) break;
		}
	}
	puts("");
	return 0;
}
```
###### 解答例2（O(|S|)解法）
```c
#include <stdio.h>

int main() {
	char s[1001];
	scanf("%s", s);
	int count[10] = {};
	for (char *c = s; *c; c++) {
		int i = (int) (*c - '0');
		if (!count[i]++) putchar(*c);
	}
	puts("");
	return 0;
}
```
- - -
##### [パスワード作成](https://paiza.jp/works/mondai/string_primer/advance_step6)
###### 解答例1
```c
#include <stdio.h>

int main() {
	int N;
	scanf("%d", &N);
	char s[N + 1];
	for (int i = 0; i <= N; i++) s[i] = '\0';
	int Q;
	scanf("%d", &Q);
	for (int q = 0; q < Q; q++) {
		int k;
		char c;
		scanf("%d %c\n", &k, &c);
		s[k - 1] = c;
	}
	char C = (char) getchar();
	for (int i = 0; i < N; i++) if (!s[i]) s[i] = C;
	puts(s);
	return 0;
}
```
###### 解答例2
```c
#include <stdio.h>
#include <string.h>

int main() {
	int N;
	scanf("%d", &N);
	int Q;
	scanf("%d", &Q);
	int A[Q];
	char C[Q];
	for (int q = 0; q < Q; q++)
		scanf("%d %c\n", &A[q], &C[q]);
	char s[N + 1];
	memset(s, getchar(), sizeof(s));
	s[N] = '\0';
	for (int q = 0; q < Q; q++)
		s[A[q] - 1] = C[q];
	puts(s);
	return 0;
}
```
- - -
##### [表記の訂正](https://paiza.jp/works/mondai/string_primer/advance_step7)
###### 方針
1. 正しい小数点の位置を取得する。無い場合は末尾とする
1. （ミス1対応）先頭の0を除去する。但し、小数点の直前の0は残す
1. （ミス3対応）正しくない小数点を除去する
1. （ミス2対応）末尾の不要な0を除去する
1. 末尾が小数点になった場合、除去する
	- 今回は「答えが`.0`の形式になるような値は与えられません」ので不要ですが、一応実装します
- - -
###### 解答例1
```c
#include <stdio.h>

int main() {
	char S[10001];
	scanf("%s", S);
	int n = 0;
	int p = -1;
	while (S[n]) {
		if (S[n] == '.' && p == -1) p = n;
		n++;
	}
	if (p == -1) p = n;

	// miss 1
	int a = 0;
	while (S[a] == '0' && a < p - 1) {
		a++;
	}

	// miss 3
	char T[10001] = "";
	int m = 0;
	int q = -1;
	for (int i = a; i < n; i++) {
		if (S[i] == '.') {
			if (i == p) q = m;
			else continue;
		}
		T[m++] = S[i];
	}
	if (q == -1) q = m;

	// miss 2
	while (m > q && T[m-1] == '0') {
		T[--m] = '\0';
	}
	if (T[m-1] == '.') T[--m] = '\0';

	puts(T);
	return 0;
}
```
- - -
###### 解答例2
```c
#include <stdio.h>
#include <string.h>

int main() {
	char S[10001];
	scanf("%s", S);
	char *p = strchr(S, '.');

	// miss 1
	char *s = S;
	while ((int) (p - s) > 1 && *s == '0') s++;
	
	char T[10001] = "";
	strcpy(T, strtok(s, "."));
	if (p) {
		char *q = T + strlen(T);
		*q = '.';

		// miss 3
		char *t = strtok(NULL, ".");
		while (t) {
			strcat(T, t);
			t = strtok(NULL, ".");
		}

		// miss 2
		char *z = T + strlen(T);
		while (z > q && *(z-1) == '0') *(--z) = '\0';
		if (*(z-1) == '.') *(--z) = '\0';
	}
	
	puts(T);
	return 0;
}
```
- - -
##### [数式の計算（１桁）](https://paiza.jp/works/mondai/string_primer/advance_step8)
```c
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int ans = 0;
	int tmp = 0;
	char op = '+';
	for (char *c = s; *c; c++) {
		if (strchr("+-", *c)) {
			if (op == '+') ans += tmp;
			else if (op == '-') ans -= tmp;
			op = *c;
		} else if (isdigit(*c)) {
			tmp = (int) (*c - '0');
		}
	}
	if (op == '+') ans += tmp;
	else if (op == '-') ans -= tmp;
	printf("%d\n", ans);
	return 0;
}
```
- - -
##### [数式の計算](https://paiza.jp/works/mondai/string_primer/advance_step9)
```c
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
	char s[10001];
	scanf("%s", s);
	int ans = 0;
	int tmp = 0;
	char op = '+';
	for (char *c = s; *c; c++) {
		if (strchr("+-", *c)) {
			if (op == '+') ans += tmp;
			else if (op == '-') ans -= tmp;
			tmp = 0;
			op = *c;
		} else if (isdigit(*c)) {
			int d = (int) (*c - '0');
			tmp = 10 * tmp + d;
		}
	}
	if (op == '+') ans += tmp;
	else if (op == '-') ans -= tmp;
	printf("%d\n", ans);
	return 0;
}
```
- - -
##### [巨大な数の足し算（繰り上がりなし）](https://paiza.jp/works/mondai/string_primer/advance_step10)
今回は
- 全ての桁において繰り上がりが発生しない
- オペランドの桁数が等しい

ので、上位桁から計算します。
```c
#include <stdio.h>

int main() {
	char s[1001];
	scanf("%s", s);
	char t[1001];
	scanf("%s", t);
	char u[1001] = "";
	for (int i = 0; s[i]; i++) {
		// u[i] = (s[i] - '0') + (t[i] - '0') + '0';
		u[i] = s[i] + t[i] - '0'; // s[i]+t[i]でオーバーフローは発生しない
	}
	printf("%s\n", u);
	return 0;
}
```
- - -
##### [巨大な数の足し算](https://paiza.jp/works/mondai/string_primer/advance_step11)
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[1001];
	scanf("%s", s);
	char t[1001];
	scanf("%s", t);
	char u[1002] = "";
	int n = (int) strlen(s);
	int c = 0; // carrying（繰り上がり）
	for (int i = n; i > 0; i--) {
		int d = c + (s[i-1] - '0') + (t[i-1] - '0');
		u[i] = d % 10 + '0';
		c = d / 10;
	}
	u[0] = c + '0';
	char *p = u;
	while (*p && *p == '0') p++;
	puts(p);
	return 0;
}
```
###### 別解（オペランドの桁数が異なっても対応できるように）
```c
#include <stdio.h>
#include <string.h>

int max(int a, int b) {
	return a > b ? a : b;
}

int main() {
	char s[1001];
	scanf("%s", s);
	int n = (int) strlen(s);
	char t[1001];
	scanf("%s", t);
	int m = (int) strlen(t);
	int k = max(n, m);
	char u[1002] = "";
	int c = 0; // carrying（繰り上がり）
	for (int i = 0; i < k; i++) {
		int d = c;
		if (i < n) d += (s[n - i - 1] - '0');
		if (i < m) d += (t[m - i - 1] - '0');
		u[k - i] = d % 10 + '0';
		c = d / 10;
	}
	u[0] = c + '0';
	char *p = u;
	while (*p && *p == '0') p++;
	puts(p);
	return 0;
}
```
- - -
##### [巨大な数のかけ算](https://paiza.jp/works/mondai/string_primer/advance_step12)
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[1001];
	scanf("%s", s);
	int n = (int) strlen(s);
	int t;
	scanf("%d", &t);
	char u[1002] = "";
	int c = 0; // carrying（繰り上がり）
	for (int i = n; i > 0; i--) {
		int d = c + (s[i-1] - '0') * t;
		u[i] = d % 10 + '0';
		c = d / 10;
	}
	u[0] = c + '0';
	char *p = u;
	while (*p && *p == '0') p++;
	puts(p);
	return 0;
}
```
###### 別解（乗数が2桁以上でも対応できるように）
```c
#include <stdio.h>
#include <string.h>

int main() {
	char s[1001];
	scanf("%s", s);
	int n = (int) strlen(s);
	char t[1001];
	scanf("%s", t);
	int m = (int) strlen(t);
	char u[2001] = "";
	memset(u, '0', n + m);
	for (int j = m; j > 0; j--) {
		int c = 0; // carrying（繰り上がり）
		for (int i = n; i > 0; i--) {
			int d = (u[i+j-1] - '0') + c + (s[i-1] - '0') * (t[j-1] - '0');
			u[i+j-1] = d % 10 + '0';
			c = d / 10;
		}
		int k = 1;
		while (c) {
			int d = (u[j-k] - '0') + c;
			u[j-k] = d % 10 + '0';
			c = d / 10;
			k++;
		}
	}
	char *p = u;
	while (*p && *p == '0') p++;
	puts(p);
	return 0;
}
```
- - -
最後の2問は、言語によっては、入力値を`reverse`して計算した結果を`reverse`するのがいいかも。