2

I'm a C noob, going back to school for my masters in CS so I'm taking some time to ramp up my skills. I wanted to see if anybody could lend some assistance on why I'm having problems compiling the following code. I've been following the videos on WiBit.net and develop on a 64 bit Linux environment (Ubuntu 13.10). I am using gedit and the gcc compiler no IDE.

This code runs on my Win 7 VM without errors, however when I try to execute it on my host Linux environment I'm getting errors:

Source Code: This example calls the strcmp and strcmpi functions

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

int main()
{
    char str1[255];
    char str2[255];
    printf("str1: "); gets(str1);
    printf("str2: "); gets(str2);

    if(strcmp(str1, str2) == 0)
        printf("Strings match exactly!");
    else if(strcmpi(str1, str2) == 0)
        printf("Strings match when ignoring case!");    
    return 0;
}

Error Message (Linux ONLY):

$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1 /tmp/ccwqdQMN.o: In function main': main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used. main.c:(.text+0x8f): undefined reference to `strcmpi' collect2: error: ld returned 1 exit status

Source Code 2: This example uses the strupr and strlwr functions

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

int main()
{
    char str1[255];
    char str2[255];
    printf("str1: "); gets(str1);
    printf("str2: "); gets(str2);

    strlwr(str1);
    strupr(str2);
    puts (str1);
    puts (str2);
    return 0;
}

Error Message (Linux ONLY):

$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1 /tmp/ccWnIfnz.o: In function main': main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used. main.c:(.text+0x57): undefined reference to strlwr' main.c:(.text+0x6b): undefined reference tostrupr' collect2: error: ld returned 1 exit status

I would love a detailed explanation if someone is willing to help and not tear me apart haha. I know that for best practices we shouldn't use gets due to buffer overflow (for example the user enters a 750 character string). Best practices would use fgets instead but my question is whether I'm getting these errors because these functions aren't part of ANSI C or what. They do show up in the man files on my machine which is throwing me through a loop.

Thanks in advance!


UPDATE: You guys are awesome. Took all of your advice and comments and was able to revise and make a sample program for string comparison as well as conversion to upper/lower. Glad I was able to get it running on both OSes error free as well.

Sample code:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
    char str[255];
    printf("Enter a string: "); fgets(str,255, stdin);
    printf("Here is your original string, my master: %s\n", str);
    //Now let's loop through and convert this to all lowercase
    int i;
    for(i = 0; str[i]; i++)
    {
        str[i] = tolower(str[i]);
    }
    printf("Here is a lowercase version of your string, my master: %s\n", str);    
    //Now we'll loop through and convert the string to uppercase
    int j;
    for(j = 0; str[j]; j++)
    {
        str[j] = toupper(str[j]);
    }
    printf("Here is a uppercase version of your string, my master: %s\n", str);    
    return 0;
}
bran.io
  • 72
  • 1
  • 9
  • You should probably check out http://www.cplusplus.com/reference/cstring/ for a reference to the standard C string library. –  Dec 09 '13 at 21:12
  • If you're using gcc, you really should use `-Wall` to get warnings about things that are questionable. – Chris Dodd Dec 10 '13 at 04:58
  • Thanks Chris. I was looking into some more of the command line switches for that purpose exactly. It's been about 5 years since I touched C++ and now I'm going back in time to good old C before going back to school. – bran.io Dec 10 '13 at 15:48

2 Answers2

3

strcmpi problem: strcasecmp() is the posix standard and so is it in linux.

strupr and strlwr doesn't exist in glibc, although you can implement them with a single line of code, as this: c - convert a mixed-case string to all lower case

In the compilation, first you can find a warning, because the gcc doesn't find the functions in the included header. In such cases it thinks they are declared as int funcname(void). But later, while linking, it can't find the exported symbols of this nonexistant functions, and thus it can't create the executable. This second error is what stops the compilation.

There are too many difference in the c apis, although the posix standard handles them, microsoft don't follow it.

Community
  • 1
  • 1
peterh
  • 11,875
  • 18
  • 85
  • 108
  • Thanks for the quick follow up! I did some across some posts mentioning writing my own function. I was getting a little frustrated trying to figure out why it was working on Windows (I used MinGW - bare minimum install) and not my linux machine. I appreciate the response. – bran.io Dec 09 '13 at 21:08
  • MingW uses its own c library, not a glibc port. They try to make simpler to port existing msvc code. Glibc people is a more hardcore standard-following style. But these are simple oneline functions (assuming you won't convert nonenglish charsets, although there are good library calls for this, too). – peterh Dec 09 '13 at 21:14
2

As you noted, the gets function is unsafe because it does not perform any boundary checking: you have called it with a 255-character string buffer, but if another program wrote a line longer than 255 characters, it could write data into your process's stack, and thereby cause your process to execute malicious code (or at the very least produce a segmentation fault).

Use fgets instead:

printf("str1: "); fgets(str1, 255, stdin);
printf("str2: "); fgets(str2, 255, stdin);

If you read the error output from the compiler carefully, you'll note that it's not issuing an error on your use of gets but a warning. Your code should still compile and execute if you fix the strcmpi call.

Tim Pierce
  • 5,514
  • 1
  • 15
  • 31
  • Thank you as well. I'm going to try running through a few examples tonight. I don't want to move forward on any additional concepts until I understand this fully. Trying to be as error free as possible haha. – bran.io Dec 09 '13 at 21:12
  • 1
    Note that while the [`gets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html) function is deprecated because it's inherently broken, the [`fgets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) function does have slightly different behavior: It doesn't discard newline (`'\n'`) characters. – This isn't my real name Jan 01 '14 at 17:31