2

I am using the code below to take in user input and then compare it with the string exit so that users can exit out of a game by typing that into the command line. However it doesn't work unless I use *buffer in the comparison with exit. It does that because it points to the first letter in exit. The problem is that means any word starting with e will cause my while loop to exit.

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

int input( char *s, int length);

int main(){

    char *buffer;
    size_t bufsize = 32;
    size_t characters;

    do{
        buffer = (char *)malloc(bufsize * sizeof(char));

        if(buffer == NULL){
            perror("Unable to allocate buffer");
            exit(1);
        }

        printf("Enter a command: ");
        characters = getline(&buffer, &bufsize, stdin);
        printf("%zu characters were read.\n", characters);
        printf("You typed: '%s' \n",buffer);

    }while(buffer != "exit");
}
hmofrad
  • 1,784
  • 2
  • 22
  • 28
  • `buffer != "exit"` -> `(strcmp(buffer, "exit"))`. Please use a search engine to look up 1. why you should now cast the return value of `malloc()` 2. How to declare the `main()` function properly. – babon Jan 21 '17 at 04:26
  • `getline()` stores the newline in the buffer, so you'll need to either include that in your comparison string, or chomp it off. – Dolda2000 Jan 21 '17 at 04:37
  • Thanks for pointing that out @Dolda2000 – babon Jan 21 '17 at 04:41
  • Possible duplicate of [How do I properly compare strings in C?](http://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c) – Govind Parmar Jan 21 '17 at 07:16

3 Answers3

1

buffer != "exit" -> (strcmp(buffer, "exit\n"))

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
Nazzu
  • 21
  • 1
  • 4
0

Replace

while(buffer != "exit");

with

while(strcmpi(buffer, "exit"));

In C, you can't check logical equality of string with == or != operators. You need to use functions like 'strcmp' or strcmpi.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
VHS
  • 9,534
  • 3
  • 19
  • 43
0

If you compare strings with ==, you are only comparing the base address of the strings, and not the actual contents of the strings. Use strcmp from <string.h> to compare strings. You while statement should be this instead:

while (strcmp(buffer, "exit"));

Note: You should also compile with -Wall -Wextra in your code, and you would have seen some warnings with using == to compare strings.

However, since getline appends a \n at the end of the buffer, similarily to fgets, you might need to remove this \n character. This would allow your code to work as intended. Otherwise, your code is actually doing this:

while (strcmp("exit\n", "exit"));

which will not allow the loop to terminate when "exit" is found, as strcmp() only returns 0 for equal strings.

You also need to check errors with getline(), as it returns -1 on failure to read a line. Their is also no need to allocate memory with malloc() in this case, as getline() stores the address of the buffer within *buffer. The function getline() basically allocates memory for you, so doing it yourself in this case would be redundant. Having said this, you do need to free()this buffer at some point. See this man page for more details.

Considering these points, you can construct your code like this:

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

int main(void ){
    char *buffer = NULL;
    size_t buffsize;
    ssize_t read = 0;
    const char *exits = "exit";

    while (1) {
        printf("Enter a command: ");

        read = getline(&buffer, &buffsize, stdin);
        if (read == -1) {
            printf("Failure found from getline()\n");
            exit(EXIT_FAILURE);
        }

        if (read > 0 && buffer[read-1] == '\n') {
            buffer[read-1] = '\0';
        }

        if (!*buffer || strcmp(buffer, exits) == 0) {
            break;
        }

        printf("%zu characters were read.\n", read);
        printf("You typed: '%s' \n", buffer);

        free(buffer);
        buffer = NULL;
    }

    return 0;
}
RoadRunner
  • 25,803
  • 6
  • 42
  • 75