{ }codelper
dynamic memoryP0075

Keeping the words

The first line gives the number of words n, and each of the next n lines gives one word made only of lowercase English letters.
On the first line print the words in reverse input order, separated by single spaces; on the second line print the longest word.
If several words are equally longest, print the one that came first in the input.
Since n is known only at run time, try storing all the words in memory obtained while running, instead of an array of fixed size (malloc and free in C, std::vector and std::string in C++).

Input
1 ≤ n ≤ 2,000, each word is 1 to 100 letters long
Output
Two lines: the words reversed, the longest word
Example 1 · stdin
4
hi
hello
hey
howdy
stdout
howdy hey hello hi
hello
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 2 languages

This problem accepts only C and C++.
Obtaining and returning memory by hand is the job of those two; Python, JavaScript, TypeScript, Java, C# and Craykon have lists that grow by themselves and a garbage collector that cleans up, so you never write it.
C allocates twice: the pointer slots char **words = malloc(n * sizeof *words), then for each word a copy in malloc(strlen(buf) + 1) (the +1 is room for the terminating '\0').
When done, free every word and then free(words), returning each allocation exactly once.
In C++, std::vector<std::string> handles both (RAII).
Two traps: (1) in C, storing only the address without copying, as in scanf("%100s", buf); words[i] = buf;, makes every slot point at the same buf, so all of them show the last word, with no error.
(2) In C++, std::vector<std::string> words(n); already holds n empty strings, so push_back appends after them and the size becomes 2n.
To only reserve room, use reserve(n) then push_back; otherwise words(n) then words[i] = w.

C++main.cpp · 26 lines
#include <iostream>#include <string>#include <vector> int main() {    std::ios::sync_with_stdio(false);    std::cin.tie(nullptr);    int n;    std::cin >> n;     // vector와 string이 알아서 힙 메모리를 빌리고, 범위를 벗어나면 돌려준다(RAII)    std::vector<std::string> words;    words.reserve(n);  // 칸을 미리 잡아 둘 뿐, 크기(size)는 아직 0    for (int i = 0; i < n; i++) {        std::string w;        std::cin >> w;        words.push_back(w);  // string은 대입·push_back 때 글자를 복사해 둔다    }     for (int i = n - 1; i >= 0; i--) std::cout << words[i] << (i > 0 ? ' ' : '\n');     const std::string* best = &words[0];    for (const auto& w : words)        if (w.size() > best->size()) best = &w;    std::cout << *best << "\n";}
Cmain.c · 33 lines
#include <stdio.h>#include <stdlib.h>#include <string.h> int main(void) {    int n;    scanf("%d", &n);     /* 낱말 수는 실행해 봐야 안다: 낱말을 가리킬 포인터 n칸을 힙에서 빌린다 */    char **words = malloc(n * sizeof *words);    if (words == NULL) return 1;     char buf[101];  /* 읽기용 칸은 하나뿐이라, 낱말마다 따로 복사해 둬야 한다 */    for (int i = 0; i < n; i++) {        scanf("%100s", buf);        size_t len = strlen(buf);        words[i] = malloc(len + 1);  /* +1은 끝을 알리는 '\0' 자리 */        if (words[i] == NULL) return 1;        memcpy(words[i], buf, len + 1);    }     for (int i = n - 1; i >= 0; i--) printf("%s%c", words[i], i > 0 ? ' ' : '\n');     const char *best = words[0];    for (int i = 1; i < n; i++)        if (strlen(words[i]) > strlen(best)) best = words[i];    printf("%s\n", best);     /* 빌린 것은 빌린 만큼 돌려준다: 낱말 하나하나, 그다음 포인터 칸 */    for (int i = 0; i < n; i++) free(words[i]);    free(words);    return 0;}