Q:

How to make wc accept a pipe file to take input from instead of stdin?

This is a homework problem. The task is to replicate the command: ls | wc -l in a C program using execlp, fork, and pipes.
My Approach
I think the problem can be solved this way:

Create a pipe file: pipe.txt
Create a child process using fork()

Map the stdout of the child process to pipe.txt
Execute ls using execlp
This puts the output of ls into pipe.txt

Inside of parent process

Map the stdin of the parent process to pipe.txt
Execute wc -l using execlp without giving any further arguments so it reads from stdin instead
Since the stdout of this parent process is still the terminal itself, so it should print out the number of lines on the terminal

My Code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <sys/wait.h>

int main() {
        int pipefds[2];
        int returnstatus;
        int pid;

        char argArr[30] = {'\n'};

        returnstatus = pipe(pipefds);
        if (returnstatus == -1) {
                printf("Unable to create pipe\n");
                return 1;
        }

        int file_desc = open("pipe.txt", O_RDWR | O_APPEND | O_CREAT); 

        pid = fork();

        if (pid == 0) {
                int copy_desc = dup2(file_desc, 1);
                execlp("ls", "ls", NULL);
        } else {
                int copy_desc = dup2(file_desc, 0);
                close(copy_desc);
                execlp("wc", "wc", "-l", NULL);
        }
        return 0;
}

Actual Output
main.cpp blabla.cpp main pipe.txt
>

Problems
Two things that are wrong with this:

Since I set the stdout of the child to be the pipe.txt file, why does it still output on the terminal? NOTE: It does put the output in the pipe.txt file too. But why does it display on the terminal too?
It starts waiting for the user to provide the input? Shouldn't it get the input from pipe file instead of the user?

Expected Output
5

*if there are 5 files in the current directory
Tried Solutions

Using just the pipe: (Got a bad file descriptor error)

int main() {
        int pipefds[2];
        int returnstatus;
        int pid;

        returnstatus = pipe(pipefds);
        if (returnstatus == -1) {
                printf("Unable to create pipe\n");
                return 1;
        }

        pid = fork();

        if (pid == 0) {
                dup2(pipefds[0], 1);
                close(pipefds[1]);
                execlp("ls", "ls", NULL);
        } else {
                dup2(pipefds[1], 0);
                close(pipefds[0]);
                execlp("wc", "wc", "-l", NULL);
        }
        return 0;
}

A:

Thanks for the helpful comments.
The problem in the code is that I am not using pipes at all. I was doing all my work with a file that I created. So that was the basic problem.
Here's the new code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <sys/wait.h>

int main() {
    // Step1. Create pipe file descriptors: pipefd[0] for reading from pipe, pipefd[1] for writing to the pipe
    int pipefds[2];

    // Helping variables
    int returnstatus;
    int pid;

    // Step2. Create a pipe with the file descriptors
    returnstatus = pipe(pipefds);

    // Check if pipe was successfully created
    if (returnstatus == -1) {
        printf("Unable to create pipe\n");
        return 1;
    }

    // Step3. Fork to create a child process
    pid = fork();

    if (pid == 0) {
        // Inside the child process

        // Step4. Duplicate the file descriptor of the write end of the pipe and set it equal to the stdout of the process 
        dup2(pipefds[1], 1);

        // Step5. Close both ends of the pipe
        close(pipefds[0]);
        close(pipefds[1]);

        // Step6. Execute the LS command. It ouputs to stdout which we set equal to the pipe in Step4.
        // So essentially, we send all output of ls to our pipe 
        returnstatus = execlp("ls", "ls", NULL);

        // Error checking the execlp command
        if (returnstatus == -1){
            perror("Error executing execlp: ");
        }
    } else {
        // Inside the parent process

        // Step7. Duplicate the file descriptor the READ end of the pipe and set it equal to the stdin of the process
        dup2(pipefds[0], 0);

        // Step8. Close the both ends of the pipe
        close(pipefds[0]);
        close(pipefds[1]);

        // Step9. Execute the WC command. It takes the file as an argument usually but if no file is given, it will take
        // stdin as input. Since the stdin is the pipe, therefore it will read all the data from the pipe.
        // The output of the wc command is stdout which is the terminal for this process so we will get the number of
        // files/directories in the current directory as an output on the terminal
        returnstatus = execlp("wc", "wc", "-l", NULL);

        // Error checking the execlp command
        if (returnstatus == -1){
            perror("Error executing execlp: ");
        }
    }
    return 0;
}

