4

I want to create a program in C that takes an arbitrary number of lines of arbitrary length as input and then prints to console the last line that was inputted. For example:

input:

hi
my name is
david

output: david

I figured the best way to do this would be to have a loop that takes each line as input and stores it in a char array, so at the end of the loop the last line ends up being what is stored in the char array and we can just print that.

I have only had one lecture in C so far so I think I just keep setting things up wrong with my Java/C++ mindset since I have more experience in those languages.

Here is what I have so far but I know that it's nowhere near correct:

#include <stdio.h>

int main()
{
    printf("Enter some lines of strings: \n");

    char line[50];

    for(int i = 0; i < 10; i++){
        line = getline(); //I know this is inproper syntax but I want to do something like this
    }

    printf("%s",line);


}

I also have i < 10 in the loop because I don't know how to find the total number of lines in the input which, would be the proper amount of times to loop this. Also, the input is being put in all at once from the

./program < test.txt 

command in Unix shell, where test.txt has the input.

Barmar
  • 741,623
  • 53
  • 500
  • 612
David -
  • 41
  • 2
  • 4
  • What is "the last line" on a console? Should user press Ctrl-D or so? – Paul Ogilvie Oct 05 '18 at 14:44
  • @PaulOgilvie OP mentions a redirection: ` ./program < test.txt` – Ingo Leonhardt Oct 05 '18 at 14:45
  • 3
    take a look at [fgets](https://linux.die.net/man/3/fgets) – Ingo Leonhardt Oct 05 '18 at 14:46
  • Arbitrary length and non-seekable input means, you need dynamic array to store just he current line (which you then discard if it isn't the last, or print and quit if it is). – hyde Oct 05 '18 at 14:51
  • 2
    If you're on a POSIX-compatible OS (Linux, Unix,...), you can use [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) – Andrew Henle Oct 05 '18 at 14:55
  • You may also wish to consider whether you truly mean arbitrary (i.e., up to the amount of available memory). In practice it is exceedingly unlikely that you would actually need to read lines of text of truly arbitrary length, and supporting arbitrary length may even be harmful as (under certain conditions) it may allow external input to consume an arbitrary amount of memory. Meanwhile if you define a reasonable maximum length (say, some kilobytes), you can probably even allocate it on the stack and read it trivially with `fgets`. – Arkku Oct 05 '18 at 17:08
  • Anyway, the answers of this question (which is in itself not strictly a duplicate) happen to have solutions for both limited and arbitrary input lengths https://stackoverflow.com/questions/52441799/how-to-make-string-function-with-user-input-in-c – Arkku Oct 05 '18 at 17:10

3 Answers3

7

Use fgets():

while (fgets(line, sizeof line, stdin)) {
    // don't need to do anything here
}
printf("%s", line);

You don't need a limit on the number of iterations. At the end of the file, fgets() returns NULL and doesn't modify the buffer, so line will still hold the last line that was read.

Barmar
  • 741,623
  • 53
  • 500
  • 612
2

I'm assuming you know the maximum length of the input line.

This one here will surely do the job for you

static char *getLine( char * const b , size_t bsz ) {
            return fgets(b, bsz, stdin) );
}

But remember fgets also puts a '\n' character at the end of buffer so perhaps something like this

static char *getLine( char * const b , size_t bsz ) {

            if( fgets(b, bsz, stdin) ){
                    /* Optional code to strip NextLine */
                    size_t size = strlen(b);
                    if( size > 0 && b[size-1] == '\n' ) {
                            b[--size] = '\0';
                    }
                    /* End of Optional Code */
                    return b;
            }
            return NULL;
    }

and your code needs to be altered a bit while calling the getline

#define BUF_SIZE 256
char line[BUF_SIZE];

for(int i = 0; i < 10; i++){
    if( getLine(line, BUF_SIZE ) ) {
            fprintf(stdout, "line : '%s'\n", line);
    }

}

Now it is how ever quite possible to create function like

char *getLine();

but then one needs to define the behavior of that function for instance if the function getLine() allocates memory dynamically then you probably need use a free to de-allocate the pointer returned by getLine()

in which case the function may look like

char *getLine( size_t bsz ) {
        char *b = malloc( bsz );
        if( b && fgets(b, bsz, stdin) ){
           return b;
        }
        return NULL;
}

depending on how small your function is you can entertain thoughts about making it inline perhaps that's a little off topic for now.

asio_guy
  • 3,667
  • 2
  • 19
  • 35
0

In order to have dynamic number of input of dynamic length, you have to keep on reallocating your buffer when the input is of greater length. In order to store the last line, you have to take another pointer to keep track of it and to stop the input from the terminal you have to press EOF key(ctrl+k). This should do your job.

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

char *get_last_line(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
    char *str, *last_str = NULL;
    int ch;
    size_t len = 0, last_len = 0;
    str = realloc(NULL, sizeof(char)*size);//size is start size
    if(!str)return str;
    while(ch=fgetc(fp)){
        if(ch == EOF){
            break;
        }
        if(ch == '\n'){
            str[len]='\0';
            last_len = len;
            last_str = realloc(last_str,sizeof(char)*last_len);
            last_str[last_len]='\0';
            //storing the last line
            memcpy(last_str,str,sizeof(char)*last_len);
            str = realloc(NULL, sizeof(char)*size);//size is start size
            len = 0;
        }
        else {
            str[len++]=ch;
            if(len==size){
                str = realloc(str, sizeof(char)*(size+=16));
                if(!str)return str;
            }
        }
    }
    free(str);
    return last_str;
}

int main(void){
    char *m;

    printf("input strings : ");
    m = get_last_line(stdin, 10);
    printf("last string :");
    printf("%s\n", m);
    free(m);
    return 0;
}
Anindya
  • 41
  • 1
  • 13