-2

I defined a function, but when I call it I get an error message that says:

*undefined reference to `only_digits'
clang: error: linker command failed with exit code 1 (use -v to see invocation)*

The code is:

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

bool only_digits(string s);

int main(int argc, string argv[])
{
    if(argc > 2)
    {
       printf("Usage: ./caesar key\n");
    }
    bool only_digits(string s);
         for(int i = 0, n = strlen(argv[1]); i<n; i++)
            if((argv[1])[i]<='z' && (argv[1])[i]>'A')
            {
               return false;
            }

            else
            {
               return true;
            }
     bool z = only_digits(argv[1]);
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Renato2022
  • 11
  • 1
  • 5
    Renato2022, "I defined a function," --> No. there is no _definition_, only 2 _declarations_: `bool only_digits(string s);`. Where do you think is a definition of the funciton? – chux - Reinstate Monica Jul 28 '22 at 02:51
  • 1
    In order to use the function `only_digits`, you must define the function somewhere. Declaring the function is not sufficient, even if you do it multiple times. Or do you expect a function by that name to be provided by the CS50 library? – Andreas Wenzel Jul 28 '22 at 02:53
  • 1
    Renato2022, Also: `for(int i = 0, n = strlen(argv[1]); i – chux - Reinstate Monica Jul 28 '22 at 02:53
  • `#include ` – Alexander Jul 28 '22 at 02:57
  • @Alexander: You are right that `#include ` is missing (unless `cs50.h` is guaranteed to include that header, of which I am not sure). However, I do not believe that the missing header can cause the error message that OP posted. – Andreas Wenzel Jul 28 '22 at 03:00
  • @AndreasWenzel I didn't say it did. It was meant to be a reminder that the header was missing. If I thought it answered the question I would have posted it as an answer – Alexander Jul 28 '22 at 03:06
  • @Alexander: Yes, that is what I thought. However, I doubt that this was obvious to everyone, including the OP. In future, you may want to prefix your comment with "Just as a side note:" or at least with "Side note:" or something similar to make clear that the comment does not address the actual question. Otherwise, the OP might misunderstand your comment as a solution to the problem. – Andreas Wenzel Jul 28 '22 at 03:12
  • You may want to consider using the function [`isdigit`](https://en.cppreference.com/w/c/string/byte/isdigit). – Andreas Wenzel Jul 28 '22 at 03:55

3 Answers3

1

Putting the function definition ahead of its use (in same compilation unit) means the function prototype is not required.

bool only_digits( string s ) {
    while( isdigit( (uint8_t) *s ) )
        s++;

    return *s == '\0'; // all chars passed inspection.
}

The OP version would have passed NULL to the function if the user ran the program with no arguments.

int main( int argc, string argv[] ) {

    // Test for what is wanted/needed; two and only two arguments.
    if( argc != 2 ) {
        printf( "Usage: ./caesar key\n" );
        return -1;
    }

    if( only_digits( argv[ 1 ] ) )
        printf( "Only digits\n" );
    else
        printf( "Mixed\n" );

    return 0;
}
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
0

There are several problems with your code:

  1. You seem to try to define the function only_digits() within the function main(). That's not how it works. You need to define (i.e. provide the body of) the function outside of main(). That's the reason for the linker error you're getting.

  2. Unlike python, in C we define a block by enclosing it in { } braces, not by indentation.

  3. The body of your only_digits() function should use the s parameter, then you pass argv[1] (or any other string) when you call that function.

  4. The logic where you're checking for only digits is incorrect. You should return true only after you've checked all characters, i.e. after the loop.

Here's a reworked version:

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

bool only_digits(string s)
{
    for(int i = 0, n = strlen(s); i<n; i++)
    {
        if(s[i]<='z' && s[i]>'A')
        {
            return false;
        }
    }
    return true;
}

int main(int argc, string argv[])
{
    if(argc > 2)
    {
       printf("Usage: ./caesar key\n");
    }

    bool z = only_digits(argv[1]);
}

Also, please note that your only_digits() function doesn't really check if the string contains only digits. It only checks if there are any letters in the string. If there are any symbols like + or -, it will still return true.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
pdp8
  • 206
  • 1
  • 6
  • 2
    Q: What happens if the string is "AAAA"? – paulsm4 Jul 28 '22 at 03:35
  • 3
    @pauslm4 Good point, the check should be >='A'. Of course, the entire logic is not exactly suited for what it's supposed to do (based on the function name). Really it should check if the characters are digits, not if they are non-letters. But that's not what this question is about. – pdp8 Jul 28 '22 at 03:46
  • 1
    It would probably be best to replace `if(s[i]<='z' && s[i]>'A')` with `if ( isdigit( (unsigned char)s[i] ) )`, especially since `ctype.h` has already been included. See the function [`isdigit`](https://en.cppreference.com/w/c/string/byte/isdigit) for further information. – Andreas Wenzel Jul 28 '22 at 03:54
0

Nested function defination is not looks like what you write, it should be:

// On my machine I haven't got the cs50 course lib, so here I
// didn't include that header, and I need include the stdbool.h
// also my environment doesn't support string type in c, so I
// use char * instead
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

int main(int argc, char **argv)
{
    if (argc > 2)
    {
        printf("Usage: ./caesar key\n");
    }

    bool only_digits(char *s)
    {
        for (int i = 0, n = strlen(argv[1]); i < n; i++)
            if ((argv[1])[i] <= 'z' && (argv[1])[i] > 'A')
            {
                return false;
            }

            else
            {
                return true;
            }
    }

    bool z = only_digits(argv[1]);

    printf("result: %d\n", z);
}

On my environment (Ubuntu20.04), compiling result and executing result is:Screen Shot

❯❯❯ gcc main.c -o nested

❯❯❯ ./nested a

result: 0

❯❯❯ ./nested 1

result: 1

Note that nested defination is GNU C EXTENTION but not ANSI C. So it may not work on your system.

g11de
  • 74
  • 5